magus v0.4.2 is out. See what's new
¶ View generated markdown
12 min read

magus-query

The --simple permutation is 19% smaller: 10541 of 13065 bytes.

Query the magus knowledge graph to find and relate entities (projects, targets, spells, ops, charms, modules, diagnostics, docs). Use INSTEAD of Grep or Glob in a repo with magusfile.buzz whenever the question is what exists, what depends on what, where something is used, or how two entities relate - a graph answer is verified against declared sources, a grep hit is a guess.

Install it, rather than copying from this page:

magus agent install .claude/skills   # writes both forms below

An installed copy carries a provenance stamp, so magus doctor can tell you when a magus upgrade has made it stale. Text copied from this page carries none.

What an installed copy carries

magus agent install writes this frontmatter above the body. magus doctor reads it to report whether your installed skills are current.

field value
license GPL-3.0-or-later
compatibility any-agent
source magus
agent-skill-version 51
knowledge-schema-version 10
skill-content 247a38915217
skill-variant full

The skill-content digest covers this skill alone, and both permutations below report it: they go stale together, never one silently, and a change to another skill does not move it.

Full form

Every mechanical step spelled out, plus the rationale for each. Installed as the <name>-full twin: loaded by name rather than always, so a reader who needs the long form can ask for it without every session carrying it.

# magus knowledge graph

magus keeps a deterministic, cache-backed graph of its own domain. Query it to
find and relate entities instead of grepping source. This skill teaches HOW to use
the tools; the verbs below say WHAT is in this specific workspace. The division is
strict, so this skill never goes stale when a workspace changes - only when the
tool surface does.

FAST PATH: in a magus workspace (a magusfile.buzz at the root), any question
shaped like "what exists / what depends on X / where is Y used / how do A and B
relate" is a graph query FIRST - do not open Grep or Glob for it. Unlike a
grep hit, a graph answer is verified: every edge is extracted from a declared
source or scored by a rubric, and says which. If the graph cannot answer,
say so and then fall back - a silent fallback hides the gap that should be
reported.

`MAGUS.md` IS NOT YOUR SOURCE. It is a generated routing index written for a
HUMAN reading the repo, and it is only as true as its last regeneration - a
workspace whose generate target has not run since the last change describes a
tree that no longer exists. Every fact in it has a live command that cannot be
stale, and those commands scope to a project where the file covers the whole
workspace. Read it as a LAST RESORT: when no daemon is reachable and the CLI is
unavailable too, or when a human explicitly asks what the committed index says.

## Act in this order

1. Ask the workspace what exists, with the verb that answers your question:
   `magus describe targets` (every target; `-o name` for bare names),
   `magus ls` (every project with its spell, sources, outputs, depends_on),
   `magus describe spells`, `magus describe projects`. These are live, so they
   are right even mid-change, and they take a `-o json` for machine reading.

2. Then reach for the verbs. Prefer the MCP tools. At session start, or after an
   MCP call fails, check `magus status --probe=mcp`. If it is unavailable, tell
   the user once that `magus server start` restores the full agent surface, then
   use the CLI equivalent from the same row below. Do not stop or grep. CLI
   fallback remains correct, but has no tool discovery or warm daemon graph.

   | question                                      | MCP tool        | CLI                                |
   | --------------------------------------------- | --------------- | ---------------------------------- |
   | find and relate entities                      | `magus_query`   | `magus query "<terms>"`            |
   | one node: its edges, provenance, blast radius | `magus_explain` | `magus explain <node>`             |
   | how do two nodes relate                       | `magus_path`    | `magus path <a> <b>`               |
   | where risk concentrates                       | `magus_stats`   | `magus graph stats`                |
   | where a code symbol is defined and used       | `magus_refs`    | `magus refs <symbol>`              |
   | what a branch changed in the graph            | (export + diff) | `magus graph diff <baseline.json>` |

   Prefer these over grep and glob for anything in the magus domain. `magus_refs`
   needs a workspace that declares a SCIP index (`knowledge.symbols` in config); it
   is the occurrence-shaped def/references answer, so use it over `magus_query` for a
   symbol's fan-in. Every empty result carries a verdict: `absent` means magus
   searched every symbol index this workspace declares and the thing is not there;
   `unknown` names the projects it could not search, and building those with
   `magus graph build` is what turns the answer into a fact. Read the verdict before
   concluding anything from an empty result.

   The graph relates entities; the evaluated dispatch plan lives one verb over.
   `magus describe target <name>` prints, per project, the resolved source globs,
   output globs (the generated files), spells, and policy for that target - use it
   when the question is "what feeds or comes out of this target", not "what relates
   to it".

