pinky CLI Reference

All pinky subcommands, what they do, and their flags. Generated from the binary's --help (pinky <command> --help always gives the canonical version).

Usage: pinky [OPTIONS] <COMMAND>

Global flags (apply to all commands)

FlagWhat it does
--db <path>SQLite index to use. Defaults to the central ~/.pinky/brain.db (all projects, partitioned by scope); PINKY_DB or --db override it.
--hash-embedUses the deterministic embedder (without downloading the ONNX model). Also enabled via the PINKY_HASH_EMBED env var. Ideal offline/CI.
--jsonJSON output, for scripts. In search it also disables telemetry logging (programmatic use).
--version / -VBinary version.
--help / -hHelp (for pinky or a subcommand).

pinky eval — retrieval quality gates

pinky eval testdata/golden.json --min-hit-rate 0.9 --min-mrr 0.85
pinky eval testdata/golden.json --matrix          # every variant, side by side
pinky eval testdata/golden.json --expand          # gate on hybrid+expand

--matrix compares lexical | hybrid | ±rerank | ±decay | +expand so each retrieval feature is measured on its own. The thresholds gate hybrid by default and hybrid+expand with --expand — CI runs both, because the expansion takes result slots and has to earn them.

testdata/golden-graph.json holds cases answerable only by following an edge. Read its _comment before trusting a number from it: a ten-document corpus cannot express "unreachable", so the gate that actually measures those cases is cargo test -p pinky-core --test graph_recall.

pinky graph — inspect the knowledge graph

pinky graph of pool-postgres                 # what this entry is connected to
pinky graph of --file src/db.rs              # what the brain knows about a code file
pinky graph of --file src/db.rs --json

of <slug> lists the entry's edges with their kind and confidence (extracted / ambiguous) and the evidence behind each one — the raw [[target]], the code file, or the superseded path. Repeated evidence is collapsed (+N more): two files naming the same pair are two facts, but still one relation.

build recomputes everything — edges, then communities and centrality over them. reindex already does it; run it by hand after a backlinks scan or to refresh a shape that went stale (a save updates the edges, not the clusters).

report writes the shape of the brain in prose — clusters, the entries everything hangs off, what is connected to nothing, and the links that point nowhere. --out GRAPH_REPORT.md to a file, stdout otherwise. It reads only: what you see is what the last build computed.

communities lists the clusters biggest-first: label, size, and the entry everything in it hangs off. Labels come from the members' own tags, hubs from betweenness centrality — no model involved in either.

of --file <path> resolves that file's // Brain: <slug> breadcrumbs to entries and, if there is room left, follows one wikilink hop. Accepts absolute paths (what an editor or hook knows) against the relative paths the scan stored. Neither form uses embeddings.

Projects & the active project

Pinky keeps one central index (~/.pinky/brain.db) holding every project, partitioned by scope, plus a persisted active project — so most commands don't need --project/--db.

pinky project <action>

ActionWhat it does
add <name> [--root <dir>]Register a project (whose <root>/documentation/ holds its .md) and make it active.
listList registered projects (the active one is marked *).
use <name>Switch the active project.
remove <name>Remove a project from the registry (its .md files are untouched).
currentPrint the active project.
import <root> --name <name>Register a project and index its documentation/ into the central index.

reindex, search, save, new and watch default to the active project when --project is omitted. Override with --project <name>, target the shared scope with --global, and (on search) span every project with --all. By default a search covers the active project plus global.

Interactive console

Running pinky with no subcommand opens an interactive terminal: a project selector, live search, an entry browser with .md preview, stats, and config (language / embedder). Press ? inside for the keybindings.

Index

pinky reindex <path> [--project <name>]

Reindexes every .md under <path>. Incremental: skips the ones that didn't change (by content_hash) and removes from the index the ones that no longer exist. With --project the entries stay in the project:<name> scope; without it, in global.

pinky reindex documentation --project sgsvp

pinky watch <path> [--project <name>]

Watches the folder and reindexes incrementally when it detects changes in .md. Blocks until Ctrl-C.

pinky watch documentation

pinky sync [--dir <folder>] [--push]

