How to Debug LifeOS, Check Logs, and Troubleshoot Setup Issues: A Complete Guide

To debug LifeOS, run individual checks directly from the command line to see console output, then inspect the structured JSON-L logs in the OBSERVABILITY directory for detailed timestamps and error payloads.

LifeOS is a personal knowledge operating system written in TypeScript and executed with Bun. Its debugging architecture is intentionally modular: each component—whether a health check, notification governor, or hook—runs as an isolated script that writes to both stdout and persistent log files. Understanding this dual-output system is essential for effective troubleshooting.

Understanding LifeOS Logging Architecture

LifeOS produces two distinct output channels for every check and hook:

Output Type Location Contents
Console output Standard output/error of the running script Human-readable status messages, NO_ACTION tokens, or stack traces
Structured logs LIFEOS/DIRECTORY/MEMORY/OBSERVABILITY/<check-name>.jsonl Machine-readable JSON-L entries with timestamps, results, and metadata

The OBSERVABILITY directory serves as the central telemetry store. Each check maintains its own .jsonl file, appending one line per execution. This design enables both real-time debugging and historical analysis.

Running Checks Manually for Immediate Feedback

The fastest way to diagnose a problem is to bypass any scheduler and invoke the check directly. LifeOS stores its checks in LifeOS/install/LIFEOS/PULSE/checks/.

Health Check Example

The health.ts script monitors configured websites via HTTP HEAD requests:

bun ./LifeOS/install/LIFEOS/PULSE/checks/health.ts

This outputs either:

  • NO_ACTION — all monitored sites responded successfully
  • A structured failure report with status codes and response times

