Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
224 changes: 202 additions & 22 deletions reference/cli.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,16 @@ Enables and bootstraps every Meridian LaunchAgent, then prints a live status sum
| Label | Service |
|---|---|
| `com.meridiona.screenpipe` | screenpipe ambient recorder |
| `com.meridiona.daemon` | Meridian Rust ETL daemon |
| `com.meridiona.jira-updater` | Jira / GitHub / Linear sync |
| `com.meridiona.daemon` | Meridian Rust ETL daemon (also runs the in-process PM worklog pipeline and the coding-agent indexer) |
| `com.meridiona.ui` | Next.js dashboard at http://localhost:3000 |
| `com.meridiona.mlx-server` | MLX inference server |
| `com.meridiona.coding-agent-indexer` | Coding-agent context indexer |

If any `.plist` file is missing, `meridian start` prints an error for that service and exits with a non-zero code. Run `./install.sh` to reinstall missing plists.

<Note>
The PM worklog (Jira / GitHub / Linear) pipeline and the coding-agent indexer used to ship as their own LaunchAgents (`com.meridiona.jira-updater`, `com.meridiona.coding-agent-indexer`). They now run inside `com.meridiona.daemon`, so `meridian status` only reports the four labels above.
</Note>

<Note>
The Rust daemon TCP-connects to the MLX server at startup to verify it is reachable. If the MLX server is not running, the daemon exits immediately. Start all services together with `meridian start` rather than launching them individually.
</Note>
Expand Down Expand Up @@ -66,7 +68,7 @@ meridian status
Queries launchd for the running state of every registered service and prints a colour-coded summary:

- **✓ running (pid N)** — service is up and has a PID
- **⊘ loaded but not running** — launchd has the plist but the process is not active (e.g. the jira-updater between scheduled slots)
- **⊘ loaded but not running** — launchd has the plist but the process is not active
- **✗ not installed** — plist is missing; run `./install.sh`

Run `meridian status` any time you are unsure whether the stack is up.
Expand All @@ -83,17 +85,18 @@ Tails a log file from `~/.meridian/logs/`. All arguments are optional.

**Valid targets**

Each component has a normal log (everything) and a paired `-error` log (WARN/ERROR only) so you can grep for problems without scrolling past routine output.

| Target | File |
|---|---|
| `daemon` *(default)* | `~/.meridian/logs/daemon.log` |
| `daemon-error` | `~/.meridian/logs/daemon-error.log` |
| `jira-updater` | `~/.meridian/logs/jira-updater.log` |
| `screenpipe` | `~/.meridian/logs/screenpipe.log` |
| `screenpipe-error` | `~/.meridian/logs/screenpipe-error.log` |
| `ui` | `~/.meridian/logs/ui.log` |
| `ui-error` | `~/.meridian/logs/ui-error.log` |
| `mlx-server` | `~/.meridian/logs/mlx-server.log` |
| `coding-agent-indexer` | `~/.meridian/logs/coding-agent-indexer.log` |
| `mlx-server-error` | `~/.meridian/logs/mlx-server-error.log` |

**Flags**

Expand All @@ -111,39 +114,187 @@ meridian logs daemon -f
# Last 50 lines of the MLX server log
meridian logs mlx-server -n 50

# Stream daemon errors only (skip routine INFO output)
meridian logs daemon-error -f

# Stream MLX server errors only
meridian logs mlx-server-error -f

