Agent Skill
What a skill is here
Section titled “What a skill is here”An Agent Skill is a Markdown instruction file a coding agent loads alongside its tools. Kivgraph ships one, and it exists for a single reason: to route a question to the right tool before the agent reaches for grep or starts opening files. It is not required in order to use the MCP server. Install it to change which tool the agent picks; skip it and the twelve tools still work.
Install
Section titled “Install”kivgraph skill installWith no --target, the command detects the supported agents present in the
requested scope, opens a selector with the detected ones pre-checked, and
installs into every entry you confirm. Arrows or j/k move, space toggles,
a selects all, n selects none, Enter confirms, q or Esc cancels.
Confirming with nothing selected is refused.
For scripted use, name the client:
kivgraph skill install --target claude-code --scope user| Flag | Default | Meaning |
|---|---|---|
--target | empty | Client to write: claude-code, claude-desktop, codex, opencode, oh-my-pi. Omit it on install to open the selector. Required for status and remove. |
--scope | user | user or project. project resolves against the current working directory. Any other value is rejected. |
--dry-run | off | Report the plan as would-install and write nothing. Not accepted by skill status. |
--force | off | Replace a file at the skill path that is not the canonical skill. Without it, that case is an error. |
Without a terminal and without --target, the selector cannot run and the
command fails with interactive selection requires a terminal; pass --target.
Client integrations are supported on Linux and macOS only.
skill install copies one file. It does not initialise Kivgraph, does not
register the MCP server, and does not index anything. Register the server
separately: see MCP clients. Build a graph with
indexing.
Where it lands
Section titled “Where it lands”The installed file is always named SKILL.md and always sits in a
skills/kivgraph/ directory. <project> is the current working directory.
| Client | --target value | Scope | Path |
|---|---|---|---|
| Claude Code | claude-code | user | ~/.claude/skills/kivgraph/SKILL.md |
| Claude Code | claude-code | project | <project>/.claude/skills/kivgraph/SKILL.md |
| Codex | codex | user | ~/.agents/skills/kivgraph/SKILL.md |
| Codex | codex | project | <project>/.agents/skills/kivgraph/SKILL.md |
| OpenCode | opencode | user | ~/.config/opencode/skills/kivgraph/SKILL.md |
| OpenCode | opencode | project | <project>/.opencode/skills/kivgraph/SKILL.md |
| Oh My Pi | oh-my-pi | user | ~/.omp/agent/skills/kivgraph/SKILL.md |
| Oh My Pi | oh-my-pi | project | <project>/.omp/skills/kivgraph/SKILL.md |
Claude Desktop has no local skill target. It is a supported MCP client, but it
never appears in the skill selector, and --target claude-desktop fails with
target "claude-desktop" does not support local skill installation. Register
the MCP server for it and it uses the tools without the skill.
What the skill says
Section titled “What the skill says”The skill teaches one contract: reach for the graph when the question is about callers, references, impact or cross-repository consumers, and reach for the files only after the graph has named them.
Routing
Section titled “Routing”| Question | Tool |
|---|---|
| Is a graph published, how old is it, what does it cover | graph_status |
| Which repositories are indexed, and in which language | list_repositories |
| Where is this name or qualified name declared | find_symbol |
| Everything about one symbol already identified | get_symbol |
| The code behind rows a tool returned | get_source |
| What a package or directory declares | get_file_outline |
| Who references this, or what it reaches, one hop out | find_references |
| Bounded dependency paths out of a symbol | trace_dependencies |
| Consumers in another repository | find_cross_repo_consumers |
| Bounded incoming impact, grouped | get_blast_radius |
| Register projects and rebuild the graph | index_project |
The skill orders the first moves: graph_status to confirm a published
snapshot exists and how old it is, then list_repositories to pick the
repository and language before narrowing. Repository names are case sensitive;
two names differing only in case are two repositories.
Why an empty answer is an answer
Section titled “Why an empty answer is an answer”Edges are resolved by go/types, the TypeScript checker and rust-analyzer,
not by matching names. A reference list is therefore complete for those
languages, and an empty one means nobody calls the symbol. Grep cannot tell you
that.
Rows are addressable
Section titled “Rows are addressable”Every row carries a repository, a repository-relative path, a qualified name and a line range, and every tool accepts that triple in place of a stable key. The next call is built from the answer just received, so stable keys need never enter the conversation.
Evidence rules the skill imposes
Section titled “Evidence rules the skill imposes”- Keep
EXACT,CANDIDATEandUNRESOLVEDapart. Never upgrade a candidate or an unresolved result because a name, path, alias or text matches. - Read the
coverageofget_blast_radius:exactandcandidatecount consumers of the symbol asked for, whilepackage_levelcounts dependencies on the provider package and proves nothing about that symbol. - Respect result limits and cursors. Narrow the query instead of treating a truncated response as complete.
- Treat the snapshot as a projection of the canonical graph, not as licence to invent facts. If it is missing or stale for the question, say so and ask for a re-index.
- In a
serveprocess,graph_statusanswersnot_applicableforstorageandworker, with the reason: the server responds from the published snapshot and never opens the database or runs the TypeScript worker. That is not a misconfiguration. - Unresolved references are facts about the workspace, not defects. Report the reason instead of concluding that coverage is broken. See resolution.
Indexing
Section titled “Indexing”index_project is the only mutating tool. The skill requires explicit user
approval before calling it, all projects passed in one call through projects,
and no claim of success until a new generation and snapshot are published. A
rebuild resolves cross-repository edges over the complete fact set, so it costs
the whole corpus whatever was added: eleven separate calls build eleven graphs
and keep the last one. A full rebuild can outlive the client’s per-call
timeout; the work still completes, and graph_status showing an advanced
snapshot_id is the check, not a retry.
Where it loses
Section titled “Where it loses”Stated in the skill’s own terms, and not softened: a rare name in a single small repository is cheaper to grep, and one small file is cheaper to read than to outline. Kivgraph wins on common names, on transitive impact, on cross-repository consumers and on proving an absence. It is the wrong tool for a one-off literal string search.
Inspect and remove
Section titled “Inspect and remove”kivgraph skill status --target claude-code --scope userkivgraph skill remove --target claude-code --scope userBoth require --target; neither opens the selector. skill status reads the
path and reports one of three states:
| Status | Meaning |
|---|---|
absent | Nothing at the path. |
managed | The file is byte-identical to the canonical Kivgraph skill. |
incompatible | A file exists at the path and is not the canonical skill. |
skill remove deletes only a file that is byte-identical to the canonical
skill. Anything else at that path is left alone and reported as an error unless
you pass --force. Nothing else in the client’s skills directory is touched:
removal withdraws Kivgraph’s own skill and nothing more. --dry-run reports
would-remove and deletes nothing.
Safety
Section titled “Safety”- The destination is inspected with a symlink-aware stat. A symlink at the skill
path is refused (
refusing symlink integration path), and so is anything that is not a regular file. - Missing parent directories are created with mode
0700. - Writes are atomic: the content goes to a temporary file in the destination
directory, is set to mode
0600, is synced, is renamed over the destination, and the directory itself is synced afterwards. Removal uses the same rename-then-delete path. - Before an existing file is overwritten or removed, its previous content is
copied to
<path>.kivgraph.bak. An existing backup is kept as it is and never overwritten, so the first backup survives later runs. A backup path that is a symlink or not a regular file aborts the operation. - Replacing a file that is not the canonical skill requires
--force. Without it the command fails withintegration path "<path>" contains an incompatible Kivgraph entry; use --force to replace or remove it. - An install whose destination already matches the canonical skill reports
managedand writes nothing. No backup is created and no timestamp changes.
In a release bundle
Section titled “In a release bundle”The canonical skill ships inside the release bundle at
skills/kivgraph/SKILL.md and is listed in the bundle’s SHA256SUMS, so it is
verified with the same checksum pass as the rest of the payload. See
install.