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

> Debug LifeOS by running command line checks and inspecting OBSERVABILITY logs. This guide helps troubleshoot setup issues with detailed timestamps and error payloads.

- Repository: [Daniel Miessler 🛡️/LifeOS](https://github.com/danielmiessler/LifeOS)
- Tags: how-to-guide
- Published: 2026-08-12

---

**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:

```bash
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)](https://github.com/danielmiessler/LifeOS/blob/main/LifeOS/install/LIFEOS/PULSE/checks/health.ts) uses a 10-second default timeout:

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

```

To capture this output for later review:

```bash
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:

```ts
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:

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

```

Pretty-print a specific entry:

```ts
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)](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)](https://github.com/danielmiessler/LifeOS/blob/main/LifeOS/Tools/DetectEnv.ts) parses these values. Verify your configuration:

```bash
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)](https://github.com/danielmiessler/LifeOS/blob/main/LifeOS/install/install.sh), the `-v` flag propagates `--log-level=debug` to all sub-scripts:

```bash
./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)](https://github.com/danielmiessler/LifeOS/blob/main/LifeOS/install/hooks/HookHealer.hook.ts) implementation writes to `hook-healer.jsonl`:

```bash
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`](https://github.com/danielmiessler/LifeOS/blob/main/health.ts):

```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:

```bash
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`](https://github.com/danielmiessler/LifeOS/blob/main/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)](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/HookHealer.hook.ts)](https://github.com/danielmiessler/LifeOS/blob/main/LifeOS/install/hooks/HookHealer.hook.ts) shows the exact structure of logged events.