> ## Documentation Index
> Fetch the complete documentation index at: https://docs.oktolabs.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# CLI Reference

> Complete reference for all okto-pulse CLI commands, flags, exit codes, and expected output.

# CLI Reference

`okto-pulse` is the single entry point for installing, starting, and maintaining a Pulse instance. All commands run locally — nothing is sent to a remote server.

## Installing the CLI

```bash theme={null}
pip install okto-pulse
```

Requires Python 3.11+. See [Install](/install) for Docker and source options.

Verify the install:

```bash theme={null}
okto-pulse --version
```

```text theme={null}
okto-pulse 0.2.0
okto-pulse-core 0.2.0
```

***

## Global flags

These flags are accepted by every command.

<ParamField query="--help" type="boolean">
  Print usage and exit. Works on the root command and on any subcommand: `okto-pulse init --help`.
</ParamField>

<ParamField query="--version" type="boolean">
  Print the versions of both `okto-pulse` and `okto-pulse-core` and exit. Source: `cli.py:164`.
</ParamField>

To increase log verbosity, set the `DEBUG` environment variable:

```bash theme={null}
DEBUG=true okto-pulse serve --accept-terms
```

***

## `okto-pulse init`

*Source: `cli.py:314–440`*

Initialize `~/.okto-pulse/`, seed the database, bootstrap the knowledge graph schema for the first board, and optionally write `.mcp.json` for your agent.

```bash theme={null}
okto-pulse init [--agents [NAME ...]]
```

<ParamField query="--agents" type="string[]">
  Generate `.mcp.json` in the current directory. Pass with no argument to include all registered agents. Pass one or more agent names to include only that subset. Omit the flag entirely to skip `.mcp.json` generation.

  ```bash theme={null}
  okto-pulse init --agents          # all agents
  okto-pulse init --agents claude   # named agent only
  okto-pulse init                   # no .mcp.json
  ```
</ParamField>

**What `init` creates:**

```text theme={null}
~/.okto-pulse/
  data/pulse.db                   SQLite database (WAL mode, FK ON)
  uploads/                        file attachment storage
  boards/{board_id}/graph.lbug    per-board knowledge graph
```

`.mcp.json` is written in the **current working directory** (not `~/.okto-pulse/`). Run `init` from your project root so your agent picks it up.

<Warning>
  `.mcp.json` contains a per-agent API key. Add it to `.gitignore` before your first commit.
</Warning>

**Exit codes:** `0` on success. Non-zero if the data directory cannot be created or the database cannot be seeded.

<CodeGroup>
  ```bash Init with agents theme={null}
  cd ~/my-project
  okto-pulse init --agents
  ```

  ```text Output theme={null}
  ✓ Data directory: ~/.okto-pulse/data/
  ✓ Database initialized
  ✓ Default board created
  ✓ Knowledge graph bootstrapped
  ✓ .mcp.json written (1 agent)
  ```
</CodeGroup>

***

## `okto-pulse serve`

*Source: `cli.py:500–563`*

Start the API server, web board, and MCP server as a single Python process with two uvicorn listeners.

```bash theme={null}
okto-pulse serve [--api-port PORT] [--mcp-port PORT] [--accept-terms]
```

<ParamField query="--api-port" type="number" default="8100">
  Port for the web board and REST API. Sets `OKTO_PULSE_PORT` before the app module is imported. Source: `cli.py:20`.
</ParamField>

<ParamField query="--mcp-port" type="number" default="8101">
  Port for the MCP server (216 tools). Sets `OKTO_PULSE_MCP_PORT` before the app module is imported. Source: `cli.py:21`.
</ParamField>

<ParamField query="--accept-terms" type="boolean">
  Pre-accept the Terms of Use and skip the interactive prompt. Equivalent to setting `OKTO_PULSE_TERMS_ACCEPTED=1`. Required in CI and containerized environments. Source: `cli.py:537`.
</ParamField>

<Note>
  Both port environment variables are set **before** the app module is imported, because `okto_pulse.community.main` reads them at import time to generate `/config.js`. If you use a non-default MCP port, update the generated `.mcp.json` URL so it matches the port passed to `okto-pulse serve --mcp-port`.
