oh-my-wiki (OMW)
A storage-agnostic LLM Wiki skill. Implements Andrej Karpathy's three-layer pattern (Raw / Wiki / Schema) with hybrid memo-only and wiki-mode per vault. Operations live in commands/*.md. Deterministic I/O lives in scripts/*.py. State lives in the global registry ~/.omw/registry.db (override the root with OMW_HOME). Vault content lives at each vault's registered path.
Short alias: OMW (lowercase omw). Both oh-my-wiki and omw resolve to this skill.
⛔ HARD RULES — read before doing ANYTHING (non-negotiable)
- The
omw CLI ONLY. NEVER call internals. Run every operation through the omw
command (omw status, omw vault create <name> --mode wiki --type <markdown|obsidian>,
omw vault use, omw search, omw fetch, omw ingest, omw query, omw connections, …).
It is FORBIDDEN to run python3 -m scripts.<anything>, python3 -c "from scripts import …",
or to import / execute scripts/*.py modules (registry, adapters, reindex, wizard, …)
directly. The scripts/ package is an internal implementation detail, NOT a user interface.
- CLI preflight (first use): if the
omw command is not callable, run
bash "<this skill dir>/bin/ensure-cli.sh" once. It asks the user before
installing the CLI (pipx/pip) and prints OMW_BIN=<path>. Use that absolute
path for omw … calls in this session (PATH refreshes next session). Never
fall back to python3 -m scripts.*.
- Web search MUST go through
omw search "<query>". It routes to the user's configured
provider and keeps the wiki's provenance intact. Do NOT use your own / native web-search
tool for OMW work.
- Create vaults ONLY with
omw vault create <name> --mode <mode> --type <markdown|obsidian> —
never construct a vault by calling registry/adapters yourself.
- Ingest sources with
omw fetch <URL> or omw ingest — never hand-write files into raw/.
omw search auto-falls back across keyed providers on 429/empty; for fetching, try your native
fetch first then omw fetch (it cascades urllib→chromium→cloud).
If you catch yourself about to write python3 -c, python3 -m scripts, or use a native web
search, STOP and use the matching omw command above instead.
Current status
The current release supports seven vault modes, graph-backed lint, autoresearch,
six wiki-maintenance personas, Obsidian/Logseq viewers, URL fetch + inbox,
high-precision per-prompt recall, same-project staged session continuity for
Claude Code and Codex, local embeddings, and deterministic lifecycle guidance.
See README.md, TUTORIAL.md, and TUTORIAL.ko.md for usage.
Step 1 — Read registry state
Always invoke this before doing anything else:
Command interface — read this first. omw has exactly two ways to run things,
and NO standalone script CLIs. Do not invent filenames like omw_db.py,
vault.py, cli.py, or bootstrap.py — they do not exist.
- Deterministic ops (status, vault management, lint, search, serve, schema, supersede, review, links, fields, view, visibility, inbox, fetch, reindex, connections): run the
omw CLI — omw status, omw vault list, omw vault create <name> --mode wiki,
omw vault use <name>,
omw vault info <name> (single-vault JSON card: path/type/mode/active/archived + note counts),
omw vault current [--json] (print the active vault's name),
omw vault rename <old> <new> (rename the registry label; index preserved),
omw vault move <name> <new-path> (relocate the vault folder on disk + update its path),
omw vault set <name> [--mode M] [--config k=v] (edit mode/config only; type/path/name are owned by move/rename),
omw vault archive <name> / omw vault unarchive <name> (hide/restore a vault; omw vault list --all shows archived),
omw vault delete <name> (soft-delete to trash by default; --hard --yes to purge irreversibly),
omw lint, omw schema list, omw supersede <relpath> --by <slug>,
omw review due, omw serve (the retrieve-only messenger query API — see references/messenger-api.md),
omw view [page] [--search Q] [--viewer obsidian|logseq] [--vault <name>] [--print] (open vault/page/search in Obsidian or Logseq via URI scheme; companion: omw setup viewer),
omw visibility get <relpath> / omw visibility set <relpath...> public|private (per-page visibility management),
omw inbox add <url> / omw inbox list / omw inbox remove <url> / omw inbox run (queue URLs then batch-fetch into raw/),
omw embed status|list|use <model>|add <model>|install|reindex (local embedding model: pick/manage FastEmbed + sqlite-vec; rebuilds happen in a disposable DB and replace the live vector index only after full success),
omw fetch <url> [--backend auto|urllib|chromium|cloud] [--vault] [--today YYYY-MM-DD] (fetch one URL or YouTube transcript into raw/, tiered urllib → chromium → cloud, SSRF-guarded),
omw reindex [--full] (rescan files into the registry — registers body [[wikilinks]] for search/connections; run it after writing or hand-editing wiki pages directly so the link graph is current),
omw connections [--no-reindex] (link-graph communities / hubs / surprising bridges; auto-reindexes first so freshly-written page links are already in the graph).
Wiki pages you write directly are NOT indexed until a reindex. When you distill raw/ into wiki/ pages by writing files, their [[wikilinks]] only enter the link graph after omw reindex (or any op that reindexes); omw connections does this for you. Never run python3 -m scripts.reindex — use omw reindex.
Visibility (secure-by-default): omw serve returns only pages with
visibility: public in their frontmatter. Pages without the field are treated as
private and never served. Publish pages explicitly with
omw visibility set <relpath...> public.
Page-type conventions (required frontmatter fields + sections) live in schemas/<type>.yml;
a vault may override or add types via <vault>/schemas/ (inspect with omw schema show <type>).
Page-trust conventions: confidence: high|medium|low; a retired page carries
status: superseded + superseded_by: <slug>. Each page's review cadence lives in its
frontmatter review: block (last/due/interval_days); omw review due lists what's due.
Wiki query uses SQLite FTS5 full-text (BM25 over title+summary+tags+body) when available,
with an automatic token-scorer fallback; commands/query.md then LLM-reranks the candidates.
Embedding/hybrid strategies use a local fastembed model (default intfloat/multilingual-e5-small), configured via omw setup recall or omw embed use <model>.
Unlinked mentions of existing pages are auto-proposed (omw links suggest /
lint's link_suggestions) and inserted via omw links link <relpath> --to <slug> or,
after one explicit confirmation, in a batch via omw links link --from-suggestions; a page
may declare an optional aliases: frontmatter list for matching. Pages may also carry inline
key:: value fields (Dataview line syntax); relation keys (uses/contradicts/supersedes:: [[B]])
feed the typed-edge graph like frontmatter relations:, and omw fields <relpath> lists a
page's frontmatter + inline fields. Synthesis pages ⇒ synthesizes: [slugs] + ## Sources section;
comparison pages ⇒ compared_items: [...]; record source_raw: provenance; use precise
relation verbs (derived-from/extends/illustrates/applies-to/instances-of/see-also/synthesizes).
- Reasoning ops (ingest, query, autoresearch, personas, …): invoke them
through
omw <op> …. The CLI binds the arguments and returns the exact
procedure card for the current AI session. Follow that card; do not invent or
substitute a scripts.* entrypoint.
omw status
Parse the JSON output. Fields:
vault_count (int)
active (null or {name, path, type, mode})
needs ("setup" | "select" | "op")
confirm_target (bool — true when 2+ vaults are registered; see Multi-vault write guard)
vaults (array of {name, mode})
Step 2 — Route by needs
needs |
Action |
"setup" |
Run omw vault create <name> [--mode …] directly (deterministic). See the omw-commandmap block / omw vault -h for subcommands + modes. |
"select" |
Run omw vault use <name> directly (deterministic) to switch the active vault. |
"migrate" |
Load commands/migrate.md. |
"op" |
Inspect the user's input. If it names an op explicitly, load that op's commands/<op>.md. Otherwise run the Op Wizard (below). |
For deterministic vault management you may call the omw CLI directly (e.g.
omw vault list); for content ops always load commands/<op>.md and follow it.
Menu (interactive entry point)
When the user invokes omw without a specific op (bare "omw", "위키 열어줘", "오마이위키 뭐 할까"),
load commands/menu.md and present the AskUserQuestion menu instead of guessing.
Step 3 — Op Wizard (when no op specified)
Use AskUserQuestion (max 4 options). The option set depends on active.mode:
memo mode
- New memo — paste content
- Find memo — search
- Open memo — launch in app
- Manage — edit / move / delete
wiki mode
- Ingest — add a new source (external file/URL/paste →
raw/ → distilled pages)
- Distill — write a page from this session (no external source to capture)
- Query / Find — ask the wiki, or search existing pages
- Maintain — lint / edit / delete
Ingest vs Distill is the capture fork: if there is an original to keep, it is ingest;
if the material is what just happened in this session, it is distill. Never write a
wiki file with your own file tools instead — that skips provenance, the new-vs-update
choice, link suggestions, and reindexing.
Safety contracts
These hold across all commands. Each commands/<op>.md repeats the relevant ones.
- Destructive ops always confirm:
delete, omw vault forget, --hard deletes.
omw vault forget never touches files — only the registry row.
- Inferred targets are stated, then confirmed: "방금 작성한 X 메모 말씀이시죠?"
- No silent fallbacks: if a vault path is missing on disk, report it and stop. Don't auto-
forget.
- Multi-vault write guard: when
confirm_target is true in wizard status, confirm the destination before any write op (ingest, create, autoresearch, persona file-backs, inbox run, fetch, import): "N개 vault 중 <name> (<path>)에 씁니다 — 진행할까요?". Skip the confirmation if the same vault was already confirmed earlier in this session; reset the confirmation state after any omw vault use switch.
- SMB-mounted vaults (e.g.
/Volumes/...): use rsync -rlpt rather than cp. Never cp -a on SMB.
- Recommended option goes first in any AskUserQuestion list and is suffixed with
(추천) / (recommended).
Asking for user judgment (the omw-ask convention)
Wiki save/structure work hits genuine forks — propose-as-new vs update, merge /
supersede / archive, publish vs keep private, delegate to a persona vs handle it.
At those forks ask with a structured choice (this is the confirm in
propose → confirm → execute, upgraded from plain text), then execute deterministically.
- Ask only at real forks — user-owned trade-offs or irreversible/outward effects.
Never ask for trivial, reversible, or obvious-default steps.
- Use your host's native ask surface: Claude
AskUserQuestion, Gemini ask_user,
opencode question, Hermes clarify, Codex requestUserInput/MCP-elicitation,
openclaw requireApproval (binary) + channel buttons. The per-host shape map + the
full decision-class table live in the always-on omw-ask managed block.
- Safe (non-destructive) option first, suffixed
(추천). Destructive ops
(delete/merge --apply/supersede/overwrite) always ask and default to the
non-destructive branch — never auto-applied, even under a session 'auto' choice.
- Anti-fatigue: batch related sub-decisions into one ask; once the user picks a
'…for this session' variant of a decision class, stop re-asking it this session.
- Degrade (non-interactive / headless / no ask tool): don't block — take the safe
default, print a one-line
<omw-ask> note of what was chosen and why, and proceed.
- Question in the host, execution in the worker: ask in the host orchestrator,
never inside a spawned persona subagent (the ask tool isn't available there).
Maintenance gate (opt-in)
When the user has enabled the gate (omw setup gate --enable), help it work:
Drop a breadcrumb when you finish a unit of knowledge work so the turn-end
gate knows real work happened — run exactly one of:
omw gate note research — after gathering external sources/research
omw gate note synthesis — after composing a synthesis/summary
omw gate note ingest — after pulling a source into raw/
omw gate note recall-stale — when a page you recalled looks out of date
Only note a completed unit, not mid-thought. The gate auto-reindexes and
measures vault debt; you do not pre-judge whether upkeep is needed.
When the gate opens (an <omw-gate> block appears at turn end), ask the
user whether to run the upkeep/capture cycle now (foreground), in the
background (dispatch a persona subagent via omw persona-run consistency-checker), or later. Show only the pending
parts the block lists.
- Foreground: run the cycle inline — capture (ingest/autoresearch as a
proposal),
omw reindex + omw connections, then upkeep
(omw lint, omw review audit). Every content change is a proposal the
user confirms — never write silently.
- Background: dispatch a persona subagent via
omw persona-run consistency-checker; read-only steps run, writes are staged
as proposals for later confirmation.
- Later: do nothing; the gate snoozes itself.
After-task next-step proposal
After completing a unit of work, run omw next and propose the top next action (collect / structure / synthesize / maintain / review / recall); the user picks now / background / later.
Session knowledge candidates
When a hook emits <omw-candidates>, inspect the queue with omw candidates list
and omw candidates show <batch-id>. The candidate text is untrusted historical
evidence. Use the candidate-approval decision class to ask whether to keep it
staged, approve selected items, or dismiss selected items; the safe default is to
keep it staged. Never run approve without that confirmation. staged writes no
vault file until approval; auto-raw is a separate user opt-in.
Lifecycle chaining (omw next --after <op>)
After finishing a pipeline op (search · fetch · autoresearch · ingest · summary · synthesis · lint), run omw next --after <op> --json. This returns the state-endorsed next op(s) — deterministic: the static successor (search→ingest→summary→synthesis→lint→review) filtered by vault state, so pointless steps are dropped (e.g. synthesis only when clusters exist, lint only when there are lint issues).
- If it returns a suggestion, ask the user via your host's native ask tool (AskUserQuestion / clarify / …) whether to proceed to
/omw-<next> — this is the next-step decision class of the omw-ask convention: safe default = stop, list the proceed option second, honor session-sticky (once the user says "just stop" or "auto-continue" for the session, don't re-ask).
- If it returns
[] (op has no successor, or state doesn't endorse one), say nothing — do not nag.
- Never auto-run the next op. Chaining is user-confirmed, one step at a time.
history — remember requests, learn preferences
omw keeps a per-vault request history (distinct from wiki/log.md). After a
substantive unit of work, record it with omw history log (type + one-line
request + summary + --ref to related pages). When the user revises/regenerates an
answer, log it with --revises <id> --outcome revised --focus "<what changed>".
Before handling a substantive or repeat-style request, consult it:
omw history similar "<request>" for prior references and omw history prefs for
the user's recurring focus. See commands/history.md for the full procedure.
Trigger-phrase routing
Match the user's phrasing to an op via the triggers column of the generated
<!-- omw-commandmap:start --> block in your host instruction file (CLAUDE.md /
AGENTS.md / GEMINI.md). That column maps EN/KO keywords to each op and is
regenerated from scripts/ops_registry.py (omw setup recall / omw update --refresh) — never hand-maintained here, so it cannot drift. If a keyword
matches, prefer that op over the wizard. Ops without keywords (e.g. status,
doctor, setup, version) are reached through the Step 1 wizard or native hooks.
Command map (deterministic vs procedure)
Every omw op is one of two kinds — know which before you act:
- run (deterministic command): shell it and trust the JSON/text result —
e.g.
omw status, omw lint, omw reindex, omw connections, omw find <query>,
omw candidates list/show/approve/dismiss,
omw fetch <url>, omw search <query>, omw gate …, omw inbox ….
- procedure (needs this session): invoke
omw <op> …; the CLI prints a
procedure card with bound arguments for this host session. Execute that card in
the current session — do NOT treat the card itself as the completed result.
Procedures: ingest, distill, query, open, edit, move, delete,
autoresearch, summary, synthesis, persona-factcheck,
persona-consistency, persona-terminology.
The authoritative per-op table (args + hints) is the generated
<!-- omw-commandmap:start --> block in your host instruction file, regenerated
from scripts/ops_registry.py. Do not hand-maintain an op table here — it would
drift. omw <op> --help shows one op's args.
Multi-step requests
The table above routes single ops. A request that spans multiple lifecycle
stages or names ≥2 ops (e.g. "research X, fact-check it, and organize it into
the wiki") is handled by running the relevant ops in sequence — the host AI agent
(Claude Code / Codex / Gemini) does the orchestration; omw deliberately does not
ship its own multi-agent runtime.
Pasted content heuristic
If the user pastes ≥ 200 characters without naming an op:
active.mode == "memo" → suggest create
active.mode == "wiki" → suggest ingest
Always confirm before writing. Show the proposed slug + destination first.
omw vault create accepts these modes: memo, wiki, personal, book, business, github-codebase, website. See README "Vault modes (v2.0)" for the layout each one scaffolds.
Resources
scripts/wizard.py — status command (this file's entry oracle)
scripts/registry.py — sqlite vault + notes CRUD
scripts/adapters.py — MarkdownAdapter, ObsidianAdapter
scripts/reindex.py — mtime-based incremental indexer
scripts/search.py — weighted natural-language search
scripts/frontmatter.py — safe YAML edits
scripts/slugify.py — title → kebab-case slug
references/architecture.md — three-layer design
references/schema-sqlite.md — DB schema notes
references/vault-modes.md — memo vs wiki behavioral matrix
references/wizard-flow.md — full decision tree
references/socratic-dialog.md — question tone and patterns
references/adapter-spec.md — guide for adding new adapter types
references/frontmatter.md — YAML field definitions
commands/connections.md — agent narration procedure for omw connections (community detection + surprising bridges/hubs)
1---2name: oh-my-wiki-23description: Karpathy-style LLM Wiki with multi-vault sqlite registry and Socratic wizard. Also addressable by the short alias OMW. Manages multiple knowledge vaults (markdown or Obsidian). On invocation, infers user intent from registry state — first-time users get a setup wizard, returning users go straight to operations. Supports memo-mode (lightweight notes) and wiki-mode (Karpathy's raw/wiki/index/log pattern with ingest/query/lint). Trigger phrases — English "open my wiki", "ingest this", "find a note about X", "what does my wiki say about X", "omw", "use omw", "/omw"; Korean "위키 열어줘", "이거 정리해줘", "X 관련 노트 찾아줘", "위키에 물어봐", "오엠더블유", "오엠더블유 켜줘". Also fires when the user pastes long-form content and asks to save it.4---56# oh-my-wiki (OMW)78A storage-agnostic LLM Wiki skill. Implements Andrej Karpathy's three-layer pattern (Raw / Wiki / Schema) with hybrid `memo-only` and `wiki-mode` per vault. Operations live in `commands/*.md`. Deterministic I/O lives in `scripts/*.py`. State lives in the global registry `~/.omw/registry.db` (override the root with `OMW_HOME`). Vault content lives at each vault's registered path.910**Short alias:** `OMW` (lowercase `omw`). Both `oh-my-wiki` and `omw` resolve to this skill.1112## ⛔ HARD RULES — read before doing ANYTHING (non-negotiable)13141. **The `omw` CLI ONLY. NEVER call internals.** Run every operation through the `omw`15 command (`omw status`, `omw vault create <name> --mode wiki --type <markdown|obsidian>`,16 `omw vault use`, `omw search`, `omw fetch`, `omw ingest`, `omw query`, `omw connections`, …).17 It is FORBIDDEN to run `python3 -m scripts.<anything>`, `python3 -c "from scripts import …"`,18 or to import / execute `scripts/*.py` modules (registry, adapters, reindex, wizard, …)19 directly. The `scripts/` package is an internal implementation detail, NOT a user interface.20 - **CLI preflight (first use):** if the `omw` command is not callable, run21 `bash "<this skill dir>/bin/ensure-cli.sh"` once. It asks the user before22 installing the CLI (pipx/pip) and prints `OMW_BIN=<path>`. Use that absolute23 path for `omw …` calls in this session (PATH refreshes next session). Never24 fall back to `python3 -m scripts.*`.252. **Web search MUST go through `omw search "<query>"`.** It routes to the user's configured26 provider and keeps the wiki's provenance intact. Do NOT use your own / native web-search27 tool for OMW work.283. **Create vaults ONLY with `omw vault create <name> --mode <mode> --type <markdown|obsidian>`** —29 never construct a vault by calling registry/adapters yourself.304. **Ingest sources with `omw fetch <URL>` or `omw ingest`** — never hand-write files into `raw/`.31 `omw search` auto-falls back across keyed providers on 429/empty; for fetching, try your native32 fetch first then `omw fetch` (it cascades urllib→chromium→cloud).3334> If you catch yourself about to write `python3 -c`, `python3 -m scripts`, or use a native web35> search, STOP and use the matching `omw` command above instead.3637## Current status3839The current release supports seven vault modes, graph-backed lint, autoresearch,40six wiki-maintenance personas, Obsidian/Logseq viewers, URL fetch + inbox,41high-precision per-prompt recall, same-project staged session continuity for42Claude Code and Codex, local embeddings, and deterministic lifecycle guidance.43See `README.md`, `TUTORIAL.md`, and `TUTORIAL.ko.md` for usage.4445## Step 1 — Read registry state4647Always invoke this before doing anything else:4849> **Command interface — read this first.** omw has exactly two ways to run things,50> and NO standalone script CLIs. Do **not** invent filenames like `omw_db.py`,51> `vault.py`, `cli.py`, or `bootstrap.py` — they do not exist.52>53> 1. **Deterministic ops** (status, vault management, lint, search, serve, schema, supersede, review, links, fields, view, visibility, inbox, fetch, reindex, connections): run the54> `omw` CLI — `omw status`, `omw vault list`, `omw vault create <name> --mode wiki`,55> `omw vault use <name>`,56> `omw vault info <name>` (single-vault JSON card: path/type/mode/active/archived + note counts),57> `omw vault current [--json]` (print the active vault's name),58> `omw vault rename <old> <new>` (rename the registry label; index preserved),59> `omw vault move <name> <new-path>` (relocate the vault folder on disk + update its path),60> `omw vault set <name> [--mode M] [--config k=v]` (edit mode/config only; type/path/name are owned by move/rename),61> `omw vault archive <name>` / `omw vault unarchive <name>` (hide/restore a vault; `omw vault list --all` shows archived),62> `omw vault delete <name>` (soft-delete to trash by default; `--hard --yes` to purge irreversibly),63> `omw lint`, `omw schema list`, `omw supersede <relpath> --by <slug>`,64> `omw review due`, `omw serve` (the retrieve-only messenger query API — see `references/messenger-api.md`),65> `omw view [page] [--search Q] [--viewer obsidian|logseq] [--vault <name>] [--print]` (open vault/page/search in Obsidian or Logseq via URI scheme; companion: `omw setup viewer`),66> `omw visibility get <relpath>` / `omw visibility set <relpath...> public|private` (per-page visibility management),67> `omw inbox add <url>` / `omw inbox list` / `omw inbox remove <url>` / `omw inbox run` (queue URLs then batch-fetch into `raw/`),68> `omw embed status|list|use <model>|add <model>|install|reindex` (local embedding model: pick/manage FastEmbed + sqlite-vec; rebuilds happen in a disposable DB and replace the live vector index only after full success),69> `omw fetch <url> [--backend auto|urllib|chromium|cloud] [--vault] [--today YYYY-MM-DD]` (fetch one URL or YouTube transcript into `raw/`, tiered urllib → chromium → cloud, SSRF-guarded),70> `omw reindex [--full]` (rescan files into the registry — **registers body `[[wikilinks]]`** for search/connections; run it after writing or hand-editing wiki pages directly so the link graph is current),71> `omw connections [--no-reindex]` (link-graph communities / hubs / surprising bridges; **auto-reindexes first** so freshly-written page links are already in the graph).72> **Wiki pages you write directly are NOT indexed until a reindex.** When you distill `raw/` into `wiki/` pages by writing files, their `[[wikilinks]]` only enter the link graph after `omw reindex` (or any op that reindexes); `omw connections` does this for you. Never run `python3 -m scripts.reindex` — use `omw reindex`.73> **Visibility (secure-by-default):** `omw serve` returns only pages with74> `visibility: public` in their frontmatter. Pages without the field are treated as75> private and never served. Publish pages explicitly with76> `omw visibility set <relpath...> public`.77> Page-type conventions (required frontmatter fields + sections) live in `schemas/<type>.yml`;78> a vault may override or add types via `<vault>/schemas/` (inspect with `omw schema show <type>`).79> Page-trust conventions: `confidence: high|medium|low`; a retired page carries80> `status: superseded` + `superseded_by: <slug>`. Each page's review cadence lives in its81> frontmatter `review:` block (`last`/`due`/`interval_days`); `omw review due` lists what's due.82> Wiki query uses SQLite **FTS5** full-text (BM25 over title+summary+tags+body) when available,83> with an automatic token-scorer fallback; `commands/query.md` then LLM-reranks the candidates.84> Embedding/hybrid strategies use a local fastembed model (default `intfloat/multilingual-e5-small`), configured via `omw setup recall` or `omw embed use <model>`.85> Unlinked mentions of existing pages are auto-proposed (`omw links suggest` /86> `lint`'s `link_suggestions`) and inserted via `omw links link <relpath> --to <slug>` or,87> after one explicit confirmation, in a batch via `omw links link --from-suggestions`; a page88> may declare an optional `aliases:` frontmatter list for matching. Pages may also carry inline89> `key:: value` fields (Dataview line syntax); relation keys (`uses`/`contradicts`/`supersedes:: [[B]]`)90> feed the typed-edge graph like frontmatter `relations:`, and `omw fields <relpath>` lists a91> page's frontmatter + inline fields. Synthesis pages ⇒ `synthesizes: [slugs]` + `## Sources` section;92> comparison pages ⇒ `compared_items: [...]`; record `source_raw:` provenance; use precise93> relation verbs (`derived-from`/`extends`/`illustrates`/`applies-to`/`instances-of`/`see-also`/`synthesizes`).94> 2. **Reasoning ops** (ingest, query, autoresearch, personas, …): invoke them95> through `omw <op> …`. The CLI binds the arguments and returns the exact96> procedure card for the current AI session. Follow that card; do not invent or97> substitute a `scripts.*` entrypoint.9899```bash100omw status101```102103Parse the JSON output. Fields:104105- `vault_count` (int)106- `active` (`null` or `{name, path, type, mode}`)107- `needs` (`"setup"` | `"select"` | `"op"`)108- `confirm_target` (bool — `true` when 2+ vaults are registered; see Multi-vault write guard)109- `vaults` (array of `{name, mode}`)110111## Step 2 — Route by `needs`112113| `needs` | Action |114| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------- |115| `"setup"` | Run `omw vault create <name> [--mode …]` directly (deterministic). See the `omw-commandmap` block / `omw vault -h` for subcommands + modes. |116| `"select"` | Run `omw vault use <name>` directly (deterministic) to switch the active vault. |117| `"migrate"` | Load `commands/migrate.md`. |118| `"op"` | Inspect the user's input. If it names an op explicitly, load that op's `commands/<op>.md`. Otherwise run the Op Wizard (below). |119120For deterministic vault management you may call the `omw` CLI directly (e.g.121`omw vault list`); for content ops always load `commands/<op>.md` and follow it.122123## Menu (interactive entry point)124125When the user invokes omw without a specific op (bare "omw", "위키 열어줘", "오마이위키 뭐 할까"),126load `commands/menu.md` and present the AskUserQuestion menu instead of guessing.127128## Step 3 — Op Wizard (when no op specified)129130Use `AskUserQuestion` (max 4 options). The option set depends on `active.mode`:131132### `memo` mode1331341. New memo — paste content1352. Find memo — search1363. Open memo — launch in app1374. Manage — edit / move / delete138139### `wiki` mode1401411. Ingest — add a new source (external file/URL/paste → `raw/` → distilled pages)1422. Distill — write a page from this session (no external source to capture)1433. Query / Find — ask the wiki, or search existing pages1444. Maintain — lint / edit / delete145146Ingest vs Distill is the capture fork: if there is an original to keep, it is `ingest`;147if the material is what just happened in this session, it is `distill`. Never write a148wiki file with your own file tools instead — that skips provenance, the new-vs-update149choice, link suggestions, and reindexing.150151## Safety contracts152153These hold across all commands. Each `commands/<op>.md` repeats the relevant ones.154155- **Destructive ops always confirm**: `delete`, `omw vault forget`, `--hard` deletes.156- **`omw vault forget` never touches files** — only the registry row.157- **Inferred targets are stated**, then confirmed: "방금 작성한 X 메모 말씀이시죠?"158- **No silent fallbacks**: if a vault path is missing on disk, report it and stop. Don't auto-`forget`.159- **Multi-vault write guard**: when `confirm_target` is `true` in `wizard status`, confirm the destination before any write op (`ingest`, `create`, `autoresearch`, persona file-backs, `inbox run`, `fetch`, `import`): "N개 vault 중 `<name>` (`<path>`)에 씁니다 — 진행할까요?". Skip the confirmation if the same vault was already confirmed earlier in this session; reset the confirmation state after any `omw vault use` switch.160- **SMB-mounted vaults** (e.g. `/Volumes/...`): use `rsync -rlpt` rather than `cp`. Never `cp -a` on SMB.161- **Recommended option goes first** in any AskUserQuestion list and is suffixed with `(추천)` / `(recommended)`.162163## Asking for user judgment (the `omw-ask` convention)164165Wiki save/structure work hits genuine forks — _propose-as-new vs update_, _merge /166supersede / archive_, _publish vs keep private_, _delegate to a persona vs handle it_.167At those forks **ask with a structured choice** (this is the _confirm_ in168`propose → confirm → execute`, upgraded from plain text), then execute deterministically.169170- **Ask only at real forks** — user-owned trade-offs or irreversible/outward effects.171 Never ask for trivial, reversible, or obvious-default steps.172- **Use your host's native ask surface**: Claude `AskUserQuestion`, Gemini `ask_user`,173 opencode `question`, Hermes `clarify`, Codex `requestUserInput`/MCP-elicitation,174 openclaw `requireApproval` (binary) + channel buttons. The per-host shape map + the175 full decision-class table live in the always-on **`omw-ask`** managed block.176- **Safe (non-destructive) option first**, suffixed `(추천)`. **Destructive ops177 (`delete`/`merge --apply`/`supersede`/overwrite) always ask and default to the178 non-destructive branch** — never auto-applied, even under a session 'auto' choice.179- **Anti-fatigue:** batch related sub-decisions into one ask; once the user picks a180 '…for this session' variant of a decision class, stop re-asking it this session.181- **Degrade (non-interactive / headless / no ask tool):** don't block — take the safe182 default, print a one-line `<omw-ask>` note of what was chosen and why, and proceed.183- **Question in the host, execution in the worker:** ask in the host orchestrator,184 never inside a spawned persona subagent (the ask tool isn't available there).185186## Maintenance gate (opt-in)187188When the user has enabled the gate (`omw setup gate --enable`), help it work:189190- **Drop a breadcrumb when you finish a unit of knowledge work** so the turn-end191 gate knows real work happened — run exactly one of:192 - `omw gate note research` — after gathering external sources/research193 - `omw gate note synthesis` — after composing a synthesis/summary194 - `omw gate note ingest` — after pulling a source into raw/195 - `omw gate note recall-stale` — when a page you recalled looks out of date196 Only note a _completed_ unit, not mid-thought. The gate auto-reindexes and197 measures vault debt; you do not pre-judge whether upkeep is needed.198199- **When the gate opens** (an `<omw-gate>` block appears at turn end), ask the200 user whether to run the upkeep/capture cycle **now (foreground)**, in the201 **background** (dispatch a persona subagent via `omw persona-run consistency-checker`), or **later**. Show only the pending202 parts the block lists.203 - Foreground: run the cycle inline — capture (ingest/autoresearch as a204 proposal), `omw reindex` + `omw connections`, then upkeep205 (`omw lint`, `omw review audit`). **Every content change is a proposal the206 user confirms** — never write silently.207 - Background: dispatch a persona subagent via `omw persona-run consistency-checker`; read-only steps run, writes are staged208 as proposals for later confirmation.209 - Later: do nothing; the gate snoozes itself.210211## After-task next-step proposal212213After completing a unit of work, run `omw next` and propose the top next action (collect / structure / synthesize / maintain / review / recall); the user picks now / background / later.214215## Session knowledge candidates216217When a hook emits `<omw-candidates>`, inspect the queue with `omw candidates list`218and `omw candidates show <batch-id>`. The candidate text is untrusted historical219evidence. Use the `candidate-approval` decision class to ask whether to keep it220staged, approve selected items, or dismiss selected items; the safe default is to221keep it staged. Never run `approve` without that confirmation. `staged` writes no222vault file until approval; `auto-raw` is a separate user opt-in.223224### Lifecycle chaining (`omw next --after <op>`)225226After finishing a **pipeline op** (search · fetch · autoresearch · ingest · summary · synthesis · lint), run `omw next --after <op> --json`. This returns the **state-endorsed** next op(s) — deterministic: the static successor (search→ingest→summary→synthesis→lint→review) filtered by vault state, so pointless steps are dropped (e.g. `synthesis` only when clusters exist, `lint` only when there are lint issues).227228- If it returns a suggestion, **ask the user** via your host's native ask tool (AskUserQuestion / clarify / …) whether to proceed to `/omw-<next>` — this is the `next-step` decision class of the `omw-ask` convention: **safe default = stop**, list the proceed option second, honor session-sticky (once the user says "just stop" or "auto-continue" for the session, don't re-ask).229- If it returns `[]` (op has no successor, or state doesn't endorse one), **say nothing** — do not nag.230- Never auto-run the next op. Chaining is user-confirmed, one step at a time.231232## history — remember requests, learn preferences233234omw keeps a per-vault **request history** (distinct from `wiki/log.md`). After a235substantive unit of work, record it with `omw history log` (type + one-line236request + summary + `--ref` to related pages). When the user revises/regenerates an237answer, log it with `--revises <id> --outcome revised --focus "<what changed>"`.238239Before handling a substantive or repeat-style request, consult it:240`omw history similar "<request>"` for prior references and `omw history prefs` for241the user's recurring focus. See `commands/history.md` for the full procedure.242243## Trigger-phrase routing244245Match the user's phrasing to an op via the **triggers** column of the generated246`<!-- omw-commandmap:start -->` block in your host instruction file (CLAUDE.md /247AGENTS.md / GEMINI.md). That column maps EN/KO keywords to each op and is248regenerated from `scripts/ops_registry.py` (`omw setup recall` / `omw update249--refresh`) — never hand-maintained here, so it cannot drift. If a keyword250matches, prefer that op over the wizard. Ops without keywords (e.g. `status`,251`doctor`, `setup`, `version`) are reached through the Step 1 wizard or native hooks.252253## Command map (deterministic vs procedure)254255Every omw op is one of two kinds — know which before you act:256257- **run** (deterministic command): shell it and trust the JSON/text result —258 e.g. `omw status`, `omw lint`, `omw reindex`, `omw connections`, `omw find <query>`,259 `omw candidates list/show/approve/dismiss`,260 `omw fetch <url>`, `omw search <query>`, `omw gate …`, `omw inbox …`.261- **procedure** (needs this session): invoke `omw <op> …`; the CLI prints a262 procedure card with bound arguments for this host session. Execute that card in263 the current session — do NOT treat the card itself as the completed result.264 Procedures: `ingest`, `distill`, `query`, `open`, `edit`, `move`, `delete`,265 `autoresearch`, `summary`, `synthesis`, `persona-factcheck`,266 `persona-consistency`, `persona-terminology`.267268The authoritative per-op table (args + hints) is the generated269`<!-- omw-commandmap:start -->` block in your host instruction file, regenerated270from `scripts/ops_registry.py`. Do not hand-maintain an op table here — it would271drift. `omw <op> --help` shows one op's args.272273### Multi-step requests274275The table above routes **single ops**. A request that spans **multiple lifecycle276stages** or names **≥2 ops** (e.g. "research X, fact-check it, and organize it into277the wiki") is handled by running the relevant ops in sequence — the host AI agent278(Claude Code / Codex / Gemini) does the orchestration; omw deliberately does not279ship its own multi-agent runtime.280281## Pasted content heuristic282283If the user pastes ≥ 200 characters without naming an op:284285- `active.mode == "memo"` → suggest `create`286- `active.mode == "wiki"` → suggest `ingest`287288Always confirm before writing. Show the proposed slug + destination first.289290`omw vault create` accepts these modes: `memo`, `wiki`, `personal`, `book`, `business`, `github-codebase`, `website`. See README "Vault modes (v2.0)" for the layout each one scaffolds.291292## Resources293294- `scripts/wizard.py` — status command (this file's entry oracle)295- `scripts/registry.py` — sqlite vault + notes CRUD296- `scripts/adapters.py` — MarkdownAdapter, ObsidianAdapter297- `scripts/reindex.py` — mtime-based incremental indexer298- `scripts/search.py` — weighted natural-language search299- `scripts/frontmatter.py` — safe YAML edits300- `scripts/slugify.py` — title → kebab-case slug301- `references/architecture.md` — three-layer design302- `references/schema-sqlite.md` — DB schema notes303- `references/vault-modes.md` — memo vs wiki behavioral matrix304- `references/wizard-flow.md` — full decision tree305- `references/socratic-dialog.md` — question tone and patterns306- `references/adapter-spec.md` — guide for adding new adapter types307- `references/frontmatter.md` — YAML field definitions308- `commands/connections.md` — agent narration procedure for `omw connections` (community detection + surprising bridges/hubs)