Syncs the global brain via git: git pullreindex → (with --push) git push. The default folder is ~/.pinky/brain; its .md are indexed into the central ~/.pinky/brain.db under the global scope (alongside the projects).

pinky sync --push

pinky search <query...> [options]

Hybrid search (BM25 + vector, RRF fusion). Metadata filters and opt-in rerank.

FlagWhat it does
--limit <n>Number of results (default 10).
--rerankLightweight lexical rerank (favors exact phrase in title/snippet).
--linksProximity boost in the [[wikilinks]] graph (Obsidian interop): re-ranks by promoting what is linked to/from the strongest results.
--project <name>Filter by project. If omitted, searches the active project + global.
--globalSearch only the global (cross-project) scope.
--allSearch across every project and global (no scope filter).
--type <type>Filters by type: gotcha | pattern | decision | diary | guide | note.
--tag <t>Filters by tag (repeatable; the entry must have them all).
pinky search "timeout closing the postgres pool"
pinky search "deadlock" --project sgsvp --type gotcha --json

Save / prepare

pinky save --title <t> [options]

Saves new knowledge: writes a .md with frontmatter and indexes it on the fly.

FlagWhat it does
--title <t>Title (required).
--body <md>Markdown body. If omitted, it's read from stdin (for pipes).
--type <type>gotcha | pattern | decision | diary | guide | note (default note). Normalized and validated.
--tag <t>Tags (repeatable).
--project <name>Project (scope).
--dir <folder>Where to write the .md (default documentation).
--no-fileSaves only in the DB, without .md (careful: a reindex would remove it).
pinky save --title "Reintento de templates" --type pattern --tag whatsapp --body "Backoff exponencial…"
echo "cuerpo largo…" | pinky save --title "Nota" --type note

pinky init [ruta]

Prepares a project: creates documentation/ (+ diary/), registers the MCP in .mcp.json with relative paths (relocatable) and leaves a guide. Doesn't use embeddings.

pinky init

Maintain (knowledge health)

pinky dedup [--threshold <0..1>]

Lists pairs of near-duplicate entries (cosine similarity > threshold, default 0.9). Deletes nothing — the decision to merge is manual.

pinky stale [--days <n>]

Lists entries with last_verified older than <n> days (default 180), or without a date, from oldest to newest. Doesn't use embeddings.

pinky telemetry

Shows the most retrieved entries (title + times + last time) and the ones that were never used (candidates for pruning). Doesn't use embeddings.

pinky lint [folder]

Validates the .md files: reports frontmatter that would degrade silently (invalid YAML, malformed type/dates). Exits ≠0 if there are errors → suitable for CI.

pinky redact [folder] [--dry-run]