## Rewriting a symbol everywhere it appears

`magus refs <symbol>` answers "where is this used" at file granularity, and its line
list is CAPPED - it describes fan-in, and a rewrite driven off it silently skips sites.
Add `--occurrences` for the edit-precise view: every occurrence, uncapped, with start and
end line/column, and each range checked against the file on disk.

```sh
magus refs <symbol> --occurrences -o json
```

magus reports the sites; YOU apply the edits. It will not rewrite the tree for you, the
same way `magus affected` names what a change reaches without touching it.

**Never drive the rewrite from a pattern** - not `sed -i`, not a scripted
substitute-and-write. A regex cannot tell YOUR symbol from a dependency's symbol of the
same name, and it writes before anyone reads a diff: a `\.Sum\b` rewrite aimed at one
proto field also hits the OTel SDK's `metricdata.Sum` and a histogram's `dp.Sum`. The
index knows which is which. Apply the sites it reports, then let the compiler enumerate
what still moved; widening the pattern until the errors stop is the same mistake with
extra steps.

**A not-indexed project is a stop, not an empty result.** `magus refs` says
`verdict: unknown, not absent` and names the projects it could not see. Run
`magus graph build` and ask again. Reading that verdict as "no matches" and falling back
to a text search is how a rename misses every site in an unindexed project - and a fresh
worktree starts unindexed, so this is the normal state at the moment you most want a
rename.

Three things decide whether the result is usable, and skipping any of them is how a bulk
rewrite corrupts a file:

- **Edit only `verified` sites.** Each occurrence carries a `status`. `verified` means
  magus read that exact range and found the symbol there. `mismatch` means it found
  something else - the index predates an edit - and `unreadable` means the range is no
  longer inside the file. The `text` field shows what is really there, and `names` is every
  spelling that would have verified, so you can check the verdict rather than trust it.
- **Check the exit status when scripting `-o name`.** It emits `file:line:col` for the
  verified sites ONLY, so a wholly stale index prints nothing - which on its own is
  indistinguishable from a symbol that is never used. Exit 1 means sites were found and
  withheld, and the count goes to stderr. Do not read empty output as "nothing to do".
- **Apply back-to-front within each file.** Replacing a name with one of a different
  length shifts every later column on that line, so editing top-down invalidates each
  subsequent range as you go. Walk each file's occurrences in reverse. Files are
  independent of each other.
- **Treat a `stale` file as a stop, not a filter.** A file is marked stale when any of its
  ranges failed to verify, which proves it changed after indexing - so the index may also
  be MISSING occurrences added since, and no per-site check can see a site that is not in
  the list. Re-run that project's `scip` target and ask again. Editing the verified sites
  and skipping the rest produces a half-renamed tree that may still compile.

Completeness rests on the index being current even when everything verifies: an edit that
appended a new use without disturbing existing ranges leaves every site verifying while
adding one magus never saw. `magus status` reports which indexes are fresh. Re-index
first when the tree has moved since you last did, and check the verdict for projects that
declare no index at all - those are not searched.

## Query grammar

Free-text terms (AND) plus field matchers. A matcher is `field<op>value`, and the operators
are `=` (match), `!=` (exclude), `=~` (regex):

- `build` - free text over IDs, labels, and docs
- `kind=spell` - only that node kind
- `project=pkg/foo` - everything the project owns: the project node, its
  targets, and the files/functions/docs whose source lives under it (nested
  projects claim their own; the root `.` owns only what no nested project does)
- `relation=uses` - seed from nodes touching that edge (`relation=calls`
  reaches symbol-to-symbol call edges, so it loads the lazy symbol shards)
- `id=build` - substring match on the node ID
- `kind!=op` - exclude these
- `id=~build$` - regex over the target; `kind=~"spell|op"` ORs the alternatives
- `id=target:*build` - `*` wildcard, matching any run (in a value or a free-text term)
- `"exact phrase"` - keep a quoted span as one term

