Command line

Search, read, list, tag, and edit your vault from the terminal. Pipe results into anything. Same SQLite index the app uses, no daemon, no auth, no cloud.

Install

Open Clearly → Settings → Command Line → Install. A symlink lands at ~/.local/bin/clearly — no sudo, no Homebrew, no second update channel. Add ~/.local/bin to your PATH if it isn't there:

export PATH="$HOME/.local/bin:$PATH"

Verify:

clearly status

Global flags

--vault <path>
Load a specific vault. Repeat to load multiple. Omit to auto-discover every vault Clearly has opened.
--format json|text
JSON (default) is structured snake_case for machines. Text is loose and tab-separated for humans. Pipelines should stay on JSON.
--bundle-id <id>
Override the app bundle identifier when running against a Debug build (com.sabotage.clearly.dev).

mcp

read & write

Start the Model Context Protocol stdio server, or inspect registered tools.

clearly mcp [serve | tools] [--read-only]

Subcommands

  • serve — start the stdio server. Default. Same as clearly mcp.
  • tools — print every registered tool's name, description, input schema, and output schema as JSON.

Examples

# Typical Claude Desktop config (claude_desktop_config.json)
"clearly": { "command": "/usr/local/bin/clearly", "args": ["mcp"] }

# List every registered tool
clearly mcp tools | jq -r '.[].name'

# Inspect the read-only-only set
clearly mcp tools --read-only

read

read

Read a note by vault-relative path, with optional line range. Returns content plus content hash, size, modified timestamp, parsed frontmatter, headings, and tags.

clearly read <path> [--start-line N] [--end-line N] [--in-vault NAME]

Examples

clearly read Daily/2026-04-17.md
clearly read Strategy/pricing.md --start-line 10 --end-line 40
clearly read Inbox/idea.md --in-vault Work | jq -r '.content'

list

read

List notes in loaded vault(s). Walks the filesystem fresh every call — results always reflect current on-disk state. Streams NDJSON.

clearly list [--under PREFIX] [--in-vault NAME]

Examples

clearly list
clearly list --under Daily/
clearly list | jq -r '.vault' | sort | uniq -c
clearly list --under Projects/ | jq -r '.relative_path' | xargs -I{} clearly headings {}

headings

read

Heading outline (H1–H6) for a note: level, text, and 1-based line number.

clearly headings <path> [--in-vault NAME]

frontmatter

read

Parsed YAML frontmatter as a flat key-value map. Empty map when the note has no frontmatter block.

clearly frontmatter <path> [--in-vault NAME]

tags

read

No argument: stream {tag, count} records across every vault. With a tag argument: stream every note carrying that tag. Tags come from inline #hashtags and YAML frontmatter tags:.

clearly tags                       # all tags with counts
clearly tags architecture          # all notes tagged #architecture
clearly tags | jq -s 'sort_by(-.count) | .[:20]'

create

write

Create a new note. Parent directories created automatically. Fails with exit 5 / note_exists if the path is already taken — use update to modify.

clearly create <path> (--content STR | --from-stdin) [--in-vault NAME]

Examples

clearly create Daily/2026-04-17.md --content "# Today\n\nNotes..."
cat draft.md | clearly create Inbox/draft.md --from-stdin
clearly create Notes/idea.md --content "..." --in-vault Work

update

write

Update an existing note in one of three modes. replace overwrites the whole file. append adds to the end. prepend inserts after the YAML frontmatter block (or at the top if there is none).

clearly update <path> --mode replace|append|prepend (--content STR | --from-stdin) \
                [--in-vault NAME] [--expected-content-hash <sha256>]

--expected-content-hash opts into optimistic concurrency — the call returns exit 5 / stale_content if the on-disk file has changed since the supplied hash, so a script can re-read and retry without clobbering a concurrent edit.

move

write

Move or rename a note within a vault. Vault-aware: reads every note that links to the source, rewrites those [[wiki-links]] to the new path (preserving heading anchors and aliases), then moves the file and updates the index without losing inbound link relationships.

clearly move <from-path> <to-path> [--in-vault NAME]

Examples

clearly move Inbox/draft.md Notes/published.md
clearly move Inbox/draft.md Archive/2026/draft.md

vaults

read

List loaded vaults as NDJSON: {name, path, file_count, last_indexed_at, bundle_id}. Use status for a single-document diagnostic snapshot. Vault add/remove lives in the app — the CLI subcommands are placeholders that exit 2 and point you to Settings.

clearly vaults                         # same as `clearly vaults list`
clearly vaults list --format text      # namepathfile_count

index

write

Vault index maintenance. rebuild performs a full filesystem walk and re-hashes every markdown file — use it after out-of-band file ops or to recover from a corrupted index.

clearly index                        # same as `clearly index rebuild`
clearly index rebuild --in-vault Work

status

read

One-shot diagnostic snapshot: binary version, configured bundle id, embedding model version, every loaded vault with file count and last-indexed timestamp. Single JSON document — intended for support tickets and human eyeballing.

clearly status
clearly status | jq '.vault_count'
clearly status --format text

Exit codes

0
Success.
1
General error (vault not loadable, internal failure).
2
Usage error (bad flags, missing required argument).
3
Not found (note doesn't exist, vault filter matches nothing).
4
Permission / sandboxing error (path outside vault, traversal attempt).
5
Conflict (creating a note that already exists).

Errors are written to stderr as JSON: {error: "<code>", message: "<human>", ...}.