</Note>

<CodeGroup>
  ```bash Default start theme={null}
  okto-pulse serve --accept-terms
  ```

  ```text Output theme={null}
  Board:  http://127.0.0.1:8100
  MCP:    http://127.0.0.1:8101/mcp
  ```

  ```bash Custom ports theme={null}
  okto-pulse serve --api-port 9000 --mcp-port 9001 --accept-terms
  ```
</CodeGroup>

**Exit codes:** `0` on clean shutdown (Ctrl+C). Non-zero if either port is already in use.

***

## `okto-pulse status`

*Source: `cli.py:567–614`*

Show service status and board metrics without starting the server.

```bash theme={null}
okto-pulse status [--api-port PORT] [--mcp-port PORT]
```

<ParamField query="--api-port" type="number" default="8100">
  Port to probe for the API server. Must match the port used in `serve`.
</ParamField>

<ParamField query="--mcp-port" type="number" default="8101">
  Port to probe for the MCP server.
</ParamField>

<CodeGroup>
  ```bash Status check theme={null}
  okto-pulse status
  ```

  ```text Output theme={null}
  Data dir:   ~/.okto-pulse/data/
  Database:   ~/.okto-pulse/data/pulse.db (1,204 KB)

    boards      1
    cards       47
    specs       8
    agents      2

  API server  :8100   running
  MCP server  :8101   running
  ```
</CodeGroup>

**Exit codes:** `0` always. Port connectivity failures are reported in the output, not via exit code.

***

## `okto-pulse api-key`

*Source: `cli.py:620–680`*

Print the bootstrap API key directly from the SQLite database. Use this in CI/CD pipelines to extract the seeded key without parsing log output.

```bash theme={null}
okto-pulse api-key
```

No flags.

**Output:** The API key value on a single line to `stdout`. The startup banner goes to `stderr` so the key can be captured cleanly:

```bash theme={null}
KEY=$(okto-pulse api-key 2>/dev/null)
```

**Exit codes:** `0` if the key is found and printed. `1` if the database is missing or no key exists (run `okto-pulse init` first).

<CodeGroup>
  ```bash Print API key theme={null}
  okto-pulse api-key
  ```

  ```text Output theme={null}
  dash_a3f8c21e4b7d9f0e2a1c5b8d
  ```
</CodeGroup>

***

## `okto-pulse verify-pipeline`

*Source: `cli.py:683–744`, `kg/health.py`*

Run five KG pipeline health checks against a board and report results.

```bash theme={null}
okto-pulse verify-pipeline <board_id> [--json]
```

<ParamField path="board_id" type="string" required>
  The board UUID to inspect. Find it in the web board URL or via `okto-pulse status`.
</ParamField>

<ParamField query="--json" type="boolean">
  Emit a structured JSON object instead of a human-readable table. Useful for scripted health monitoring.
</ParamField>

**Checks run:**

| Check                  | What it verifies                                               |
| ---------------------- | -------------------------------------------------------------- |
| `check_queue`          | SQLite consolidation queue depth                               |
| `check_kuzu`           | LadybugDB graph file presence and node count                   |
| `check_kuzu_node_refs` | Cross-check between LadybugDB total and SQLite node ref mirror |
| `check_outbox`         | Global update outbox staleness                                 |
| `check_global`         | Global discovery graph file presence                           |

**Exit codes:** `0` if all five checks pass. `1` if any check fails. Use exit code in CI to gate deployments.

<CodeGroup>
  ```bash Table output theme={null}
  okto-pulse verify-pipeline <board_id>
  ```

  ```text Output theme={null}
  check_queue          ✓ pass   depth=0
  check_kuzu           ✓ pass   nodes=312
  check_kuzu_node_refs ✓ pass   delta=0
  check_outbox         ✓ pass   staleness=0s
  check_global         ✓ pass
  ```

  ```bash JSON output theme={null}
  okto-pulse verify-pipeline <board_id> --json
  ```

  ```json Output theme={null}
  {
    "check_queue": {"status": "pass", "depth": 0},
    "check_kuzu": {"status": "pass", "nodes": 312},
    "check_kuzu_node_refs": {"status": "pass", "delta": 0},
    "check_outbox": {"status": "pass", "staleness_seconds": 0},
    "check_global": {"status": "pass"}
  }
  ```