The `:` grammar (`kind:spell`) and dash negation (`-kind:op`) are the pre-`=`
spelling, kept as a compat alias so old invocations still parse. Prefer `=`/`!=`/`=~`.

A query returns ranked matches plus their neighborhood, bounded by `--budget`
(default 50). For a large match set over MCP, pass `limit` and echo the returned
`next_cursor` to fetch the next page.

## Retrieving prose from the docs

Every markdown heading in the workspace is a `docsection` node, so documentation is
QUERYABLE, not something to read whole. When you are looking for WHERE something is
explained - in this repo's docs, a project's README, any tracked markdown - query the
section rather than cat or grep the file:

- `magus query "kind=docsection <terms>"` returns the heading whose section covers your
  terms. Each result's id and Source are `<path>#<anchor>` - a citable pointer to the exact
  passage, the same fragment a link into the rendered page carries. Read that one section,
  not the whole page.
- Scope it with `project=<p>` and combine free-text terms. `magus explain
  "docsection:<path>#<anchor>"` shows the page a section belongs to and what it links to; a
  page `contains` its sections and a section contains the headings nested under it, so you
  can walk the outline.
- Prose only: a code file is not indexed this way - `magus refs` and the entity kinds above
  still cover code and the domain model.

Reading one file you already know the path of is fine. This replaces the SCAN - the grep or
cat over markdown to find a passage - not a targeted read.

## Reading results

- Reading as a machine? Add `-o json`: every verb returns a stable,
  `schema_version`-stamped OBJECT with a top-level wrapper - key into the
  plural (`.matches`, `.targets`), it is never a bare array. `-o name` prints
  bare IDs for piping. Do not scrape the human text or trim it with `head`.
  Over MCP the tools already return structured content; nothing to shape.
- Node IDs are stable and structured: `<kind>:<qualified-name>`, e.g.
  `target:pkg/foo:build`, `spell:go`, `diagnostic:MGS2001`. Key on them; a rename
  is a delete plus an add.
- Edges are directed and carry a `confidence` - `extracted` (read directly off a
  source) or `inferred` (a rubric score) - plus `provenance` (where it came from).
- Node `attrs` surface metadata: a project's `engine` and `target_count`, a
  target's inherited `engine`, a doc's `title` and `tags`. The `duration_p75_ms`,
  `cache_hit_rate`, `run_samples`, `last_output_ref`, and `last_run_ok` attrs are
  OBSERVED from local run history, not derived from sources - read them as history, not
  guarantees. A target's `last_output_ref` is the `refxxxxxxxx` id of its most recent
  captured run (with `last_run_ok` its `true`/`false` outcome), so `magus query output
<ref>` on it fetches that output - a target-to-output hop. When `knowledge.vcs` is
  enabled, file nodes also carry `vcs_last_commit`, `vcs_last_modified`, and
  `vcs_commits` extracted from git history.
- Every output carries `schema_version`; a bump means the node/edge shape changed.

## Ownership and blast radius

If the repo commits a `CODEOWNERS` file, the graph has `owner` nodes with `owns`
edges to the projects and files they cover. Combine that with dependency edges to
answer "who owns the blast radius of this change": `magus explain <node>` for the
node's owners and dependents, or `magus query kind=owner` to list owners. Only
declared CODEOWNERS ownership appears - it is not blame-inferred.

## Across workspaces and neighbors

- `--global` unions every workspace registered in config
  (`knowledge.workspaces`); IDs are namespaced per workspace (`web//spell:go`).
- `magus affected`, `magus_insight`, and `magus describe` sit alongside the graph;
  `magus graph export -o json` dumps the whole graph for bulk analysis.
- To show a PR's domain impact, run `magus graph diff --rev main -o markdown` for a CI
  comment (nodes/edges added, removed, or changed); `--rev` builds the base graph from
  that revision's files, or pass a `graph export -o json` baseline file instead.

## Do not render the graph yourself

magus emits; it does not render. To LOOK at the graph, do not draw it: OFFER the
human an export - `magus graph export -o json` (or `-o graphml`) opens directly in
Gephi, yEd, or a browser graph tool. The emit-never-render rule that governs magus
governs you too.

## Fetching current behavior