# Tail errors from screenpipe
meridian logs screenpipe-error
```

<Tip>
The Rust daemon also writes structured JSON logs to `~/.meridian/logs/meridian-rust.jsonl.<date>` for `jq`-friendly grepping outside the CLI.
</Tip>

</Accordion>

<Accordion title="meridian doctor">
<Accordion title="meridian doctor [--fix] [--dry-run] [--porcelain]">

```bash
meridian doctor [--fix] [--dry-run] [--porcelain]
```

Runs a comprehensive, read-only system-health sweep across every Meridian daemon and prints a colourised (when stdout is a TTY) by-daemon table, a root-cause **Diagnosis** section, and an escalation footer when anything needs attention. The CLI wrapper delegates to the daemon binary's health engine — if the binary is missing or stale, a minimal bash fallback runs so `meridian doctor` always produces something useful.

Run `meridian doctor` as the first diagnostic step whenever something seems wrong: a missed Jira sync, a blank dashboard, a misclassified session, or a daemon that looks alive but isn't producing output. Every check is content-free — counts, timestamps, status codes, reachability — never screen content or ticket text.

**Check groups**

| Group | What it looks at |
|---|---|
| `system` | macOS detected, disk free, `.env` present, required toolchains |
| `meridian daemon` | ETL last-run status + freshness, frame cursor, summariser / classifier queue depth, subprocess-error sentinels |
| `screenpipe` | binary on PATH, plist installed, process live, DB frames, frame freshness, blank-text rate (Screen Recording permission proxy), per-app accessibility share, WAL size |
| `mlx-server` | `/health` reachability and backend, `/info` model-loaded readiness (liveness vs. readiness) |
| `jira` | `/myself` auth (distinguishes 401 expired from 403 scope), ticket sync freshness, candidate-ticket completeness |
| `ui` | launchd service up, `.next` built, `/` serves, a referenced `_next/static` asset fetches, serve mode (catches an `output: 'standalone'` build run with `next start`) |
| `mcp server` | `packages/meridian-mcp/dist/index.js` built |
| `worklog` | drafts awaiting review, hours stuck unprocessed, approved worklogs failing to post |
| `coding-agent` | Claude Code and Codex CLI presence, JSONL session directories, `~/.claude/commands/session-summary.md` skill file (without it, every Claude Code session falls back to MLX) |
| `observability` | OpenObserve reachability (so telemetry doesn't silently drop) |
| `config` | cross-process contract — DB path agreement (`MERIDIAN_DB` vs. `MERIDIAN_DB_PATH`), settings-file split-brain, dead env vars like `POLL_INTERVAL_SECS` |

Each row is `✓ ok`, `⊘ warn`, `· info`, or `✗ critical`. Failing rows show a `→` remedy line with the exact command to fix them. The exit code is `0` on a clean run and `1` when any check is critical.

**Flags**

| Flag | Description |
|---|---|
| `--fix` | Apply tiered repairs to the warnings the sweep finds — see below |
| `--dry-run` | With `--fix`, plan the repairs without executing them |
| `--porcelain` | Emit TSV rows instead of the rich table — for scripts and dashboards |

**`--fix` repair tiers**

| Tier | Behaviour |
|---|---|
| auto | Safe + idempotent (e.g. restart a dead service) — run silently |
| guided | Shows the command and asks `y/N` before running (e.g. drain the summariser queue, re-classify sentinels, refresh Jira, rebuild UI). Defaults to **No** on non-interactive stdin so `--fix` never auto-runs a mutating action without a human. |
| manual | Only a human can do it (regenerate a token, align settings) — printed as instructions |

Anything still failing after `--fix` is escalated: a content-free diagnostic bundle is written to `~/.meridian/` so you can share it with the team or hand it off to `claude`.

**Examples**

```bash
# Default: full sweep with table, diagnosis, and escalation footer
meridian doctor

# See what --fix would do, without changing anything
meridian doctor --fix --dry-run

# Apply auto fixes, prompt for guided ones, print remaining manuals
meridian doctor --fix

# Machine-readable TSV for a dashboard or CI gate
meridian doctor --porcelain
```

<Note>
The daemon also runs a subset of these checks (capture-layer / L1 only) as a startup preflight, logging warn/error to `daemon.log`. The preflight is non-fatal — the daemon still runs — so always confirm with `meridian doctor` if you suspect a fault.
</Note>

</Accordion>

<Accordion title="meridian worklog-status [--day YYYY-MM-DD]">

```bash
meridian worklog-status [--day YYYY-MM-DD]
```

Prints a read-only, human-readable report of the day's PM worklogs: the hour ledger (done / pending / stuck), worklogs grouped by state (`drafted`, `approved`, `posted`, `rejected`, `failed`), and a per-ticket table with the synthesised Jira comment for each row. Useful for a quick "what is the daemon about to post?" check before approving worklogs in the dashboard.

This command is read-only — it never writes to the DB and never calls Jira / GitHub / Linear. It also skips daemon initialisation, so it's safe to run while the daemon is up.

**Flags**

| Flag | Description |
|---|---|
| `--day YYYY-MM-DD` | Report for the given day (default: today, in the daemon's local timezone) |

**Examples**

```bash
# Today's worklogs
meridian worklog-status