Replaces credentials (sk-ant-…, ghp_…, AKIA…, xoxb-…, a postgres://user:pass@… password, a JWT, a PEM private key) with …REDACTED in the .md files.

Everything saved from now on is already redacted at write time — pinky save, brain_save and brain_update all pass through the same seam, and a reindex redacts before it touches the index. This command is the backfill for knowledge saved before that existed.

--dry-run writes nothing and exits ≠0 when it finds something (so it can gate a pipeline); start there. A real run archives each original under .archive/ before rewriting, so it is reversible, and exits 0. Reindex afterwards.

pinky redact ~/.pinky/brain --dry-run    # audit
pinky redact ~/.pinky/brain              # fix (originals in .archive/)

pinky evergreen <file>

Validates that a doc (e.g. CLAUDE.md) is evergreen: flags volatile data (line number, LOC, file:line). Exits ≠0 if it finds any.


Scans a code tree looking for // Brain: <slug> markers and populates the repo's backlinks (default default).

Lists the code (file:line) that references a <slug>.

pinky backlinks scan ./src --repo miapp
pinky backlinks of pool-postgres

Diary rollups

pinky rollup <dir> [--period week|month] [--out <file>]

Aggregates the diaries (YYYY-MM-DD.md) of a folder into a deterministic markdown summary (no LLM). --period default week; --out writes to a file instead of stdout.

pinky rollup documentation/diary --period month --out RESUMEN.md

Diagnostics

pinky stats [--value]

Number of indexed entries and chunks. With --value, the report that answers "what is the brain giving me?": real usage (retrievals, sessions, corpus coverage), confirmed usefulness (explicit agent feedback or the implicit correlation from the stop hook: served entries whose file the agent actually read), flagged noise, top confirmed value, and never-used entries. No embeddings; with --json, tooling-friendly.

pinky doctor [--airgap]

Environment check: binary version, sqlite-vec, schema version, entries/chunks, and index model vs. active embedder (warns if they don't match). Tolerates the index not existing (tells you what to run). With --json, suitable for monitoring.

With --airgap, each check answers a single question: "would this need the network?". It verifies the model is already cached (or that you use --hash-embed, which needs none) and that the index opens healthy. It exits with an error if anything would need the network — suitable for a CI gate or to validate an air-gapped deployment before disconnecting it. It does not build the embedder (building it could trigger the model download, exactly what an air-gap can't do).


pinky understands Obsidian-style [[wikilinks]] in your notes' bodies:

  • pinky search <q> --links: enables a proximity boost in the wikilinks graph. It re-ranks results by promoting what is linked to/from the strongest hits — 80% of a knowledge graph's value without dragging in a graph DB. It's opt-in: the default search doesn't change.
  • pinky lint reports broken wikilinks (a [[target]] that resolves to no note) as a warning, never an error: a vault lives with loose links to notes not yet written. Targets resolve by path or basename (as in Obsidian), case-insensitively.

Backup

pinky snapshot <dir> [--out <dir>] [--keep <n>]

Verifiable backup of the brain: a tar.gz with every file in the folder (including .archive/; never brain.db* or .git/) plus a manifest with the SHA-256 of each. The freshly written archive is re-read and verified whole before being declared good. Default destination: ~/.pinky/snapshotsoutside the working tree, to survive an rm -rf of the repo (the threat model is an agent with write access). With --keep N it prunes the oldest snapshots.

pinky restore <archivo.tar.gz> [--to <dir>] [--force]

Restores a snapshot with verify-then-write: it extracts to a temp dir, verifies EVERY checksum against the manifest, and only then moves to the destination — a tampered or truncated file doesn't write a single byte. Without --force it won't overwrite an existing folder; with --force, the previous one is kept at <dest>.pre-restore (nothing is ever destroyed). Afterward: pinky reindex (the index isn't backed up, it's derived).


Retrieval quality

pinky eval <golden.json> [--k <n>] [--min-hit-rate <x>] [--min-mrr <x>] [--matrix] [--mine]

Measures retrieval quality against a golden set of gold-standard queries: reports hit@k, MRR and nDCG. With --min-hit-rate/--min-mrr, it exits with code 1 if it drops below the threshold → gates the build in CI on a regression.

FlagWhat it does
--matrixRuns the variant matrix (lexical | hybrid | ±rerank | ±decay) and prints the comparison table — measures what each ranking feature contributes in isolation. Thresholds gate on hybrid.
--mineProposes new golden cases from the real queries in telemetry (the usage table) and appends them to the golden set after terminal confirmation. Does not use embeddings.
pinky eval testdata/golden.json --min-hit-rate 0.95 --min-mrr 0.9
pinky eval testdata/golden.json --matrix     # do rerank/decay help or hurt?
pinky eval testdata/golden.json --mine       # the golden set grows with real usage

Utilities

pinky completions <bash|zsh|fish>

Prints the autocompletion script for your shell.

pinky completions zsh > ~/.zfunc/_pinky

pinky update [--check] [--force]

Updates pinky to the latest version published on the CDN. It compares your version with the VERSION pointer and, if a newer one exists, runs the official installer (which verifies minisign signature + SHA-256 checksum), replacing the binary in its current folder. With --check it only reports; with --force it reinstalls anyway. Needs curl and sh on the PATH.

pinky update --check
pinky update

The three pieces share the same index: CLI pinky (this), MCP pinky-mcp (for the agent: brain_search/brain_save/brain_stats) and hooks pinky-hooks (Claude Code). See HOW-IT-WORKS.md and CONFIGURATION.md.