For flags and behavior this skill does not cover, run any verb with `-h`, and read
the magus documentation site. Prefer the tools' own output over assumptions.

Short form

The enumeration dropped, the judgment kept - for the most capable readers, not the least; the bar under the heading above shows by how much. This is the always-loaded primary. Both are hand-authored from one source body; see Skills for the difference.

Show the short form
# magus knowledge graph

magus keeps a deterministic, cache-backed graph of its own domain. Query it to
find and relate entities instead of grepping source.

FAST PATH: in a magus workspace (a magusfile.buzz at the root), any question
shaped like "what exists / what depends on X / where is Y used / how do A and B
relate" is a graph query FIRST - do not open Grep or Glob for it. If the graph cannot answer,
say so and then fall back - falling back silently hides the gap.

`MAGUS.md` IS NOT YOUR SOURCE. It is a
generated index for humans, true only as of its last regeneration. Last resort
only: no daemon AND no CLI, or a human asking what the committed index says.

## Act in this order

1. Ask the workspace what exists, with the verb that answers your question:
   `magus describe targets` (every target; `-o name` for bare names),
   `magus ls` (every project with its spell, sources, outputs, depends_on),
   `magus describe spells`, `magus describe projects`.

2. Then reach for the verbs. Prefer the MCP tools. At session start, or after an
   MCP call fails, check `magus status --probe=mcp`. If it is unavailable, tell
   the user once that `magus server start` restores the full agent surface, then
   use the CLI equivalent from the same row below. Do not stop or grep.

   | question                                      | MCP tool        | CLI                                |
   | --------------------------------------------- | --------------- | ---------------------------------- |
   | find and relate entities                      | `magus_query`   | `magus query "<terms>"`            |
   | one node: its edges, provenance, blast radius | `magus_explain` | `magus explain <node>`             |
   | how do two nodes relate                       | `magus_path`    | `magus path <a> <b>`               |
   | where risk concentrates                       | `magus_stats`   | `magus graph stats`                |
   | where a code symbol is defined and used       | `magus_refs`    | `magus refs <symbol>`              |
   | what a branch changed in the graph            | (export + diff) | `magus graph diff <baseline.json>` |

   Prefer these over grep and glob for anything in the magus domain. `magus_refs`
   needs a workspace that declares a SCIP index (`knowledge.symbols` in config); Every empty result carries a verdict: `absent` means magus
   searched every symbol index this workspace declares and the thing is not there;
   `unknown` names the projects it could not search, and building those with
   `magus graph build` is what turns the answer into a fact. Read the verdict before
   concluding anything from an empty result.

   `magus describe target <name>` prints, per project, the resolved source globs,
   output globs (the generated files), spells, and policy for that target.

## Rewriting a symbol everywhere it appears

`magus refs <symbol>` answers "where is this used" at file granularity, and its line
list is CAPPED - it describes fan-in, and a rewrite driven off it silently skips sites.
Add `--occurrences` for the edit-precise view: every occurrence, uncapped, with start and
end line/column, and each range checked against the file on disk.

```sh
magus refs <symbol> --occurrences -o json
```

magus reports the sites; YOU apply the edits. It will not rewrite the tree for you, the
same way `magus affected` names what a change reaches without touching it.

**Never drive the rewrite from a pattern** - not `sed -i`, not a scripted
substitute-and-write. A regex cannot tell YOUR symbol from a dependency's symbol of the
same name, and it writes before anyone reads a diff: a `\.Sum\b` rewrite aimed at one
proto field also hits the OTel SDK's `metricdata.Sum` and a histogram's `dp.Sum`. The
index knows which is which. Apply the sites it reports, then let the compiler enumerate
what still moved; widening the pattern until the errors stop is the same mistake with
extra steps.

**A not-indexed project is a stop, not an empty result.** `magus refs` says
`verdict: unknown, not absent` and names the projects it could not see. Run
`magus graph build` and ask again. Reading that verdict as "no matches" and falling back
to a text search is how a rename misses every site in an unindexed project - and a fresh
worktree starts unindexed, so this is the normal state at the moment you most want a
rename.

Three things decide whether the result is usable, and skipping any of them is how a bulk
rewrite corrupts a file:

- **Edit only `verified` sites.** Each occurrence carries a `status`. `verified` means
  magus read that exact range and found the symbol there. `mismatch` means it found
  something else - the index predates an edit - and `unreadable` means the range is no
  longer inside the file. The `text` field shows what is really there, and `names` is every
  spelling that would have verified, so you can check the verdict rather than trust it.
- **Check the exit status when scripting `-o name`.** It emits `file:line:col` for the
  verified sites ONLY, so a wholly stale index prints nothing - which on its own is
  indistinguishable from a symbol that is never used. Exit 1 means sites were found and
  withheld, and the count goes to stderr. Do not read empty output as "nothing to do".
- **Apply back-to-front within each file.** Replacing a name with one of a different
  length shifts every later column on that line, so editing top-down invalidates each
  subsequent range as you go. Walk each file's occurrences in reverse. Files are
  independent of each other.
- **Treat a `stale` file as a stop, not a filter.** A file is marked stale when any of its
  ranges failed to verify, which proves it changed after indexing - so the index may also
  be MISSING occurrences added since, and no per-site check can see a site that is not in
  the list. Re-run that project's `scip` target and ask again. Editing the verified sites
  and skipping the rest produces a half-renamed tree that may still compile.

Completeness rests on the index being current even when everything verifies: an edit that
appended a new use without disturbing existing ranges leaves every site verifying while
adding one magus never saw. `magus status` reports which indexes are fresh. Re-index
first when the tree has moved since you last did, and check the verdict for projects that
declare no index at all - those are not searched.

## Query grammar

Free-text terms (AND) plus field matchers. A matcher is `field<op>value`, and the operators
are `=` (match), `!=` (exclude), `=~` (regex):

- `build` - free text over IDs, labels, and docs
- `kind=spell` - only that node kind
- `project=pkg/foo` - everything the project owns
- `relation=uses` - seed from nodes touching that edge
- `id=build` - substring match on the node ID
- `kind!=op` - exclude these
- `id=~build$` - regex over the target; `kind=~"spell|op"` ORs the alternatives
- `id=target:*build` - `*` wildcard, matching any run (in a value or a free-text term)
- `"exact phrase"` - keep a quoted span as one term

The `:`/`-kind:op` spelling still parses (compat); prefer `=`/`!=`/`=~`.

A query returns ranked matches plus their neighborhood, bounded by `--budget`
(default 50). Over MCP, page with `limit` plus the returned
`next_cursor`.

## Retrieving prose from the docs

Every markdown heading in the workspace is a `docsection` node, so documentation is
QUERYABLE, not something to read whole. When you are looking for WHERE something is
explained - in this repo's docs, a project's README, any tracked markdown - query the
section rather than cat or grep the file:

- `magus query "kind=docsection <terms>"` returns the heading whose section covers your
  terms. Each result's id and Source are `<path>#<anchor>` - a citable pointer to the exact
  passage, the same fragment a link into the rendered page carries. Read that one section,
  not the whole page.
- Scope it with `project=<p>` and combine free-text terms.
- Prose only: a code file is not indexed this way - `magus refs` and the entity kinds above
  still cover code and the domain model.

Reading one file you already know the path of is fine. This replaces the SCAN - the grep or
cat over markdown to find a passage - not a targeted read.

## Reading results

- Reading as a machine? Add `-o json`: every verb returns a stable,
  `schema_version`-stamped OBJECT with a top-level wrapper - key into the
  plural (`.matches`, `.targets`), it is never a bare array. `-o name` prints
  bare IDs for piping. Do not scrape the human text or trim it with `head`.

- Node IDs are stable and structured: `<kind>:<qualified-name>`, e.g.
  `target:pkg/foo:build`, `spell:go`, `diagnostic:MGS2001`. Key on them.
- Edges are directed and carry a `confidence` - `extracted` (read directly off a
  source) or `inferred` (a rubric score) - plus `provenance` (where it came from).
- Node `attrs` surface metadata. The `duration_p75_ms`,
  `cache_hit_rate`, `run_samples`, `last_output_ref`, and `last_run_ok` attrs are
  OBSERVED from local run history. A target's `last_output_ref` is the `refxxxxxxxx` id of its most recent
  captured run (with `last_run_ok` its `true`/`false` outcome), so `magus query output
<ref>` on it fetches that output. When `knowledge.vcs` is
  enabled, file nodes also carry `vcs_last_commit`, `vcs_last_modified`, and
  `vcs_commits` extracted from git history.
