원클릭으로
nn-guide
Use when you need to look up an nn command, flag, or usage pattern. Load with `nn skills get nn-guide`.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Use when you need to look up an nn command, flag, or usage pattern. Load with `nn skills get nn-guide`.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Use when after nn new or nn update to discover notes that should be linked to the modified note. Load with `nn skills get nn-link-suggester`.
Use when cleaning up a specific note or before promoting it — runs atomicity, link, and title checks. Load with `nn skills get nn-refine`.
Use when ending a session to consolidate captures, assess promotion eligibility, and update the daily page. For weekly review use --weekly; for daily page only use --daily; for lightweight mid-session capture use --partial. Load with `nn skills get nn-session-debrief`.
Use when asked to organise, capture, or link notes in the Zettelkasten. Load with `nn skills get nn-workflow`.
Use when about to take any action that introduces new information not already in the conversation. Load with `nn skills get nn-capture-discipline`.
Use when running a hygiene pass across multiple notes at once — drafts, orphans, long notes, or a topic cluster. Load with `nn skills get nn-refine-workflow`.
| name | nn-guide |
| description | Use when you need to look up an nn command, flag, or usage pattern. Load with `nn skills get nn-guide`. |
| when_to_use | When you need to look up an nn command, flag, or usage pattern. Invoke with /nn-guide. |
Reference for nn commands, flags, and LLM usage patterns.
--json Machine-readable JSON output
--no-color Disable ANSI color
-q, --quiet Suppress progress/info output
--notebook Select a non-default notebook (name from config)
Create a new note.
nn new --title TEXT --type TYPE [--tags TEXT] [--content TEXT] [--no-edit]
[--link-to ID --annotation TEXT]
[--from-stdin]
[--from-file PATH]
[--expires YYYY-MM-DD]
[--expires-when "condition text"]
--type is required: concept | argument | model | hypothesis | observation | question | protocol--no-edit skips $EDITOR launch (always use in non-TTY/LLM context)--content TEXT sets the note body directly--from-stdin reads the note body from stdin--from-file PATH scaffolds the note body from nn ast output for a source file (sets title to filename if not given)The five types cover the epistemic roles a note can play (after Ahrens, How to Take Smart Notes):
| Type | Use when the note… | Example title |
|---|---|---|
concept | defines or explains a single idea, term, or principle | "The Atomicity Principle" |
argument | makes a claim and supports it with reasoning | "Atomicity enables reuse across contexts" |
model | describes a framework, pattern, or mental model | "The Zettelkasten as a second brain" |
hypothesis | states an untested conjecture worth investigating | "Dense linking predicts note longevity" |
observation | records a concrete fact, datum, or empirical finding | "Luhmann produced 90,000 notes over 40 years" |
question | poses an open question that the graph should eventually answer | "Why did Luhmann avoid hierarchical folders?" |
protocol | specifies an imperative procedure the LLM should follow in this notebook | "When creating a hypothesis, immediately link it to its source observation" |
Decision heuristic: if you're not sure, ask — is this a definition (concept), a claim with support (argument), a framework (model), a guess to test (hypothesis), something I witnessed/measured (observation), an open question (question), or an operating instruction for the LLM (protocol)? If none fit cleanly, the note may not be atomic yet.
Print note content to stdout. Accepts a full ID or a title substring.
nn show <id-or-title> [--depth N] [--json]
nn show --linked-from <id>
nn show --global
--global shows all global protocol notes (type:protocol with no outgoing governs links) in one command, each with the derivation instruction appended. Replaces the two-step nn list --global --json + nn show <id> pattern. Also appends a ## Reminders block listing the body of any non-expired notes tagged reminder.
If the query doesn't match an ID exactly, nn searches note titles case-insensitively.
If multiple titles match, the command lists the candidates and exits with an error — use
the full ID to disambiguate.
Graph neighborhood in plain-text output: nn show <id> now includes two navigation aids in its plain-text output:
## Links section renders each outgoing link as [[ID|Title]] instead of bare [[ID]], so target note titles are immediately readable without a separate lookup.## Backlinks (N) block is appended listing all notes that link to the shown note, each with its annotation. This replaces the need for a separate nn backlinks <id> call when exploring the local graph.These additions appear only in plain-text output (--json is unaffected).
--depth N traverses outgoing links from the given note up to N hops, collecting all
reachable notes and printing them as a single concatenated Markdown document separated by
---. Useful for loading a coherent subgraph as context for an LLM.
nn show <id> --depth 2 # root + 2 hops of outgoing links
nn show <id> --depth 1 --json # JSON array with depth field per note
--json with --depth returns an array of note objects in BFS order, each with an added
depth field (0 = origin note, 1 = direct links, etc.).
List and filter notes.
nn list [--tag TEXT] [--type TYPE] [--status STATUS]
[--linked-from ID] [--linked-to ID] [--orphan] [--global] [--long]
[--has-url] [--url-contains STRING]
[--search TEXT] [--similar ID] [--sort FIELD] [--limit N] [--json]
--search TEXT performs a ranked case-insensitive search across note title and body. Title matches rank above body matches. Notes with more inbound backlinks receive a log-scale centrality boost on top of BM25, so well-linked notes surface above equal-content orphans. The score field in --json output reflects both BM25 relevance and centrality.
--similar ID ranks all notes by BM25 similarity to the given note's title and body, excluding the note itself. Use for serendipitous discovery — find notes that share vocabulary with a given note but have no explicit link. Composes with --status, --tag, --type, --limit, --json. When --similar is active, --sort is ignored (similarity ranking takes precedence).
nn list --similar <id> # notes most similar to <id>
nn list --similar <id> --limit 5 # top 5 most similar
nn list --similar <id> --status permanent --json
--sort FIELD sorts results: title (alphabetical), modified (most-recently-modified first), created (default, most-recently-created first). Applied after filtering and ranking. Ignored when --similar is active.
--global returns protocol notes with no outgoing governs links — protocols that apply universally to the entire notebook rather than governing specific notes. Distinct from --orphan: a global protocol is intentionally universal, not forgotten.
--long filters to notes whose body exceeds the atomicity threshold (2000 chars). Use to find notes that have grown too large to split.
--has-url filters to notes containing at least one http:// or https:// URL. Use to find notes with external references.
--url-contains STRING filters to notes containing a URL that includes the given string. Only matches within actual URLs (requires http:// or https:// prefix) — bare text occurrences are ignored.
nn list --has-url # all notes with any URL
nn list --url-contains "github.com" # notes linking to GitHub
nn list --has-url --search "auth" # URL-containing notes matching "auth"
--older-than N filters to notes not modified in the last N days (age-based staleness). Uses the same thresholds as nn show freshness: 3 days = aging boundary, 14 days = stale boundary.
nn list --older-than 14 # notes not touched in 14+ days (stale tier)
nn list --older-than 3 # notes not touched in 3+ days (aging + stale)
nn list --older-than 14 --type concept --json
--expired filters to notes with an expires date set and in the past. Use to find notes marked for deletion.
--has-expires filters to notes with an expires date set (any date, past or future). Use to see all time-bounded notes.
Expiration fields: Notes support two complementary expiry mechanisms:
expires: YYYY-MM-DD — date-based; automated by --expired filter and reviewexpires_when: "condition" — semantic condition (e.g. "when the auth PR is merged"); surfaces in nn review under Pending conditions as a checklist for the reviewer to evaluatenn review also surfaces Expiry candidates: observation notes older than 30 days with no expiry set and not permanent — use to identify notes that should have been time-bounded.
nn list --expired # notes past their expiration date
nn list --has-expires # all notes with an expiration date
nn list --has-expires --json # machine-readable expiring notes
--has-open-items filters to notes with at least one unchecked checkbox (- [ ]). Use to find notes with pending work items.
--unblocked filters to notes that have at least one requires link and whose required targets are all done (no unchecked checkboxes). A required target with no checkboxes is considered done vacuously — a warning is emitted to stderr in that case. Use to find notes that are now actionable because their prerequisites are complete.
--no-inbound filters to notes with zero inbound links. Stricter than --orphan (zero links in either direction) — use to find notes nothing references that still have outbound links.
--unactioned filters to notes that were accessed via nn show but have had no git commit touching their file since the last access. Advisory — requires access.log. Use to surface notes the LLM read but never updated. (Previously named --stale.)
Filters compose: nn list --search "implicit" --type concept --sort modified works as expected.
nn update-link <from-id> <to-id> [--annotation TEXT] [--type TYPE] [--status draft|reviewed]
nn bulk-update-link <from-id> --to <id> [--type TYPE] [--annotation TEXT] [--status draft|reviewed] [--to <id> ...]
Update annotation, type, and/or status of existing links in place — no unlink/relink needed. At least one change flag is required. Only specified fields are modified; unspecified fields are preserved.
--status reviewed signs off a draft link as human-endorsed. Use after verifying LLM-suggested links.
nn bulk-update-link applies all updates in a single git commit. --type and --annotation are paired with --to by position; if provided, their counts must match --to. --status applies to all --to targets.
nn link <from-id-or-title> <to-id-or-title> --annotation "relationship description" --type TYPE [--status draft|reviewed]
nn unlink <from-id-or-title> <to-id-or-title> [--type TYPE]
nn bulk-link <from-id> --to <id> --annotation "..." --type TYPE [--status draft|reviewed] [--to <id> --annotation "..." --type TYPE]...
nn link and nn unlink accept title substrings for both arguments. nn bulk-link requires IDs.
nn unlink --type TYPE removes only edges of that type between the pair; without --type, all edges between the pair are removed. Multiple typed edges between the same pair are allowed (uniqueness is (from, to, type)).
[[id]]inline references are presentational only. Writing[[20260423-1234]]in a note's prose body does not create a graph edge — it is not parsed bynn graph,nn backlinks,nn path, ornn links. Usenn linkto create edges. This is intentional: the link graph is the authoritative record of relationships, not the prose.
Both --annotation and --type are required. A bare link is a schema violation.
Canonical types: refines, contradicts, source-of, extends, supports, questions, governs, requires.
requires — note A requires note B means A cannot be acted on until B is complete. Completion is derived from B's checkbox state: done when all - [x] (or no checkboxes, vacuously). Used with nn list --unblocked to surface actionable notes.
--status defaults to draft. Pass --status reviewed when a human is explicitly creating and endorsing the link at creation time.
nn bulk-link creates all links in a single git commit. --to, --annotation, and --type are paired by position; counts must match. --status applies to all targets.
nn graph [--json]
JSON output: { "nodes": [...], "edges": [...] }
nn graph show --focus <id> [--depth N] [--format text|json]
Renders a subgraph centered on <id>. BFS depth defaults to 2. Use --format json for structured output. Prefer this over nn graph when exploring a note's neighborhood — it scopes the result to the relevant region rather than exporting the whole graph.
nn status [--json] [--hubs N]
Reports: total notes, orphan count (with IDs/titles), draft count, broken links, draft link count, long notes, hub notes.
--hubs N overrides the default of 5.status: draft — links not yet human-endorsed.--json output adds: "draft_links": N, "long_notes": [{"id": "...", "title": "...", "body_len": N}], "hub_notes": [{"id": "...", "title": "...", "degree": N}]
nn links <id> [--type TYPE] [--status draft|reviewed] [--json]
Lists outgoing links from a note with their annotations. --type filters by relationship type. --status filters by link status.
Link status: draft (default for new links — not yet human-endorsed), reviewed (human has verified the relationship). Legacy links without a status field are treated as reviewed for backward compatibility.
Text output: one entry per link — targetID title {status}\n [type] annotation (status and type shown when present)
--json output: [{"id": "...", "title": "...", "annotation": "...", "type": "...", "status": "..."}]
Triage draft links: nn links <id> --status draft shows only unreviewed links for a specific note.
nn path <id-a> <id-b> [--json]
Find and print the shortest undirected path between two notes via the link graph (BFS). Returns an error when no path exists.
Text output: each note on its own line with an → separator between hops.
--json output: [{"id": "...", "title": "..."}] — ordered path from A to B.
nn clusters [--min N] [--singletons] [--json]
Detect topological clusters of notes using label propagation. Each note starts with its own label and iteratively adopts the most common label among its linked neighbours.
--min N omits clusters smaller than N notes (default: 2). Notes with no links are singletons and omitted by default.--singletons includes singleton clusters (notes with no links).Text output: one cluster per block — cluster N (K notes):\n ID Title\n ...
--json output: [{"notes": [{"id": "...", "title": "..."}]}]
nn ast <file> [--json] [--refs] [--root DIR]
Print a compact structural outline of a source file (imports, types, functions, constants). Uses gotreesitter (pure Go) to parse the file.
Supported languages: Go, Python, JavaScript, TypeScript, Rust, Java.
Text output always appends a ## Related notes section with BM25-matched nn notes per symbol and the standard resolution instruction. Use --json for symbol-array-only output without the footer.
Text output:
file: src/backend/gitlocal.go language: go
imports: fmt, os, path/filepath, ...
type Backend struct {
func (b *Backend) Write(n *note.Note) error {
...
## Related notes
- [[20260630…|gitlocal RMW lock pattern]] [likely relevant]
Resolve each related note before the next action — run `nn show <id>` to open...
--json output: [{"kind": "...", "name": "...", "signature": "...", "line": N}] (no footer)
--refs searches for name-match references to every symbol in the outline across the codebase rooted at --root (default: .). Emits one references to "X" section per symbol. Name-match only — not symbol-resolved, may include false positives. Prefer nn trace when you need call-graph traversal rather than text matches.
nn ast src/backend/gitlocal.go --refs --root ./
nn tee
Reads stdin, writes it unchanged to stdout, and prints BM25-matched related notes to stderr. Pipeline-transparent — downstream commands receive stdin byte-for-byte; note output never appears on stdout.
Use nn tee when:
curl <url> | nn tee | jq .ps aux | nn teeLarge inputs are truncated to 4096 bytes for the BM25 search window; stdout receives the full content.
stderr output format:
## Related notes
- [[ID|title]] [likely relevant]
Resolve each related note before the next action...
LLM usage note: prefer nn tee over manually running nn list --search after fetching content — nn tee surfaces notes in one step and keeps the pipeline intact for downstream processing.
nn trace <root-dir> --symbol <name> [--symbol <name> ...] [--depth N] [--json] [--show-unresolved]
Syntax-aware call graph from one or more entry-point symbols. Uses gotreesitter to index all definitions in <root-dir>, then DFS-traces calls from each --symbol up to --depth hops (default 3).
Prefer nn trace over nn grep when you want to understand how a symbol is called or what it calls across files — trace follows actual call edges rather than text matches.
Each resolved node is annotated with related nn notes via BM25 (same mechanism as nn grep). After the tree, a ## Related notes section lists all surfaced notes with the standard resolution instruction.
Ambiguous receiver annotation: when a method call obj.method() resolves to N > 1 definitions (because the receiver type is unknown), each expanded candidate is marked [receiver: obj, N candidates — type-unqualified]. This signals that those branches may be false positives — the call is real but the targets are uncertain.
Human-readable output (default):
AddLink (method) [internal/backend/gitlocal/gitlocal.go:288]
note: [[20260630…|gitlocal RMW lock pattern]]
→ acquireLock (function) [internal/backend/gitlocal/gitlock.go:26]
→ Read (method) [internal/backend/gitlocal/gitlocal.go:109] [receiver: g, 3 candidates — type-unqualified]
--json output: {"nodes": [...], "edges": [...]} — each node has nn_notes, ambiguous_receiver, and receiver fields.
--show-unresolved: include stdlib/external leaves (default off; always in JSON with resolved: false).
nn trace ./internal/backend/gitlocal --symbol AddLink --depth 3
nn trace ./cmd/nn/cmd --symbol newGrepCmd --json
nn update <id-or-title> [--title TEXT] [--tags TEXT] [--tags-add TAG] [--tags-remove TAG]
[--content TEXT] [--stdin] [--append TEXT] [--replace-section HEADING]
[--type TYPE] [--status STATUS] [--no-edit]
Accepts a note ID or a title substring — if the substring matches exactly one note it is used; multiple matches returns an error. At least one change flag is required. --content/--stdin/--append are mutually exclusive.
| Flag | Effect |
|---|---|
--title TEXT | Replace note title |
--tags TEXT | Replace all tags (comma-separated) |
--tags-add TAG | Add a tag without touching others (repeatable) |
--tags-remove TAG | Remove a tag without touching others (repeatable) |
--content TEXT | Replace note body entirely |
--stdin | Read replacement body from stdin (heredoc-safe, no shell escaping) |
--replace-section HEADING | Replace only the named ## Heading section; requires --content or --stdin; errors if heading not found |
--append TEXT | Append text to note body (double-newline separator) |
--status STATUS | Set note status: draft, reviewed, or permanent |
--expires YYYY-MM-DD | Set expiration date; note appears in nn list --expired after this date |
--expires-when TEXT | Set conditional expiration (plain text condition, e.g. "when the PR is merged") |
--no-edit | Skip $EDITOR (always use in non-TTY/LLM context) |
--since RFC3339 | Required. Reject update if note was modified after this timestamp; read modified: from nn show output. Omitting returns an error. |
Preferred LLM patterns:
# Update by title substring (no ID lookup needed)
nn update "my note title" --content "new body" --no-edit
# Multiline body without shell escaping
nn update <id-or-title> --stdin --no-edit <<'EOF'
Body with `backticks`, "quotes", and $pecial chars — no escaping needed.
EOF
# Replace a single section, preserve the rest
nn update <id-or-title> --replace-section "Why" --content "New explanation." --no-edit
# Additive tag operations
nn update <id-or-title> --tags-add "zettelkasten" --tags-remove "inbox" --no-edit
# Demote or reset status
nn update <id-or-title> --status draft --no-edit
Create a temporary reminder note that surfaces in nn show --global until its expiration date.
nn remind "TEXT" [--for N] [--expires YYYY-MM-DD]
observation note tagged reminder with permanent status--for N for N days, or --expires DATE for a specific date)## Reminders block of nn show --global until expired--global outputnn remind "Don't merge the auth PR until legal signs off" # expires tomorrow
nn remind "Check in with mobile team" --for 3 # expires in 3 days
nn remind "Hold off on deploys" --expires 2026-06-01 # expires on date
nn promote <id-or-title> --to reviewed|permanent
Status progression: draft → reviewed → permanent. Accepts title substring. For direct status assignment (including demotion), prefer nn update --status.
Show the git diff history for a single note — all commits that touched its file, with full patch output.
nn log <id-or-title> [--since DATE]
| Flag | Effect |
|---|---|
--since DATE | Limit history to commits after this date (e.g. 2025-01-01); passed directly to git log --since= |
Output is raw git log -p --follow for the note's filename. Use to audit what changed and when.
nn log <id> # full diff history
nn log <id> --since 2026-01-01 # only changes since Jan 2026
nn delete <id-or-title> --confirm
nn delete --from-stdin --confirm
--confirm is required. Warns if other notes link to the deleted note.
--from-stdin reads note IDs line-by-line from stdin and deletes each. Compose with nn list for batch deletion:
nn list --no-inbound --status draft --json | jq -r '.[].id' | nn delete --from-stdin --confirm
Quickly capture raw material (articles, quotes, observations) as a draft note.
nn capture --title TEXT [--content TEXT] [--type TYPE] [--tags TEXT]
observation. Override with --type concept|argument|...draft — the note is intended for LLM refinementTypical flow:
nn capture --title "..." --content "..." # capture → get ID
nn update <id> --content "..." --no-edit # LLM refines
nn suggest-links <id> # discover links
nn suggest-tags <id> # discover tags
nn tags # enumerate tag vocabulary
Format context for LLM-driven link suggestion. Does not call an LLM — emits a structured block for the LLM session to reason over.
nn suggest-links <id> [--limit N] [--format json]
Output contains:
## Focal note — full body of the focal note## Candidate notes (N total, M excluded — no term overlap) — BM25-ranked candidates, each with tags and a 200-char summary(already linked: <type>)Default limit: 20. The LLM reads the output and calls nn link or nn bulk-link for accepted suggestions.
Returns tag suggestions for a note based on BM25-similar notes that share tags the target lacks.
nn suggest-tags <id> [--json] [--min-notes N]
Only tags appearing in ≥ --min-notes similar notes (default: 2) are returned. The LLM applies accepted tags via nn update <id> --tags "...".
Lists all tags in the notebook with note counts.
nn tags [--json]
JSON output: [{"tag": "...", "count": N, "notes": ["id1", ...]}]. Use before tagging a new note to orient against the existing vocabulary.
Notebook health report formatted for LLM-driven analysis.
nn review [--format json]
Sections:
nn show freshness — aging (3–14 days) and stale (>14 days), sorted oldest-first within each bucketfriction-candidateprotocol-presence.logaccess.logA "dead-end" note has outbound links but no inbound links — it contributes to others but nothing points back to it.
Long notes (body exceeds 2000 bytes) are listed under Structural gaps — candidates for splitting into atomic notes.
Aging notes surface content that may be stale. Notes in the stale (>14 days) bucket should be verified before relying on them; notes in aging (3–14 days) may need a recheck. This mirrors the freshness: line injected by nn show.
--format json keys: growth, connectivity, drafts, long_notes, aging_notes, stale_notes, friction_candidates, protocol_telemetry, note_access
Format topic neighborhood context for LLM gap analysis.
nn gap <topic> [--limit N] [--depth N] [--format json]
Loads notes matching <topic> via BM25 search, then expands to their direct neighbors (depth 1 by default) via forward links and backlinks. Output:
## Topic notes (N matching "topic") — ranked by BM25 score## Neighborhood (N notes, depth D) — linked neighbors not in topic setThe LLM receiving this output identifies what is thoroughly covered, what is shallow, what is absent, and what questions the notes raise but do not answer.
Default limit: 20. Default depth: 1.
Format topic cluster context for LLM-driven Map of Content creation.
nn index <topic> [--limit N] [--format json]
Loads notes matching <topic> via BM25, then groups them into clusters using link-based label propagation (scoped to the topic subset). Output:
## Topic: "topic" (N notes) — all matching notes with summaries## Clusters (N) — grouped by link connectivityThe LLM names the clusters, identifies tensions and gaps, and creates an index note via nn new.
Default limit: 30. --format json keys: topic_notes, clusters
Return a randomly selected note. Optionally filtered.
nn random [--tag TEXT] [--type TYPE] [--status STATUS] [--json]
Returns one note at random from the notebook. All filters from nn list are supported.
Use for deliberate serendipity — re-encounter a forgotten note and consider whether it
connects to current work.
nn random # any note
nn random --status permanent # a random permanent note
nn random --tag philosophy --json
nn install-skills [--dest DIR] [--list]
Copies skill directories into ~/.claude/skills/ (or --dest).
~/.config/nn/config.toml:
[notebooks]
default = "personal"
[notebooks.personal]
path = "~/notes"
backend = "gitlocal"
Environment overrides:
NN_NOTEBOOK — select a named notebook (overrides default)NN_CONFIG_DIR — override config directory (useful for testing)---
id: 20260411120045-3821
title: "The Atomicity Principle"
type: concept
status: draft
tags: [zettelkasten, methodology]
created: 2026-04-11T12:00:45Z
modified: 2026-04-11T12:05:00Z
---
Body text.
## Links
- [[20260411090000-1234]] [extends] {draft} — provides the foundational philosophy this principle implements
Link format in plain-text show output: - [[target-id|Target Title]] [type] {status} — annotation (titles resolved at render time). In the raw file on disk, the format remains - [[target-id]] [type] {status} — annotation.
[type] optional: refines, contradicts, source-of, extends, supports, questions, governs, requires{status} optional: draft (default for new links), reviewed (human-endorsed). Absent = reviewed (legacy compat).Create and link in sequence:
nn new --title "Concept A" --type concept --content "..." --no-edit
# note ID from output: 20260411120045-0001
nn list --json | jq '.[].id' # find related note IDs
nn link 20260411120045-0001 <related-id> --annotation "extends this concept" --type extends
Load all global protocols at session start:
nn show --global
Find orphans before a review session:
nn list --orphan --json
Export graph for visualisation:
nn graph --json > graph.json
Discover related notes (no known query):
nn list --similar <id> --limit 10
Load a topic cluster as LLM context:
nn show <id> --depth 2
Explore a note's immediate graph neighborhood (single round-trip):
nn show <id> # shows body + resolved outgoing links + backlinks in one call
Serendipitous re-encounter:
nn random --status permanent