magus v0.4.3 is out. See what's new
¶ View markdown source · ✎ Suggest an edit
6 min read

The CLI in practice

magus has around thirty subcommands. You reach for maybe six of them daily. This page groups them by the question you are asking rather than alphabetically, and covers the behavior that the per-command reference pages do not.

Before anything else: -o json works on every command that prints structured output, as do -o yaml, -o name, and -o template=<go-template>. If you are scripting magus, or you are an agent reading its output, reach for that first instead of parsing the human format. The human format is allowed to change; the JSON shape is the contract.

What is in this workspace?

magus ls enumerates the projects magus discovered, with what each declares:

workspace: /Users/you/repo (8 projects)

project: magus
  dir:  /Users/you/repo
  spell: magusfile
  sources: [magusfile.buzz **/*.go go.mod go.sum ...]
  depends_on: [libs/gopherbuzz]

sources and depends_on are the two lines worth reading. They are what the cache key is derived from and what the affected set walks, so a target rebuilding when you did not expect it is usually explained here.

magus describe <thing> does two jobs in one command, which is its main quirk: it defines the concept, then lists every instance.

$ magus describe targets
definition: A target is a named operation (e.g. build, test, lint) declared as
an exported function in a project's magusfile ...

targets (44):
  ci  [canonical - affected/pipeline anchor; composed in the magusfile]
  biome-check  [spell: ts]
  build  [custom - projects: console]

The bracket suffix tells you where each came from: a spell, a custom magusfile function, or the canonical set. describe accepts spell, charm, target, graph, project, workspace, module, mcp-tool, file, and tool (singular or plural).

magus where fuzzy-matches a project and prints its absolute path, bare and alone, so it composes:

cd "$(magus where console)"

Run something

magus run <target> [projects...] is the workhorse. With no projects it runs everywhere the target is defined; naming projects narrows it.

magus affected <target> runs only what a VCS diff says changed. It is not a filter over run: it walks the dependency closure, so a project you did not touch is included when something it depends on moved.

One thing to know: affected ci errors when no project in scope declares a ci target. That is deliberate. Ordinary targets fan out and skip projects that lack them, but ci is the anchor the affected set keys off, so a missing one would exit 0 having gated nothing.

To fail fast on a cheap check before the expensive part starts anywhere, run it first and pipe it in. A failed stage stops the stages after it (MGS3030), and a --plan downstream of one prints no plan:

magus affected generate --no-default-charms | magus affected ci
magus affected generate --no-default-charms | magus affected ci --plan

See Failing fast with a pipe.

For a tight loop, pipe the watcher into it:

magus watch | magus affected --stdin build

magus x is the interactive shorthand: pick a project and target from a picker. It requires a TTY and does not work in a pipeline.

The magus x picker: a filter line narrowing the project list as it is typed, the highlighted row a click or Enter would take, and the way out on the bottom rule

Typing filters, arrow keys and the mouse both move the highlight, and [esc] cancels. Off a TTY it refuses with a non-zero exit and names the non-interactive form instead of hanging. See Terminal.

Why did that happen?

Every run prints an output reference, on success and failure alike:

[pass] docs (ran, 1m36s)
  magus run generate:rw docs
out3a777178
summary: 2 cached, 5 ran, 0 failed (1m46s)

magus query output out3a777178 replays exactly what that run printed. A failure adds the reproduce command and an inspect hint:

[fail] docs generate:rw (ran, 50s)
  cause: magus generate docs: 1 spell(s) failed
  output: out462efb79
  inspect: magus query output out462efb79
  reproduce: magus run generate:rw docs

References are portable: the same inputs mint the same ref on every machine, so one pasted from CI or a teammate resolves in your checkout once your cache holds a run of those exact inputs. The inline inspect: hint above is still suppressed when magus detects CI, but that is about the runner, not the ref: by the time anyone reads the log, the ephemeral job that printed it is usually gone, and the failing output is already inline above it. If a ref resolves nowhere locally, magus query output <ref> sweeps the workspace for a target whose live cache key predicts it and prints the command that reproduces it. See output references.

The lines above ([pass] ..., the reproduce command, the ref, the summary: footer) are the TEXT rendering. magus run <target> -o jsonl reports the same facts as typed events on the same stream as run.target.result: run.scope/run.charms/run.cache for the header, run.step per ctx.needs sub-target, and run.summary for the footer. Nothing free-text reaches stdout or stderr under -o jsonl: notices, every other log record, and output printed outside a target are run.notice records on stderr.

For structural questions, the knowledge graph commands answer different shapes of "why":

  • magus query <term>: search, and show a node's neighborhood
  • magus explain <node>: one node: its edges, provenance, blast radius
  • magus path <a> <b>: the shortest path between two nodes
  • magus refs <symbol>: where an ingested code symbol is defined and used, and what calls it
  • magus graph stats: where the workspace concentrates and where it is neglected

graph stats is the one to run when you have inherited a repository:

graph: 2137 nodes, 4665 edges
connectivity: 2 component(s), largest holds 2136, 0 isolated node(s)

god nodes (most connected):
  DEGREE    IN   OUT  KIND         LABEL
      77    77     0  import       std
      61     2    59  target       content-generate

A high-degree node is a structural risk: everything depends on it, so changing it touches everything. Isolated nodes are the opposite problem: something the builder never linked up.

The insight lenses (hotspots, change affinity, ownership, trend, volatility) answer the same questions from VCS history instead of structure. They are not a magus subcommand: the console's Insight page renders all five together, and an agent reads the same report through the client tool (magus\insight).

Is my setup sane?

magus doctor validates the workspace and is the first thing to run when something behaves strangely. magus config views and updates configuration; magus init bootstraps magus.yaml, a starter magusfile, and the VCS merge driver for generated outputs.

Long-running processes

magus server start backgrounds the server, which keeps the knowledge graph warm and serves MCP. Starting one when it is already running is a no-op that still exits 0, so it chains safely in scripts. magus server stop exits non-zero when it found nothing to stop.

magus status inspects the concurrency pool of a running parent magus: what is executing, what is queued, and what is waiting on a slot.

Verbosity

Every command honors the same output flags. Which one to reach for, and what each prints, is covered in Logging and verbosity. The short version: -v for "why did this rebuild", -vv when you want to watch the build happen, and --silent for unattended runs.

clisubcommandslsdescriberunaffectedquerygraphdoctorjson output
Last updated (353014be)
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. Workspace in full.

Project

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

Magusfile

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

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. Target in full.

Op

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

Spell

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

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. Charm in full.

Module

A magus stdlib namespace a magusfile imports for host capabilities: filesystem, exec, vcs, and more. Module in full.

Buzz

The language magusfiles are written in (the .buzz engine). Buzz in full.

Cache

The content-addressed store magus consults before running a target, so unchanged work is skipped. Cache in full.

Affected

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

CI

An ordinary target you compose yourself with ctx.needs; magus does not hardcode its stages. It is the anchor magus affected ci keys off, and ci strips the rw charm. CI in full.

Output reference

A short, shareable id such as out1a2b3c for one target execution's captured output; magus query output prints those exact bytes. In OpenTelemetry terms it names a span. Output reference in full.

Pool

The concurrency pool: the shared set of slots that caps how many targets run in parallel on one machine. Its capacity defaults to MAGUS_CONCURRENCY, then 4 on GitHub-hosted runners, then min(NumCPU, 8); magus status and the dashboard report it live. Pool in full.

Slot

One unit of the pool's capacity. A target acquires the slots it needs to run (most take one) and releases them when it finishes; the pool tracks capacity (total slots), running (acquired), and queued (blocked). Slot in full.

Concurrency

How many targets run at once. It is bounded by the pool's capacity and set with --concurrency, MAGUS_CONCURRENCY, or the concurrency config key. Concurrency in full.

Queued

A target that wants a slot while the pool is full; it blocks first-in-first-out until a slot frees. The dashboard colors a sample with queued > 0 accordingly. Queued in full.

Volatility

A target that fails once and passes on rerun is volatile, as opposed to a regression that started failing and stays failing. magus keeps per-target pass/fail history and a Wilson-score volatility rate to tell them apart and auto-retry the noise. Volatility in full.

Knowledge graph

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

Insight

The reports magus derives over the graph and history (hotspots, affinity, ownership, trend, volatility, unreferenced). Insight in full.

Hotspot

An insight lens: edit frequency times complexity, the prime refactoring targets. The project view heat-colors the dependency graph by churn; --files ranks individual files. Hotspot in full.

Affinity

An insight lens: projects that change together (temporal coupling). A pair that co-changes without either declaring a dependency on the other is a candidate architectural smell. Affinity in full.

Ownership

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

Trend

An insight lens: the recent half of the window against the earlier half. A positive delta is a rising hotspot; a negative one is cooling. Trend in full.

Agent

A model working through an agent host such as Claude Code, Codex, Cursor or OpenCode. magus treats an agent as one more caller of its CLI, MCP tools and console, held to the same checks as a person. Agent in full.

Tool

An action a model can call through its host: a name, a description, a typed input and a result. magus serves its tools over MCP, each a read of the workspace model or a run of the CLI it already has. Tool in full.

Job

The unit of delegated work, and one row of the job store: what an orchestrating agent handed out, with its goal, the checkpoint it was cut against, the paths it may write or must not touch, and the one check it runs. A job's holder is either a session, for work an orchestrator handed out, or the daemon, for its own maintenance. The store records; the agent guard is what reads those facts back when grading a write. Job in full.

Run

One target executing under one magus invocation, such as magus run test web or magus affected ci. A run keeps its captured output behind an output reference. Every magus run is a run whether or not any job asked for it; see Job for how the two relate. Run in full.

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.