magus v0.3.0 is out. See what's new
¶ View markdown source · ✎ Suggest an edit
5 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 tools, targets, projects, workspaces, and mcp-tools.

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.

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 will not work in a pipeline.

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.

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
  • 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.

magus insight answers the same questions from VCS history instead of structure: hotspots, change affinity, ownership, trend, volatility.

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 daemon, 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 actually 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 (a103255f)
Earlier changes on this page (3)

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.

Operation

A single tool-native command a target composes; the middle of the work hierarchy (Spell to Operation 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.

Buzz

The language magusfiles are written in (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.

Output reference

A short, shareable id (out1a2b3c, "ref" for short) for one target execution's captured output; it appears on each target's line, and magus query output out1a2b3c prints those exact bytes. In OpenTelemetry terms it corresponds to a span (one target execution) within its trace (the whole magus invocation). See output-refs.

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. See daemon.

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). See daemon.

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. See daemon.

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. See daemon.

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. See volatility.

Knowledge graph

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

Insight

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

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. See insight.

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. 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.

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. See insight.

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.