- Every output carries `schema_version`; a bump means the node/edge shape changed.

## Ownership and blast radius

If the repo commits a `CODEOWNERS` file, the graph has `owner` nodes with `owns`
edges to the projects and files they cover. `magus explain
<node>` for owners plus dependents; `magus query kind=owner` to list. Declared
ownership only, never blame-inferred.

## Across workspaces and neighbors

- `--global` unions every workspace registered in config
  (`knowledge.workspaces`); IDs are namespaced per workspace (`web//spell:go`).
- `magus affected`, `magus_insight`, and `magus describe` sit alongside the graph;
  `magus graph export -o json` dumps the whole graph for bulk analysis.
- To show a PR's domain impact, run `magus graph diff --rev main -o markdown` for a CI
  comment.

## Do not render the graph yourself

magus emits; it does not render. To LOOK at the graph, do not draw it: OFFER the
human an export - `magus graph export -o json` (or `-o graphml`) opens directly in
Gephi, yEd, or a browser graph tool.

## Fetching current behavior

For flags and behavior this skill does not cover, run any verb with `-h`, and read
the magus documentation site.
generatedinternal/agent/skills/magus-query/SKILL.mdagentsskillsmagus-query
Last updated (77dde07d)
Earlier changes on this page (7)

Full history ↗ · Blame source ↗

Glossary

Workspace

The magus root directory that owns a set of projects and shared config; the unit magus operates over. See workspace.

Project

A directory magus recognizes as a unit of work (it has a magusfile); the unit of caching, scheduling, and dependency tracking. See workspace.

Magusfile

The magusfile.buzz that declares a project's targets (as export funs) and binds its spells. See targets.

Target

A named operation (build, test, ...) you invoke with magus run <target>; it may compose a spell's tool-native operations and depend on other targets. See targets.

Op

A single tool-native command a target composes (long form: operation); the middle of the work hierarchy (Spell to Op to Target). See operations.

Spell

A language/runtime adapter (e.g. go, md) that maps generic targets onto a toolchain's real commands. See spells.

Charm

An execution modifier attached with : (lint:rw) that changes how a target runs, not which one; the built-in rw flips a check-only target to mutate in place, and ci always strips it. See charms.

Module

A magus stdlib namespace a magusfile imports for host capabilities: filesystem, exec, vcs, and more. See the module reference.

Buzz

The language magusfiles are written in (the .buzz engine). See engines.

Engine

The interpreter a magusfile runs on; magus embeds the Buzz engine. See engines.

Cache

The content-addressed store magus consults before running a target, so unchanged work is skipped. See cache.

Affected

The set of projects touched by a change; magus affected <target> runs a target only over them. See affected.

Daemon

The background magus host that owns shared state such as services and the warm knowledge graph. See daemon.

CI

An ordinary magusfile-defined target you compose yourself with magus\needs - magus does not hardcode its stages. Magus.RunCI treats it specially only in that it strips the rw charm, it is the anchor magus affected ci keys off, and a selected scope with no project declaring it is a load error rather than a silent no-op. See targets.

Span

OpenTelemetry's name for one unit of work under a trace - a target execution, whose sub-operations are child spans. An output reference points at a span's captured output. See telemetry.

Knowledge graph

The queryable graph of a workspace's spells, targets, docs, and code relationships; query it with magus query/explain/path. See knowledge.

MAGUS.md

The committed routing index at a workspace root, regenerated from the knowledge graph: it lists every node and points at the exact query for a given question, so it is the entry point an agent reads first. See knowledge.

Insight

The reports magus derives over the graph and history (hotspots, affinity, ownership, trend, volatility, unreferenced). See insight.

Ownership

An insight lens: author concentration - the primary author and their share, the distinct-author count (the bus factor), and abandonment. See insight.

Session

One magus process's recorded facts - the targets it finished, their outcomes, and the lease it acted as - kept in a repo-scoped store every worktree shares. magus session lists them; the store prunes itself by last-fact age.

Conventions

Placeholders

Angle brackets mark a value you replace with your own - never type the brackets:

magus run <target>
magus completion <shell>    # e.g. bash, zsh, fish

<target>, <path>, <shell>, <name> and the like are stand-ins, not literal text.