# Backfill check for a specific day
meridian worklog-status --day 2026-05-30
```

</Accordion>

<Accordion title="meridian pm-worklog [--day YYYY-MM-DD]">

```bash
meridian pm-worklog [--day YYYY-MM-DD]
```

One-shot run of the Stage 4 PM worklog pipeline: walks the day's hour ledger and **drafts** one worklog per task per ready hour. Worklogs land in the `drafted` state — they are never auto-posted. Approve them in the dashboard (or run `meridian worklog-post-approved`) to send them to Jira / GitHub / Linear.

Use this when you want to regenerate drafts for a past day, recover from a failed run, or kick the pipeline manually without waiting for the next daemon cycle. The daemon runs the same pipeline on a schedule, so under normal operation you do not need to call this command.

**Flags**

| Flag | Description |
|---|---|
| `--day YYYY-MM-DD` | Day to process (default: today) |

**Examples**

```bash
# Re-draft worklogs for yesterday
meridian pm-worklog --day 2026-06-01

# Draft today's worklogs now (skip waiting for the next daemon cycle)
meridian pm-worklog
```

<Warning>
Running `meridian pm-worklog` while the in-daemon worklog pipeline is also active can have both processes hit the LLM at the same time. The global LLM gate prevents corruption, but for predictable behaviour run this against a stopped daemon (`meridian stop`) when backfilling.
</Warning>

</Accordion>

<Accordion title="meridian worklog-post-approved">

```bash
meridian worklog-post-approved
```

Runs a full suite of environment health checks and prints a pass/fail result for each one. Checks include:
Posts every worklog you have approved in the dashboard to its provider (Jira / GitHub / Linear) immediately. This is a one-shot run of the same approved-poster sweep the daemon performs every ~60 seconds, so use it when you want a result *now* — for example, right after approving a batch of worklogs in the dashboard and not wanting to wait for the next cycle.

- macOS detected
- `meridian-daemon` binary exists and is executable
- Service `.plist` files are installed and pass `plutil -lint` (daemon, jira-updater, screenpipe, UI)
- Daemon process is running
- `~/.meridian/.env` configuration file exists
- screenpipe binary is in `$PATH`
- screenpipe database exists at `~/.screenpipe/db.sqlite`
- screenpipe process is running
- Python venv is set up and `run_agent` is importable
- MCP server has been built (`packages/meridian-mcp/dist/index.js` exists)
- Next.js UI has been built (`ui/.next` directory exists)
This is the only CLI command that writes to a real ticketing system. Worklogs in any state other than `approved` are skipped.

At the end, `doctor` prints a count of failed checks. A clean run looks like:
**Example**

```bash
# Approve worklogs in the dashboard, then flush them to Jira now
meridian worklog-post-approved
```
✓ all checks passed

</Accordion>

<Accordion title="meridian coding-agent-install-skill">

```bash
meridian coding-agent-install-skill
```

Run `meridian doctor` as the first diagnostic step whenever something seems wrong.
Writes the `session-summary` Claude Code slash-command file to `~/.claude/commands/session-summary.md` so `claude -p /session-summary` resolves to the prompt Meridian uses to summarise coding-agent transcripts for the Jira worklog.

Without this file, `claude -p /session-summary` returns *Unknown command* and the summariser silently falls back to the local MLX model for every Claude Code session — you lose subscription-claude quality on the transcript summaries that feed the worklog. Run this once per machine where Claude Code is installed.

The command is idempotent (safe to re-run) and writes nothing if the file already exists. `meridian doctor` warns when the skill is missing, and `meridian doctor --fix` runs this command for you, so most users never need to invoke it directly.

**Example**

```bash
# First-time setup for Claude Code summarisation
meridian coding-agent-install-skill
```

</Accordion>

Expand Down Expand Up @@ -187,6 +338,35 @@ Without Screen Recording permission, screenpipe cannot capture frames and Meridi

</Accordion>

<Accordion title="meridian update">

```bash
meridian update
```

Updates a source checkout to the latest `main` in one step: `git pull --ff-only`, rebuilds the Rust daemon (`cargo build --release`), rebuilds the Next.js UI (`npm run build`), then restarts every daemon via `meridian restart`. Use it after a release announcement, or any time you want to pull upstream fixes without running each step by hand.

This command only works in a source checkout (the directory contains a `Cargo.toml`). For production installs from npm, upgrade with:

```bash
npm install -g @meridiona/meridian@latest
```

If `git pull --ff-only` fails (local commits that haven't been pushed, or a non-fast-forward), `meridian update` exits without rebuilding so you can resolve the conflict yourself; rerun `meridian dev build` and `meridian restart` afterwards.

**Example**

```bash
# Pull, rebuild, and restart everything in a source checkout
meridian update
```

<Tip>
The command prints the new version on success — either the contents of the `VERSION` file or the short Git SHA if `VERSION` is missing.
</Tip>

</Accordion>

<Accordion title="meridian uninstall">

```bash
Expand Down