</CodeGroup>

***

## `okto-pulse kg backfill`

*Source: `cli.py:747–902`*

Run the Layer 1 deterministic KG worker against a board to (re-)populate the knowledge graph from existing artifacts. Dry-run by default — pass `--apply` to write.

```bash theme={null}
okto-pulse kg backfill <board_id> [--apply] [--artifact-type TYPE] [--json]
```

<ParamField path="board_id" type="string" required>
  The board UUID to backfill.
</ParamField>

<ParamField query="--apply" type="boolean">
  Enqueue all artifacts and drain the consolidation queue, writing to LadybugDB. Without this flag the command reports what *would* be emitted without making any changes.
</ParamField>

<ParamField query="--artifact-type" type="string">
  Restrict backfill to one artifact type. Accepts: `spec`, `sprint`, or `card`. Omit to backfill all types.
</ParamField>

<ParamField query="--json" type="boolean">
  Emit structured JSON output. Useful for scripting and log parsing.
</ParamField>

<Note>
  Run `kg backfill` after a schema migration, after importing data from another instance, or when the KG health check reports a `check_kuzu_node_refs` delta greater than zero. For ongoing consolidation, the background worker handles new artifacts automatically. See [KG backfill operations](/kg-operations/backfill) for guidance on expected runtime.
</Note>

<CodeGroup>
  ```bash Dry run (default) theme={null}
  okto-pulse kg backfill <board_id>
  ```

  ```text Output theme={null}
  Dry run — no writes. Pass --apply to commit.

    spec artifacts   8    →  would emit  43 nodes,  61 edges
    sprint artifacts 12   →  would emit  28 nodes,  34 edges
    card artifacts   47   →  would emit  94 nodes, 118 edges

  Total: 165 nodes, 213 edges pending
  ```

  ```bash Apply backfill theme={null}
  okto-pulse kg backfill <board_id> --apply
  ```

  ```text Output theme={null}
  Enqueueing artifacts...
  Processing queue...

    spec artifacts   8    → committed  43 nodes,  61 edges
    sprint artifacts 12   → committed  28 nodes,  34 edges
    card artifacts   47   → committed  94 nodes, 118 edges

  Backfill complete. Queue empty.
  ```
</CodeGroup>

**Exit codes:** `0` on success. `1` if the board is not found or the graph file cannot be opened.

***

## `okto-pulse kg dedup-entities`

*Source: `cli.py:908–936`*

Consolidate duplicate LadybugDB nodes that share the same `(node_type, source_artifact_ref)`. Writes by default — pass `--dry-run` to preview.

```bash theme={null}
okto-pulse kg dedup-entities <board_id> [--dry-run] [--json]
```

<ParamField path="board_id" type="string" required>
  The board UUID to deduplicate.
</ParamField>

<ParamField query="--dry-run" type="boolean">
  Report duplicates without merging them. Always run this first to review what will be merged before committing.
</ParamField>

<ParamField query="--json" type="boolean">
  Emit structured JSON output.
</ParamField>

<Warning>
  `kg dedup-entities` writes to the LadybugDB graph **by default** (without `--dry-run`). Merging nodes is not automatically reversible. Run the dry-run first, then `verify-pipeline` after applying to confirm the graph is consistent.
</Warning>

<CodeGroup>
  ```bash Dry run first theme={null}
  okto-pulse kg dedup-entities <board_id> --dry-run
  ```

  ```text Output theme={null}
  Dry run — no writes.

    Decision  "Use SQLite for queue"   2 duplicates → would merge
    Entity    "Claude Code"            3 duplicates → would merge

  2 merge operations pending. Run without --dry-run to apply.
  ```

  ```bash Apply dedup theme={null}
  okto-pulse kg dedup-entities <board_id>
  ```

  ```text Output theme={null}
    Decision  "Use SQLite for queue"   merged (2 → 1)
    Entity    "Claude Code"            merged (3 → 1)

  Deduplication complete. 2 nodes merged.
  ```