The source implementation in [LifeOS/install/LIFEOS/PULSE/checks/health.ts](https://github.com/danielmiessler/LifeOS/blob/main/LifeOS/install/LIFEOS/PULSE/checks/health.ts) uses a 10-second default timeout:

const resp = await fetch(site.url, {
  method: "HEAD",
  signal: AbortSignal.timeout(10_000),
  redirect: "follow",
});

To capture this output for later review:

bun ./LifeOS/install/LIFEOS/PULSE/checks/health.ts > health_debug.log 2>&1

Reading Structured Logs in the OBSERVABILITY Directory

For persistent diagnostics, checks write to their respective .jsonl files. The notification-governor.ts script demonstrates this pattern:

import { appendFileSync } from "fs";
import { join } from "path";

const LOG_FILE = join(LIFEOS_DIR, "MEMORY", "OBSERVABILITY", "notification-governor.jsonl");

appendFileSync(
  LOG_FILE,
  JSON.stringify({ ts: new Date().toISOString(), ...entry }) + "\n"
);

View the last 10 entries for any check:

tail -n 10 ./LIFEOS/DIRECTORY/MEMORY/OBSERVABILITY/notification-governor.jsonl | jq .

Pretty-print a specific entry:

import { readFileSync } from "fs";

const logPath = "./LIFEOS/DIRECTORY/MEMORY/OBSERVABILITY/notification-governor.jsonl";
const lines = readFileSync(logPath, "utf-8").trim().split("\n");
const lastEntry = JSON.parse(lines.at(-1)!);

console.log("Last notification event:", JSON.stringify(lastEntry, null, 2));

The full implementation is available at [LifeOS/install/LIFEOS/PULSE/checks/notification-governor.ts](https://github.com/danielmiessler/LifeOS/blob/main/LifeOS/install/LIFEOS/PULSE/checks/notification-governor.ts).

Verifying Environment Configuration

Many LifeOS checks rely on environment variables for customization. Missing or malformed variables often cause silent failures or fallback to defaults with warning emissions.

Key variables include:

  • LIFEOS_PULSE_HEALTH_SITES — comma-separated list of name|url pairs for health monitoring
  • LIFEOS_DIR — base directory path (defaults to ./LIFEOS if unset)

The centralized loader in [LifeOS/Tools/DetectEnv.ts](https://github.com/danielmiessler/LifeOS/blob/main/LifeOS/Tools/DetectEnv.ts) parses these values. Verify your configuration:

export LIFEOS_PULSE_HEALTH_SITES="blog|https://myblog.example.com,api|https://api.example.com"
bun ./LifeOS/install/LIFEOS/PULSE/checks/health.ts

Debugging the Installation Process

The top-level installer supports verbose mode for tracing setup issues. In [LifeOS/install/install.sh](https://github.com/danielmiessler/LifeOS/blob/main/LifeOS/install/install.sh), the -v flag propagates --log-level=debug to all sub-scripts:

./LifeOS/install/install.sh -v

This reveals:

  • Directory creation steps
  • Configuration file parsing
  • Hook registration and execution order

Troubleshooting Hook Failures

Hooks like HookHealer record their activity separately from Pulse checks. The [LifeOS/install/hooks/HookHealer.hook.ts](https://github.com/danielmiessler/LifeOS/blob/main/LifeOS/install/hooks/HookHealer.hook.ts) implementation writes to hook-healer.jsonl:

cat ./LIFEOS/DIRECTORY/MEMORY/OBSERVABILITY/hook-healer.jsonl | jq 'select(.error != null)'

This filters for entries containing error fields, surfacing integration problems that might not appear in console output.

Common Failure Patterns and Resolutions

Symptom Cause Resolution
ECONNRESET or timeout in health check Slow network or unresponsive server Increase timeout: AbortSignal.timeout(30_000)
ENOENT when writing logs Missing OBSERVABILITY directory mkdir -p LIFEOS/DIRECTORY/MEMORY/OBSERVABILITY
Checks report NO_ACTION unexpectedly Missing LIFEOS_PULSE_HEALTH_SITES Export the variable with valid site list
Permission denied on script execution Insufficient filesystem rights chmod -R u+w LIFEOS/ or run as appropriate user
Empty log files despite check execution Log directory path mismatch Verify LIFEOS_DIR matches actual installation path

Adjusting Timeouts for Network Reliability

For unreliable networks, modify the fetch timeout in health.ts:

// Before: 10 second default
const resp = await fetch(site.url, {
  method: "HEAD",
  signal: AbortSignal.timeout(30_000), // Extended to 30 seconds
  redirect: "follow",
});

Test the change immediately:

bun ./LifeOS/install/LIFEOS/PULSE/checks/health.ts

Summary

Effective LifeOS debugging follows a consistent workflow:

  • Run checks directly using bun to capture real-time console output
  • Inspect JSON-L logs in MEMORY/OBSERVABILITY/ for structured historical data
  • Validate environment variables through DetectEnv.ts loading patterns
  • Use verbose installation (-v flag) to trace setup failures
  • Check hook-specific logs separately from Pulse monitor logs
  • Adjust timeouts and permissions based on common failure patterns

Frequently Asked Questions

Where does LifeOS store its log files?

LifeOS writes structured logs to LIFEOS/DIRECTORY/MEMORY/OBSERVABILITY/<component-name>.jsonl. Each check and hook maintains its own file, appending one JSON object per line. Console output from scripts is separate and must be captured manually with shell redirection.

How do I increase the timeout for health checks?

Edit [LifeOS/install/LIFEOS/PULSE/checks/health.ts](https://github.com/danielmiessler/LifeOS/blob/main/LifeOS/install/LIFEOS/PULSE/checks/health.ts) and modify the AbortSignal.timeout() value. The default is 10_000 milliseconds (10 seconds); raise it to 30_000 or higher for slower networks. No restart is required—run the script directly to apply changes.

Why does a check return NO_ACTION when my site is down?

NO_ACTION indicates the check completed without triggering its notification condition. Verify that LIFEOS_PULSE_HEALTH_SITES is exported with the correct name|url format. Also confirm the site URL includes the protocol (https://) and that your network can reach it from the host running LifeOS.

How can I debug hook integration problems?

Examine hook-healer.jsonl in the OBSERVABILITY directory. This file contains timestamps and payloads for each hook invocation. Filter for entries with non-null error fields to identify failures. The hook source in [HookHealer.hook.ts](https://github.com/danielmiessler/LifeOS/blob/main/LifeOS/install/hooks/HookHealer.hook.ts) shows the exact structure of logged events.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →