# CLI commands

> Reference for every gno command, global option, retrieval mode, background service, and integration surface.

Section: Reference  
Canonical: https://gno.sh/docs/cli  
Markdown: https://gno.sh/docs/cli.md

## Compiled project context

Compile verified Capsules with gno context compiled preview, compile, check, and refresh. [Read the compiled context guide](https://gno.sh/docs/compiled-context) for limits, indexed freshness, inclusion, and recovery.

The `gno` CLI indexes local folders into SQLite and runs BM25, vector, hybrid, and cited Ask against that index. Use it to connect folders, build the index, search and ask questions, keep the collection fresh in the background, and wire GNO into AI tools. It is useful from a terminal, but the same commands also power the Web UI, REST API, MCP server, and agent skills.

## Quick chooser

Start here when you know what you want to do but not which command to reach for.

- `gno setup` — connect the first folder, prove BM25, and optionally install explicit agent handoffs.
- `gno search`, `gno vsearch`, `gno query`, `gno ask` — BM25, vector, hybrid, or cited Ask over the local index.
- `gno get`, `gno multi-get`, `gno ls` — inspect indexed documents.
- `gno capture` — add quick notes with structured provenance and a write/sync/embed receipt.
- `gno links`, `gno backlinks`, `gno similar`, `gno graph` — follow relationships.
- `gno audit` — inspect links, declared provenance, and source/index freshness without changing the workspace.
- `gno trace` with `list`, `show`, `label`, `export`, `replay`, `delete`, or `purge` — manage opt-in private retrieval receipts, explicit relevance feedback, and read-only candidate replay.
- `gno serve`, `gno daemon` — run long-lived local services.
- `gno peek` — cheap counts, backlog, recent files, and serve status for status bars and desktop widgets.
- `gno mcp`, `gno skill`, `gno publish` — connect agents and share snapshots.

## How the CLI thinks

1. **Collections** point at folders on disk: notes, research, PDFs, project docs, client files, or a Karpathy-style personal knowledge base.
2. **Indexing** reads files, extracts text, chunks documents, records links and tags, then embeds chunks for semantic search.
3. **Retrieval** searches with keyword, vector, hybrid, default bounded graph expansion, and optional reranking.
4. **Surfaces** expose the same index through the CLI, browser workspace, REST API, MCP, SDK, and installed skills.

## Setup: verified first retrieval

### gno setup

Creates or reuses a collection, indexes it, and succeeds only after an exact `gno://` result. Semantic indexing then starts in the background and setup returns right away; `--no-semantic` skips it and records the skip.

```
gno setup ~/notes --name notes
gno setup ~/notes --name notes --exclude .env --exclude private
gno setup ~/notes --authorize-secret-risk
gno setup ~/notes --no-semantic
gno setup . --apply-profile --no-semantic
gno setup ~/notes --connector cursor-mcp --connector codex-skill
```

`--exclude` is one repeatable literal pattern, not a CSV. Secret-risk detection fails closed; only interactive confirmation or `--authorize-secret-risk` authorizes likely credentials. Safe-default `--yes`, JSON, non-TTY, decline, and EOF do not. Exit `0` means lexical proof completed, even when semantic or connector follow-up remains. Exit `1` is invalid or safely rejected input. Exit `2` is config, receipt, I/O, store, indexing, proof, or invariant failure.

Canonical private state lives under the configured data directory at `setup-receipts/<index>/<folder-fingerprint>.json` and `setup-semantic/<index>/<folder-fingerprint>.json`.

Only one background semantic job runs per folder and index. Rerunning setup while it runs leaves that job in place, even with different options. `--no-semantic` starts no job and leaves a running one alone. If semantic work is pending or failed, setup still exits 0 and prints the exact foreground `gno ... embed <collection>` command to finish it.

Setup checks for the nearest valid `.gno/index.yml`. By default it only prints an advisory and points to `gno profile diff`; it does not mutate profile-owned config. Pass `--apply-profile` to apply a valid profile before lexical setup. For a valid profile, that option cannot be combined with explicit `--name` or `--exclude`; conflicting input fails before config or index mutation. A missing or invalid profile never makes setup mandatory: normal setup continues, while an explicitly requested apply is reported as a truthful follow-up action. If the profile check or apply fails, setup stops before indexing and connector work. A failed apply can leave some resources created or updated; rerunning it resumes from there.

Without connectors or profile application, JSON is `setup-command-result@1.0`. Connector mode uses `setup-activation-result@1.0` around the unchanged setup result. With `--apply-profile`, the closed `setup-profile-result@1.0` records the profile check, optional apply, setup result, and any connector results. Supported connector IDs: `claude-code-skill`, `claude-desktop-mcp`, `cursor-mcp`, `codex-skill`, `opencode-skill`, `openclaw-skill`, and `hermes-skill`. Skill execution remains `target_runtime_unverifiable`; connector follow-up may be `completed_with_actions` with lexical success intact.

Web and Desktop onboarding run the same keyword-search check through the running server. They do not write the CLI setup receipts.

## Project profiles: check, show, diff, apply

These commands discover the nearest repository-owned `.gno/index.yml`. Discovery stops at the first Git root, filesystem boundary, or filesystem root; a nearer nested profile shadows, rather than merges with, an ancestor profile. Passing a directory or its exact `.gno/index.yml` disables ancestor fallback.

```
gno profile check [path]
gno profile show [path]
gno profile diff [path]
gno profile apply [path]
```

- `check` validates discovery, the closed schema, referenced paths, local model-preset aliases, and offline cache availability when global `--offline` is active. The offline probe never repairs, deletes, or rewrites model-cache files or metadata.
- `show` adds normalized, machine-portable desired state.
- `diff` compares desired state with user config and reports stale mappings and repair choices without applying them.
- `apply` creates or updates declared resources through a resumable locked operation. Omitted and stale same-path resources remain intact, as do unrelated DB-only collections, documents, contexts, and index state. Multiple declared contexts for the same collection are preserved. Changed collections are returned in `pendingIndexing`.

Add `--json` for deterministic, path-redacted closed contracts: `project-profile-command@1.0` for check, show, and diff; `project-profile-apply@1.0` for apply. Unknown output fields are not part of either contract. Apply is idempotent and safe to rerun after an interruption. Concurrent config writes, including writes through symlinked config paths, cannot overwrite each other, and repeating an unchanged apply leaves the config byte-identical. Public receipts identify the collection but redact the local profile path, and the apply receipt stays outside the project. Config, data, databases, cache, selected file-backed models, receipts, and locks may not overlap the project root. Apply fails before mutation when that runtime boundary is unsafe. It never writes the tracked profile or indexes documents.

## Advanced setup: init, collection, index

### gno init

Creates the first GNO config and points it at a folder. Use it for the first folder in a new index.

```
gno init ~/Documents/Knowledge --name knowledge
gno init ~/Notes --name notes --pattern "**/*.md"
gno init ~/Research --name research --exclude "**/archive/**"
```

- `--name` sets the collection name used by filters.
- `--pattern`, `--include`, and `--exclude` decide which files enter the index.
- `--update` records a collection-specific update command, useful for git-backed or generated folders.
- `--tokenizer` and `--language` tune text processing for specialized collections.

### gno collection

Adds, lists, renames, removes, or resets collection embeddings after the initial setup.

```
gno collection add ~/Downloads/Papers --name papers
gno collection list
gno collection rename papers reading
gno collection clear-embeddings notes
gno collection remove old-notes
```

`remove` deletes the collection's documents from the index at once; run `gno cleanup` afterwards to reclaim the space its content and embeddings used. After `rename`, run `gno update` to index the folder under its new name; the collection has no documents until then, and existing embeddings are reused. Deleting a collection from the config file by hand keeps its documents until you run `gno cleanup` or add it back; see [collections not in the config](https://gno.sh/docs/configuration#collections-not-in-config).

### gno index, update, embed

`update` scans files into SQLite. `embed` creates vectors for semantic search. `index` does both.

An optional [chunking policy](https://gno.sh/docs/configuration#chunking) change also rechunks cached mirrors across the index. Sync receipts include `rechunkedMirrors` when this happens; file counters still describe source refresh. Sync-only work leaves changed chunks pending embedding.

```
gno update
gno update --git-pull
gno embed notes
gno index
gno index --models-pull
gno index --no-embed
gno index notes --path meeting.md projects/plan.md
gno index --lock-wait 5m
```

- `--git-pull` pulls git-backed collections before scanning.
- `--models-pull` downloads needed model files before the run.
- `--no-embed` builds a fast keyword-only index.
- `--path <file...>` reindexes only the listed files of one collection, given relative to its root or as absolute paths inside it, at most 256 files. A listed file that no longer exists is removed from the index. It needs a collection, skips the collection's update command, and cannot be combined with `--git-pull`. A path outside the collection (including through a symlink), a directory, or a path the collection's pattern, include, or exclude rules leave out exits 1 before anything is written. To reindex a whole directory, reindex the collection.
- Concurrent writers queue on the shared write lease (default wait 120s; `--lock-wait` to change, `--no-wait` to fail fast). If another writer still holds the lock after the wait, the command exits 4 (`BUSY`) and the index is unharmed. Reads are unaffected.
- `gno embed` and `gno embed --force` retry transient embedding chunk failures inside the same command run. Use `--verbose` when a run still fails so the sample errors and retry hint are visible.
- Run `gno embed` after changing embedding models or after doctor reports stale vectors. If stale or mixed vectors remain, run `gno embed --force` for a full vector refresh.

Restoring identical bytes at the same path reactivates an inactive document on the next successful `update` or `index` and records one `reactivate` event in the change journal. Repeated unchanged syncs add no further events. Unchanged chunks keep their vectors. Changed titles, text, or embedding model need re-embedding. A runtime change (backend, Bun version, threads) does not, as long as the new runtime reproduces the stored vectors.

`gno embed` resumes from completed checkpoints and rebuilds a missing vector index from stored vectors where it can. Backlog counts are document chunks waiting for vectors; identical text may share one embedding call. If stored vector data is missing or corrupt, semantic search reports a failure and hybrid search falls back to keyword results with that fallback reported. Run normal `gno embed` first; use `--force` for an intentional full refresh.

If the current runtime cannot reproduce the stored vectors, `gno embed` would build a separate vector partition. It states that, the full chunk count and an estimate, then asks for confirmation; non-interactive runs need `gno embed --new-partition`, and `--yes` alone never confirms. See [Switching backend or Bun version](https://gno.sh/docs/troubleshooting#backend-switch).

## Retrieve: search, vsearch, query, ask

### gno search and gno vsearch

`search` is exact and fast. Use it for titles, names, quotes, filenames, error messages, and identifiers you already have verbatim. `vsearch` is semantic. Use it when the right documents may use different words than your query; for a question, start with `gno query --fast`.

`search` builds highlighted snippets only for the results it returns, so even a long natural-language input answers in about 0.2-0.4 seconds on a 2,300-document index. Each snippet, and its `snippetRange` line span, comes from the part of the document that best covers the query terms, with the terms marked.

```
gno search "spaced repetition" --collection notes
gno search "ERR_INVALID_STATE" --line-numbers
gno search --query-file /run/user/1000/gno-recall/q.XXXX --json
printf '%s' "auth" | gno search --query-file - --json
gno search "deploy" -c work -c ops --json
gno vsearch "notes about memory and learning loops" --limit 10
```

- `--query-file <path>` reads the query from a file (`-` is stdin) so desktop callers can keep it off argv. Do not also pass a positional query.
- Scope with `--collection` (repeatable), `--limit`, `--min-score`, `--since`, `--until`, `--tags-any`, `--tags-all`.
- Change output with `--full`, `--line-numbers`, `--json`, `--md`, `--csv`, `--files`, `--xml`.

Structured `--json` results include `results[].source.absPath` when the hit is a resolvable file-backed document. There is no `--source` flag. If `absPath` is absent, show the URI tail and do not offer file-open for that row.

Default snippets skip a leading YAML frontmatter fence and prefer document prose. When the snippet window is frontmatter-dominated, GNO falls back to stripped chunk prose. `line` and `snippetRange.startLine` follow that trimmed display range. `--full` and `--line-numbers` still emit the raw source. This display cleaning applies to `gno search`, `gno vsearch`, and `gno query`.

Local CLI retrieval uses the canonical repository or worktree for the current directory as a bounded soft signal. When the nearest local `.gno/index.yml` is valid, its canonical root and affinity defaults replace that cwd-derived fallback for the request; the profile does not mutate the user’s global affinity config. A matching collection can receive at most `+0.03`. Pass repeatable `--project-root <path>` values to replace the profile or cwd-derived root. The user config’s `projectAffinity.enabled` setting controls only cwd fallback; explicit roots and valid profiles retain their higher precedence. Use `--no-project-affinity` to disable every source for one request. Invalid and missing profiles fall back normally. Roots never stack; collection, tag, date, exclude, and egress filters stay hard. Explain output exposes only redacted collection and root aliases. Local `gno query diagnose` returns `schemaVersion: "1.1"` with redacted affinity metadata, including `project_profile` as the source when the profile supplied the root, and whether anything matched. When affinity is off or absent, or the request is remote, diagnose returns the `1.0` shape; those responses omit `affinity`.

### Search several collections at once

`gno search`, `gno vsearch`, and `gno query` search every collection by default. One `-c` (`--collection`) limits the search to that collection; repeat it to search several: `gno query "rollout plan" -c work -c ops`. The filter applies before the result limit, so documents from other collections never take result slots, graph neighbors, or rerank budget.

- Names are case-insensitive and de-duplicated. `--json` lists the searched collections, sorted, in `meta.collections`; a single `-c` still reports `meta.collection`.
- Up to 256 collections per search; more exits 1. A name that is not configured exits 2 with `Collection not found: <name>` (or `Collections not found: a, b`), the same as a single unknown `-c`.
- When the listed collections use different embedding, expansion, or rerank models, that step uses your default model; when they agree, their shared model is used.
- `gno query diagnose` takes one `-c`.

The MCP tools, REST API, and SDK take the same scope as a `collections` list; see [MCP](https://gno.sh/docs/mcp#tool-playbook), [REST API](https://gno.sh/docs/api#search-endpoints), and [SDK](https://gno.sh/docs/sdk#client-apis).

Supported collection/path scope, tags, modified-date bounds, category, author, exclusions, visibility, and managed-memory filters select eligible owners before the corresponding candidate limit. Vector and hybrid retrieval also filter chunk language before their budgets; standalone lexical `--lang` remains reserved. Whole-document exclusions inspect all chunks, including other languages. Score thresholds, deduplication, and available evidence can still yield fewer than `--limit` results, including zero.

### gno query

Hybrid retrieval for normal use. It combines keyword, vector, fusion, default bounded graph expansion, and optional reranking. Disable the graph stage only when you explicitly want a graph-free path.

Fusion works on documents: keyword search ranks whole documents and semantic search ranks passages, so each list counts a document once, at the rank of its best passage. A document both searches find first gets both votes.

```
gno query "what did I decide about backups?"
gno query --query-file /run/user/1000/gno-recall/q.XXXX --json
gno query "papers about retrieval evaluation" --tags-any research
gno query "pricing notes" --fast
gno query "architecture tradeoffs" --thorough --explain
gno query "linked context" --explain
gno query "pure vector/lexical" --no-graph
gno query "auth" -c work -c notes
gno query $'auth flow\nterm: "refresh token"\nintent: token rotation'
```

- Start questions with `--fast` (about 0.2 s with models loaded through MCP or `gno serve`, about 2 s as a one-off command). Run the balanced default when it misses (2 to 3 s with models loaded). `--thorough` spends more time for better recall. Measured on a 17,600-chunk index with an RTX 4090; CPU-only machines are slower.
- Graph expansion resolves outgoing wiki/markdown links and backlinks touching the top seeds, then adds those one-hop neighbors as candidates. Links can cross collections of one vault, but a query scoped with `--collection` only ever adds neighbors from that collection. Semantic similarity stays in vector retrieval, so the query does not rebuild the collection graph. It is on by default;` --no-graph` and `--fast` skip it. `--no-expand` and `--no-rerank` disable pipeline stages for debugging or speed.
- `--query-file` is the same as on `gno search`. It is invalid with a positional query and invalid on `query diagnose`.
- `--intent`, `--query-mode`, `--candidate-limit`, and `--explain` steer or inspect retrieval.

One configured `contentTypes[].searchBoost` may contribute at most `±0.05` and composes with trusted local project affinity under a shared `±0.08` cap. BM25 and vector only adjust candidates that already survived retrieval and `minScore`. In hybrid mode the boost applies before reranking, so the reranker and the top keyword hit keep precedence. The signal cannot create a candidate or bypass hard filters. `--explain` reports the base score, factor, bounded contribution, final score, rule source, and ranking fingerprint when active.

### gno ask

Retrieves evidence and optionally asks a local model to synthesize a cited answer. Use it for questions over your notes, not for general chatbot use.

The model is told today's date and each source's content date (its frontmatter or record date, never the file's modification time), so it can answer questions about when something happened or which source is newer.

```
gno ask "what are my open migration risks?" --answer
gno ask "who owns the launch decision?" --verify
gno ask "summarize my latest meeting notes" --since "last week"
gno ask "what did I save about local-first apps?" --show-sources
```

- `--answer` forces synthesis. `--no-answer` returns retrieval results only.
- `--verify` implies answer generation, compiles a closed Context Capsule, and classifies every substantive claim as `supported`, `contradicted`, `insufficient`, or `uncertain`. It withholds the draft unless support reaches 100%.
- A claim that quotes its source, in double or single quotes and even a single word, must quote it exactly (whitespace, quote style and letter case aside). A misquote makes the claim `uncertain` with `quote_not_in_evidence`, whatever the semantic judge said, and the answer abstains.
- Verified output retains exact evidence IDs, line ranges, and source, mirror, and passage hashes. Missing or stale evidence, unavailable semantic verification, and degraded retrieval capabilities stay explicit.
- `--max-answer-tokens` controls answer length.
- `--show-sources` keeps citations visible.

A source hit is not proof that all answer-bearing passages were retained. For multi-source questions, inspect each required passage with `gno get` and preserve its citation. Diagnose a known missing target with `gno query diagnose`; keep omissions, gaps, and unanswered parts explicit. See [document hits and complete evidence](https://gno.sh/docs/how-search-works#complete-evidence).

## Context Capsules and saved freshness

Compile one deterministic, token-budgeted evidence bundle, verify a saved bundle without rebuilding it, or explicitly register a caller-owned Capsule file for resident freshness checks:

```
gno context build "compare launch proposals" --budget 12000 --json --output capsule.json
gno context verify capsule.json --json
gno context watch capsule.json --question "Who owns launch?" --notify --json
gno context watches --json
gno context reverify <registration-id> --json
gno context unwatch <registration-id>
```

Watch lifecycle commands are CLI-only and scoped to the Capsule's canonical index. GNO stores bounded metadata and evidence hashes, never Capsule or passage text, and never rewrites the saved file. A completed check stores a verification receipt and runs no answer model. A failed check stores no receipt; `gno context reverify` prints its error code and message and exits nonzero. Local notifications contain only registration/Capsule identity, operation status, affected-question state, and timestamp.

## Knowledge Delta

Read bounded metadata-only change history, one retained structural diff, or explainable inbound dependency paths:

```
gno changes --since 2026-07-20T00:00:00Z --json
gno diff gno://notes/plan.md --json
gno impact gno://notes/plan.md --max-depth 3 --max-edges 250 --json
gno impact gno://notes/plan.md --collection notes --json
```

Change IDs and cursors are opaque. Journal retention can expire old cursors; GNO reports partial, expired, or unavailable history instead of reconstructing source bodies. Impact traversal always enforces depth, node, edge, frontier, and visited-row bounds. Without `--collection` it covers every collection; repeat `--collection` to keep the traversal, and every step of each evidence path, inside those collections.

## Private retrieval receipts

With `retrievalTraces.enabled: true`, successful search, query, ask, get, and Context Capsule calls print `Trace: <traceId>` to stderr. Stdout and structured payloads remain unchanged. Continue a retrieval-only receipt by passing the ID to an exact read:

```
gno query "deployment decision"
gno get gno://work/decisions/deploy.md --from 40 --limit 20 --trace-id <traceId>
```

Terminal replay-mode receipts with explicit labels can become content-free qrels and a verified local replay baseline:

```
gno trace export <traceId> --format qrels --output qrels.json
gno trace replay <qrels-export-id> --candidate hybrid --md
```

Replay checks the aggregate manifest and immutable evidence hashes, then compares rank, coverage, capability fallbacks, and source freshness. It can recommend promotion but always returns `applied: false`; it never edits ranking configuration, models, prompts, traces, or source files.

## Read: get, multi-get, ls, tags

### gno get and gno multi-get

Search results return `gno://` URIs, paths, doc IDs, and line anchors. Use the read commands to pull the exact source into a terminal, script, or AI prompt after retrieval.

Structured search, vector, query, and ask results may also include `context`: user-configured guidance resolved for that exact `uri` and `docid`. Matching guidance composes global first, collection second, then path prefixes from broadest to most specific. It guides interpretation without changing ranking.

```
gno get gno://notes/learning.md
gno get gno://notes/learning.md --from 40 --limit 30
gno multi-get gno://notes/a.md gno://notes/b.md --max-bytes 12000
```

- `--from` and `--limit` fetch bounded line ranges.
- `--line-numbers` preserves citation-friendly anchors.
- `--source`, `--json`, `--md`, `--files` control output shape.

### gno convert

Print the Markdown GNO would index for one file, without adding it to a collection. The output is exactly what indexing stores for that file, and nothing is written: no config, index, or cache is needed.

```
gno convert report.pdf
gno convert report.pdf > report.md
gno convert slides.pptx --json
```

- Plain output is the Markdown only; conversion warnings go to stderr.
- `--json` adds the title, language hint, converter, mirror hash, and warnings.
- Files over the indexing size limit (100 MB) are refused before they are read.
- Mail archives, calendars, and other formats GNO splits into several records are refused with `MULTI_DOCUMENT`; index them in a collection instead.
- Errors name a reason: `NOT_FOUND`, `TOO_LARGE`, `UNSUPPORTED`, and `MULTI_DOCUMENT` exit 1; converter failures such as `CORRUPT` or `TIMEOUT` exit 2.

### gno ls, tags, status, doctor

Use these when results look wrong. First check whether the document is indexed, then inspect tags and health.

Status JSON includes `chunking.configured`, `applied`, `state`, `pendingDocuments`, and `pendingMirrors`. Layout states are empty, legacy-default, current, pending, or mixed. Applied parameters are null for empty/mixed layouts. These counts describe cached chunks; source errors and embedding backlog remain separate.

Embedding status reports coverage for the vectors that search actually reads, so a half-built replacement never shows up as lost embeddings. Pending counts are per document chunk: identical text in documents with different titles needs separate embeddings. Collection chunk totals count shared text once, and a shared chunk counts as embedded only when every document using it in that collection is covered. Status does not load a model. You do not need `gno embed --force` to fix a status count.

When more than one partition exists, status prints a `Vector partitions:` block (JSON: `vectorRuntime` and `vectorPartitions`): first what this runtime's queries read, selected by the same rule retrieval uses (a partition, lexical retrieval only with the reason, or not resolved until its first query or embed), then each partition's state, chunk count, provenance such as `CUDA, Bun 1.4.2`, and the runtimes that read or cannot read it. Status prints a `gno vec drop <id-prefix>` hint for exactly the partitions drop accepts: abandoned shadow or legacy partitions this runtime does not read. Activated partitions are refused because another runtime may read them.

Status checks each configured collection's folder every time it runs. A folder that is missing or unreadable (an unmounted drive, an offline sync folder, a renamed directory) is named under its collection with a `Root unavailable:` line and the error; its documents stay indexed and counted. JSON output adds `rootError` (`code`, `message`) to that collection and sets `healthy` to false. The report clears as soon as the folder is back, without an update. For `sourceAvailability: local` collections the check confirms the folder exists and is readable without listing it, so it never downloads a cloud folder's listing.

Status lists configured collections only. Indexed collections the config does not list appear under `Collections not in this config` (JSON: `staleCollections`); other commands refuse to open that index until you add them back, use a separate `--index`, or run `gno cleanup`. See [Troubleshooting](https://gno.sh/docs/troubleshooting#collections-not-in-config).

```
gno ls --collection notes
gno tags
gno metadata --collection notes
gno status --json
gno doctor
```

`gno doctor` includes an `embedding-fingerprint` check. In JSON output, that check carries an `embeddingFingerprint` object with `currentFingerprint`, `pendingChunks`, `legacyChunks`, `mixedGroups`, and `groups`. Warnings mean BM25 still works, but semantic results may need `gno embed` or `gno embed --force`. A `vector-partitions` check reports the partition retrieval uses and warns about shadow or legacy partitions and incompatible runtimes. A `collection-roots` warning names each collection whose folder is missing or unreadable right now, with the folder and the error; it counts as a warning for the exit code but makes the structured doctor result non-healthy. The documents stay indexed.

Doctor and status also expose collection-scoped retrieval activation. Lexical readiness comes from a corpus-derived local search that must return the expected indexed document; it does not wait for semantic models. Semantic state is reported independently and may remain pending or skipped. Connector rows appear only after you run the connector check in the Web UI, and only while that result still matches the current setup. Only the first 64 target/collection checks are listed, but every check counts: the listing says how many of the rest passed, failed or are pending, and overall connector health is decided from all of them.

### gno peek

Cheap read-only snapshot of index counts, backlog, recent files, and whether detached serve is up. One invocation; no model or embedding initialization. Use it instead of composing `gno status` + `gno ls` + `gno changes`. Keep `gno status` for activation, onboarding, and the full health payload. Status bars and desktop widgets can poll it on a coarse interval. GNO Recall (`omarchy plugin add https://github.com/gmickel/omarchy-gno-recall`) uses this snapshot from the Omarchy bar.

```
gno peek
gno peek --json
```

Uninitialized is success: `--json` returns `initialized: false` with pinned nulls and `recent: []`, exit 0. JSON is `peek@1.0`. `recent` is at most 10 files, newest first. `recent[].absPath` is the path to open a recent file without `gno get`. `serve.running` is pid-file based and is true only for `gno serve --detach`. A foreground `gno serve` is not detected. A stale pid reports not running. There is no HTTP probe. If any part of the snapshot fails, peek returns one `RUNTIME` error (exit 2) and no partial snapshot.

```
{
  "schemaVersion": "peek@1.0",
  "initialized": true,
  "counts": { "documents": 1234, "collections": 5 },
  "backlog": { "pending": 0, "failed": 0 },
  "lastIndexedAt": "2026-08-29T09:00:00Z",
  "recent": [
    {
      "docid": "#abc123",
      "uri": "gno://notes/inbox.md",
      "title": "Inbox",
      "collection": "notes",
      "absPath": "/home/user/notes/inbox.md",
      "modifiedAt": "2026-08-29T08:55:00Z"
    }
  ],
  "serve": { "running": true, "url": "http://localhost:3000" }
}
```

When `serve.running` is true, open a document in the Web UI with the stable template `{serveUrl}/doc?uri=<encodeURIComponent(uri)>` (`serve.url` plus document URI; optional `#anchor`). See [document deep links](https://gno.sh/docs/web-ui#section-links).

### gno capture

Capture writes a note into an editable collection. Inline content,`--stdin`, and `--file` are mutually exclusive. Capture accepts text only; binary-like file or stdin content is rejected before writing. With no path, folder, or title, captures land under `inbox/YYYY-MM-DD/capture-<body-hash>.md` using UTC time.

```
gno capture "thought to remember"
gno capture --stdin --collection notes --preset source-summary --tags inbox,gno
gno capture --file ./clip.md --source-url https://example.com --source-kind web --json
gno capture --preset person --title "Jane Doe" --folder people/
gno capture --preset meeting --title "Weekly sync" --folder meetings/
gno capture "meeting note" --quiet
```

Preset IDs include `blank`, `project-note`, `research-note`, `decision-note`, `prompt-pattern`, `source-summary`, `idea-original`, `person`, `company-project`, and `meeting`. The typed second-brain presets keep current synthesis above `## Timeline` and dated evidence below it.

JSON output returns a receipt with separate write, sync, and embed status. Capture writes and syncs the note into text search before it returns; it does not imply embedding unless `embed.status` is `completed`. If lexical sync fails, the command still exits 0 with `sync.status` `failed`; run `gno update` to index the note. Capture writes fail instead of replacing a late-arriving file.

### Retry-safe writes and gno request-status

`gno capture` and `gno remember` (with `--add` or `--supersede`) accept `--request-id <id>`; check one with `gno request-status <id> [--json]` before retrying. See [Retry-safe writes](https://gno.sh/docs/retry-safe-writes).

## Relationships: links, backlinks, similar, graph

### gno links, backlinks, similar

These commands answer “what does this note point to?”, “what points back?”, and “what is semantically nearby?”.

```
gno links gno://notes/llm-memory.md
gno backlinks gno://notes/llm-memory.md
gno similar gno://notes/llm-memory.md --limit 8
```

Links resolve across the collections of one [link workspace](https://gno.sh/docs/configuration#link-workspaces), so backlinks can come from a sibling collection. JSON names the other collection (`resolvedCollection` on links, `sourceCollection` on backlinks); `gno backlinks --collection` limits the linking documents.

### gno graph

Builds a document graph from wiki links, markdown links, backlinks, unresolved links, and optional similarity edges. Use it to find hubs, isolated notes, communities, nearest neighbors, and paths between ideas.

```
gno graph --collection notes --json
gno graph --neighbors gno://notes/llm-memory.md
gno graph --from gno://notes/a.md --to gno://notes/b.md
gno graph --include-similar --threshold 0.78
gno graph --dot > graph.dot
gno graph --mermaid
```

- Scope with `--collection`, `--limit`, `--edge-limit`, `--include-isolated`.
- Add semantic edges with `--include-similar`, `--threshold`, `--similar-top-k`.
- Explore locally with `--neighbors`, `--direction`, `--from`, `--to`, `--max-depth`.

Sync repairs affected incoming graph references across collections, including changed target identities and ambiguous names. Unchanged syncs skip the graph work, and after an interrupted sync the next run rebuilds the graph in full. No separate graph-rebuild command is needed.

## Services: serve and daemon

### gno serve

Starts the local browser workspace and REST API. Use it when you want visual search, browsing, graph exploration, editing, or API access. Default serve is the production bundle; `--dev` enables the development bundle with HMR.

```
gno serve
gno serve --dev
gno serve --port 8080
gno serve --detach
gno serve --status --json
gno serve --stop
```

### gno daemon

Runs the headless watch/sync/embed loop plus the resident MCP gateway at `/mcp`. Use it when your CLI and AI tools need fresh search results but you do not need the browser open.

The daemon picks up edits, editor atomic saves, renames, and folder deletions, and retries failed syncs. A change that keeps failing to sync is retried after 0.5 seconds at first, then twice as long each time up to 5 minutes, until a sync succeeds; new edits are still picked up right away. A file GNO cannot read at all (locked, password-protected, too large) is recorded once, the way `gno update` does, and tried again when the file changes, so it never causes repeated rescans. When it cannot tell exactly what changed, it resyncs the whole collection. This applies to supported local filesystems; some network and removable volumes are not covered.

The daemon also rechecks watched Context Capsules when documents they cite change, and after a restart it resumes without repeating work. Rechecks write no source or Capsule files and run no answer model.

```
gno daemon --detach
gno daemon --no-sync-on-start
gno daemon --status
gno daemon --stop
```

Lifecycle flags for both commands: `--detach`, `--status`, `--stop`, `--pid-file`, `--log-file`. `--json` is for `--status`. Serve and daemon are alternative owners of one resident index: a second process against the same data directory is rejected.

Background syncs and embedding wait while a CLI command is writing. A CLI write that overlaps a busy server or daemon reports `BUSY` (exit 4) at worst, never a raw `database is locked` error. A failing background embed pass backs off and parks after 5 failures in a row. `gno status`, `gno serve --status`, and `gno daemon --status` list these as background issues, together with an overrunning pass or a resident that does not answer within 500ms. See [resident background issues](https://gno.sh/docs/troubleshooting#resident-background-issues).

Reindex requests sent to a running server or daemon (MCP `gno_sync` and `gno_index`, or `POST /api/sync`) wait in a queue while another job runs instead of being refused. Requests for the same collection merge into one waiting pass, and a request can name just the files that changed. See [reindexing over MCP](https://gno.sh/docs/mcp#reindex) and [POST /api/sync](https://gno.sh/docs/api#sync).

Started on a [session archive](https://gno.sh/docs/sessions#automation-opt-in) config and index with automation profiles enabled, the daemon also runs due session schedules and pending imports (from schedules, the Claude Code SessionEnd hook, or an interrupted run) at startup and every 30 seconds through the ordinary `sessions import` path. `sessions automation enable` and `disable` take effect without a restart. A daemon on a config without automation profiles does nothing here, and `gno serve` never runs these imports. The daemon keeps answering MCP and status requests during a long import. If the archive is busy, the run is recorded as failed with reason `busy` and retried with backoff. Logs contain no session content. Check automation with `gno sessions status`; `gno daemon --status` does not show it. GNO never installs or starts the daemon for you.

CLI commands load their own models and do not use a running server or daemon. Serve and daemon load models on first use and keep them loaded during the [idle grace](https://gno.sh/docs/configuration#model-timeouts). The first request, and the first after an idle period, is slower because it loads the model. If model loading fails, GNO reports the error and does not retry on its own; send the request again. Hybrid fallback reports whether vector retrieval actually succeeded.

Stopping serve or daemon waits up to about 11 seconds for running work to finish or cancel. Completed checkpoints survive; unfinished embeddings resume on the next start. See [shutdown behavior](https://gno.sh/docs/architecture#resident) for limits.

## Agents, models, publishing, and maintenance

### gno mcp and gno skill

Use MCP when you want AI clients to call GNO tools automatically. Use skills when you want explicit `/gno` lookups with low context overhead.

```
gno mcp install --target claude-desktop
gno mcp install --target cursor --scope project
gno skill install --target all --scope user --force
gno skill paths
```

At user scope, the Claude target follows `CLAUDE_CONFIG_DIR` and the Codex target follows `CODEX_HOME` when they are set, as `gno agents` does: the skill goes to `$CLAUDE_CONFIG_DIR/skills/gno` or `$CODEX_HOME/skills/gno`. `gno skill uninstall` and `gno skill paths` resolve the same directories. A blank value counts as unset.

### gno agents

Install a versioned GNO protocol block into each detected harness's global instruction file (Claude Code, Codex, Cursor, OpenCode, Hermes, OpenClaw; Grok is covered via Claude) so agents know the retrieval ladder before they reach for the skill. Backup-first, idempotent, symlink-aware; `--dry-run` shows the diff and `--extra-dir` handles nonstandard layouts. Exit 1 on malformed markers or an outdated block, 2 when a file cannot be read or written; on failure the complete block is printed for manual use. `update` refreshes only files that already contain the block: a file without one is reported `absent` with a hint to run `gno agents install`, and is never written or created.

```
gno agents install
gno agents install --target claude --dry-run
gno agents install --extra-dir ~/.claude-instances/work-cli
gno agents verify --json
gno agents update
gno agents uninstall
```

### models, publish, bench, vec, cleanup

These are supporting commands for model files, shared artifacts, retrieval evaluation, vector index maintenance, and housekeeping.

```
gno models list
gno models use balanced
gno models pull
gno publish export atlas --out ~/Downloads/atlas.json
gno bench fixture.json --modes bm25,hybrid --json
gno vec sync
gno vec drop 9a8b7c6d5e4f
gno cleanup
gno completion zsh
```

`gno vec sync` repairs drift in the vector index after failed inserts, and `gno vec rebuild` rebuilds it in full. Run `gno vec sync` when `gno similar` returns nothing although embeddings exist. `gno vec drop` removes an abandoned shadow vector partition and its vectors, named by an id prefix of at least 8 characters from `gno status`. Status prints a drop hint for exactly the partitions drop accepts: shadow or legacy partitions this runtime does not read. Active partitions are refused, because another runtime may read them. See [Switching backend or Bun version](https://gno.sh/docs/troubleshooting#backend-switch).

`gno cleanup` deletes the documents of indexed collections the config does not list, then orphaned content, chunks, and vectors. Before deleting, it names each of those collections on stderr (`Deleting collections not in this config:`). It deletes whatever the config you pass omits, so run it with the config that owns the index. With `--json`, the announcement is `{"deleting": [...]}` on stderr and the result carries `droppedCollections` and the orphan counts.

## Global options and output flags

Global options work before the command name. Output flags are repeated on retrieval and read commands where they make sense.

- `--index <name>` — use a named index instead of `default`.
- `--config <path>` — load a specific config file. An index holding collections that config does not list is refused, never emptied; pair a second config with its own `--index`.
- `--offline` — use cached model files only.
- `--json`, `--md`, `--csv`, `--files`, `--xml` — structured output.
- `--verbose`, `--quiet`, `--no-color`, `--no-pager`, `--yes` — terminal and automation behavior.

Long terminal output honors `$PAGER`. Without an override, GNO uses `less -R` on Unix and a built-in less-compatible pager on Windows, including backward scrolling and search. Use `--no-pager` for automation or direct output.

The CLI flushes stdout and stderr before it exits, so large piped output such as `gno search --json | jq` arrives complete. A consumer that closes the pipe early, such as `| head`, still lets the command exit promptly with its own exit code. Structured errors follow the `error` output schema, which lists every CLI error code, including `BUSY` (exit 4).

## Typed metadata filters

Pass --filter JSON to search, vsearch, query, query diagnose, ask, and context build. Custom predicates intersect existing scope and fixed filters before candidate limits.

[Read the metadata guide: examples, operators, missing fields, limits, and recovery.](https://gno.sh/docs/typed-metadata)

## Agent session archive

gno sessions discover previews local Codex, Claude Code, OpenClaw, and Hermes session roots and never imports. On a dedicated archive config/index pair, sessions init, source add and remove, import (with --dry-run and --limit), status, and prune manage a manual, redacted archive. Nothing imports, watches, or schedules on its own unless you explicitly enable automation for a profile.

```
gno sessions discover
gno --config ~/gno-sessions/archive.yml --index sessions sessions init --archive ~/gno-sessions/archive --collection sessions-work
gno --config ~/gno-sessions/archive.yml --index sessions sessions source add codex --harness codex --path ~/.codex/sessions --collection sessions-work
gno --config ~/gno-sessions/archive.yml --index sessions sessions import --source codex --dry-run
gno --config ~/gno-sessions/archive.yml --index sessions sessions import --source codex --json
gno --config ~/gno-sessions/archive.yml --index sessions sessions status
```

Exit codes: 1 validation (including a selection with no supported session format), 4 busy, 2 for an unavailable source, a failed import or automation run, or a hook that was not accepted; the [error-code table](https://gno.sh/docs/sessions#error-codes) and [troubleshooting](https://gno.sh/docs/sessions#troubleshooting) live in the [session archive guide](https://gno.sh/docs/sessions), with the config/index binding, receipts, and redaction limits.

### gno sessions automation

Opt-in hooks and daemon schedules for registered sources. Every trigger is off until you enable it; the imports always go through sessions import. Full behaviour: [Automation](https://gno.sh/docs/sessions#automation-opt-in).

```
A="gno --config ~/gno-sessions/archive.yml --index sessions"
$A sessions automation set claude --source claude-code [--cadence 30m] [--limit 200] [--retries 3]
$A sessions automation preview claude [--settings <file>]
$A sessions automation enable claude --hook claude-code [--settings <file>]
$A sessions automation enable claude --schedule --cadence 30m
$A sessions automation run claude
$A sessions automation disable claude [--hook] [--schedule]
$A sessions automation remove claude
```

| Subcommand          | Description                                                                                                                                                     |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `set <profile>`     | Create or reconfigure a profile: `--source <id>` (repeatable), `--cadence`, `--limit`, `--retries`. Enables nothing.                                            |
| `preview <profile>` | Sources with paths, destinations, the exact hook command and settings file, schedule, budget, daemon prerequisite.                                              |
| `enable <profile>`  | `--hook claude-code` installs the owned SessionEnd entry; `--schedule --cadence <n>s\|m\|h\|d` (min `1m`) turns on ticks.                                       |
| `run <profile>`     | Run the profile now through the importer (exit 4 `SESSIONS_BUSY` when the archive is busy, and the busy run is recorded; exit 2 when the run failed otherwise). |
| `disable <profile>` | Pause: switch triggers off (all, or `--hook` / `--schedule`), remove the owned entry, clear pending work.                                                       |
| `remove <profile>`  | Uninstall owned integrations and delete the profile; archives are kept.                                                                                         |

All subcommands accept `--json`. `run --json` prints the `sessions-automation-run` object. `sessions status` includes an automation block with daemon availability and, per profile, state, hook and schedule switches, pending and running work, last run, last success, next due time (only with a running daemon), and a recovery action; text output shows times in your local timezone.

### gno sessions hook

```
gno --config ~/gno-sessions/archive.yml --index sessions sessions hook claude-code --profile claude
```

The command a Claude Code SessionEnd hook runs; `automation enable --hook` installs it. It reads the event on stdin, durably marks the profile pending and prints one line: `accepted (… pending, not yet archived …)`, `skipped (…)`, or `not accepted (…)` with exit 2. It never imports. Set `GNO_SESSIONS_HOOKS=off` to make every installed hook return immediately. An unknown profile is reported as `skipped (… unknown_profile)`, a profile whose hook is off as `skipped (… hook_disabled)`. An explicit `--settings` other than the default location must name an existing file (VALIDATION).