</CodeGroup>

**Exit codes:** `0` on success (including zero duplicates found). `1` if the board or graph file is not found.

***

## `okto-pulse reset`

*Source: `cli.py:939–960`*

Delete all local Pulse data and re-seed from scratch. Equivalent to uninstalling and reinstalling the data directory.

```bash theme={null}
okto-pulse reset [-y]
```

<ParamField query="-y, --yes" type="boolean">
  Skip the confirmation prompt. Required for non-interactive environments (CI, scripts). Without this flag, the command prints a warning and asks for confirmation before proceeding.
</ParamField>

<Warning>
  `reset` permanently deletes `pulse.db`, all WAL files, and everything in the uploads directory. All boards, specs, cards, knowledge graph data, and file attachments are lost. There is no undo.

  If you need to start over on a single board without losing others, use `archive_tree` via the MCP API instead.
</Warning>

**What `reset` does:**

1. Deletes `~/.okto-pulse/data/pulse.db*` (database and WAL files)
2. Clears `~/.okto-pulse/uploads/`
3. Runs `okto-pulse init` to re-seed defaults

**Exit codes:** `0` on success. `1` if the user declines the confirmation prompt.

<CodeGroup>
  ```bash Interactive reset theme={null}
  okto-pulse reset
  ```

  ```text Output theme={null}
  ⚠ This will delete all boards, specs, cards, and knowledge graph data.
    Data dir: ~/.okto-pulse/

  Type "yes" to confirm: yes

  ✓ Database deleted
  ✓ Uploads cleared
  ✓ Re-initialized
  ```

  ```bash Non-interactive reset theme={null}
  okto-pulse reset -y
  ```
</CodeGroup>

***

## Environment variables

Key variables that affect CLI behavior. Set in your shell or in a `.env` file in the working directory.

| Variable                    | Default         | Description                                                   |
| --------------------------- | --------------- | ------------------------------------------------------------- |
| `OKTO_PULSE_PORT`           | `8100`          | API + frontend port                                           |
| `OKTO_PULSE_MCP_PORT`       | `8101`          | MCP server port                                               |
| `OKTO_PULSE_TERMS_ACCEPTED` | —               | Set to `1` to skip the ToU prompt (same as `--accept-terms`)  |
| `OKTO_PULSE_DATA_DIR`       | `~/.okto-pulse` | Override the data directory location                          |
| `OKTO_PULSE_NO_BANNER`      | —               | Set to `1` to suppress the ASCII banner                       |
| `DEBUG`                     | `false`         | Enable verbose debug logging                                  |
| `KG_KUZU_BUFFER_POOL_MB`    | `256`           | LadybugDB buffer pool in MB (legacy env-var name, 16–512)     |
| `KG_KUZU_MAX_DB_SIZE_GB`    | `1`             | LadybugDB max database size in GB (legacy env-var name, 1–64) |

Full environment variable reference: [Local operations](/operations/local).

***

## Quick reference

| Command                                       | What it does                            |
| --------------------------------------------- | --------------------------------------- |
| `okto-pulse init --agents`                    | Bootstrap data dir + write `.mcp.json`  |
| `okto-pulse serve --accept-terms`             | Start board (`:8100`) and MCP (`:8101`) |
| `okto-pulse status`                           | Check running ports and board metrics   |
| `okto-pulse api-key`                          | Print bootstrap API key (CI use)        |
| `okto-pulse verify-pipeline <id>`             | Run 5 KG health checks                  |
| `okto-pulse kg backfill <id> --apply`         | Rebuild KG from existing artifacts      |
| `okto-pulse kg dedup-entities <id> --dry-run` | Preview duplicate node merges           |
| `okto-pulse reset -y`                         | Delete all data and re-seed             |
