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

magus-shell

Check a command against this workspace's conventions before running it

Synopsis

magus shell '<command>' [flags]

Description

Check a shell command against this workspace's conventions, and name the better command when there is one.

The rules are the workspace's own. A raw `go build` misses the cache and the affected set; a recursive grep misses what the symbol index already knows; `git add -A` sweeps regenerated output into a commit about something else. None of that is a fact about who typed the command, which is why this is a plain subcommand rather than something under an agent namespace.

Nothing is executed and nothing is prevented. This reports; you decide.

THE INPUT ARRIVES TWO WAYS, and they are the same command either way. A person passes it as one quoted argument. A host pipes it on stdin, where it may be plain text or the JSON envelope the host already writes, so nothing has to survive being quoted through a shell twice. That is deliberate: an agent and a person get the same verdict from the same entry point, and neither reads documentation the other cannot.

--path judges the input as a file path an edit is about to write, rather than as a shell command.

--observe records a path the agent merely REACHED, without judging it. No rule applies to a read, so the verdict is always pass and the activity event previews as observed rather than as a guard decision. Which of a host's tools only look is the caller's knowledge, never magus's.

--agent-name, --session, --transcript, and --event are attribution, not policy. They record who produced the observation on the activity event, and the verdict never reads what they say. The host name is an opaque label rather than a set magus knows: a magus that enumerated hosts would need a release per host, and a caller that cannot extract a session id must still be able to get a verdict.

--transport names the form of the hook calling, such as sh or buzz, as that form declares it. Installed hook glue passes it, and glue that passes it without --agent-name is refused with MGS3024: the configuration "magus agent harness apply" writes names the host, so a call that does not is a stale or hand-written config, never defaulted to one host. With --agent-name and --session it names the CALLER that the once-per-session notices and the full text of a repeated deny are kept for, as one key, host/transport/session. A session id alone is not enough: two hosts can present the same id, and two forms of one hook wired into a session are two callers, each told a rule in full once.

--lease is the exception: it IS policy. It names the lease the caller is acting as, and a write is then graded against that lease's declared write boundary in this workspace's lease ledger. Inside its write paths passes; inside its deny paths, or inside another live lease's write paths, is denied and the reason names the owning lease. It defaults to the magus.lease member of $BAGGAGE - the W3C baggage list a spawning tool exports - and the flag wins when both are set.

A call that names no valid lease while a fleet is running is ADVISED and never blocked: a person editing their own repository has no lease id, and the guard is a seatbelt for callers that opt in rather than a sandbox. With no ledger, or with no lease in it declared or running, nothing is graded and nothing is read.

EXIT CODES are the contract a host blocks on: 2 is a deny and everything else is allowed. An advisory exits 0 on purpose - it attaches context and does not block, and a suggestion that failed a script would not be a suggestion. Input that could not be READ is 2, so a host that blocks on 2 fails closed when bytes were lost on the way in; an EMPTY input passes, because a wrapper that hands this nothing must not block every tool call.

Options

--agent string
The host's id for the subagent making this call, empty for the main conversation; a subagent magus saw spawned is graded under its job
--agent-name string
Name of the agent host this invocation came from (attribution only); required with --transport
--event string
The host's hook event name (e.g. PreToolUse)
--lease string
The lease this call is acting as, graded against the ledger's declared write boundary; outranks the spawn record, the checkout's marker and magus.lease in $BAGGAGE
--observe
Record the input as a path the agent reached, without judging it: no rule applies and the verdict is always pass
--observes-skill-loads
This host's wiring reports skill loads to magus, so a rule may require one before a spawn; without it those rules stand down
--path
Judge the input as a file path an edit is about to write, not as a shell command
--renders-ask
This wiring puts an ask verdict in front of the person through the host's own approval prompt; without it an ask is returned as a deny
--session string
The host's own session id for this invocation
--transcript string
Path to the host's own log of this session, recorded as a pointer; magus never opens it
--transport string
The form of the hook calling, such as sh or buzz; the once-per-session notices and deny explanations are kept per host, transport and session. Without --agent-name it is refused (MGS3024)

Exit status

0
The input is allowed: pass, or advise, which attaches context and does not block. --observe always lands here, because it judges nothing. An EMPTY input is also 0: a wrapper that hands this nothing must not block every tool call.
1
Not returned by a verdict. A wrapper should treat anything other than 2 as allowed rather than enumerating codes, so that a future signal added here does not start blocking commands.
2
A DENIED command or path, and also input that could not be READ - the two share the code deliberately: a guard that could not parse its input has not cleared the command either, so a host that blocks on 2 fails closed in both cases. Misuse (an unquoted command, an unknown flag) is also 2.

Examples

Check one command

magus shell 'go test ./...'

Check a search

magus shell 'grep -rn HandleFoo internal/'

Judge a path an edit would write

magus shell --path MAGUS.md

As a host's pre-tool-use hook

printf '%s' 'go build ./...' | magus shell

Record a path an agent read, without judging it

printf '%s' 'internal/cache/output.go' | magus shell --observe

Grade a write as a lease

printf '%s' 'internal/job/store.go' | magus shell --path --lease f2-guard

The verdict as JSON

magus shell 'git add -A' -o json

See Also

magus(1), magus-ls(1), magus-describe(1), magus-run(1), magus-x(1), magus-where(1), magus-affected(1), magus-graph(1), magus-query(1), magus-explain(1), magus-path(1), magus-refs(1), magus-watch(1), magus-events(1), magus-status(1), magus-clean(1), magus-vcs(1), magus-queue(1), magus-doctor(1), magus-config(1), magus-session(1), magus-memory(1), magus-job(1), magus-notes(1), magus-diff(1), magus-server(1), magus-broker(1), magus-mcp(1), magus-buzz(1), magus-completion(1), magus-man(1), magus-init(1), magus-spell(1), magus-agent(1), magus-self(1), magus-version(1)

generatedinternal/cli/registry.goclimagus shellguardconventionshookpre-tool-use
Last updated (a9ff8609)
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.

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.

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.

Sandbox

The restricted filesystem and environment a target runs in, so builds stay reproducible and side-effect-free. See sandbox.

Broker

The per-user background process that holds this host's capacity: the machine budget every run claims slots from, and the shared services runs keep warm. A run starts it on demand; broker: off in magus.yaml runs without one. See server.

Server

The background process a person starts with magus server start. It serves MCP, the console, background jobs and the warm knowledge graph, and adopts nested magus calls into one pool. See server.

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.

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.

Session

An agent host's conversation, by the id the host delivers to its hooks. magus never mints one: a record with no session is unattributed, and the OS user it carries says whose account ran it.

Invocation

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

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 server, for its own maintenance. The store records; the agent guard is what reads those facts back when grading a write. See doctrine.

A job is not a run. magus run build web is a run, and no job exists for it. A job causes runs: its check executes as one, and a server job records the invocation of its last one. Jobs are listed with magus ls jobs and in the console's Jobs view; runs are listed in the Runs view.

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.

Lease

The grant a holder takes on a job: the write and read paths that job declared, enforced in the checkout that took it with magus job exec. A job is the piece of work; a lease is permission over it.

Lease id

The short identifier a worker carries (the --lease flag, or the magus.lease member of the W3C BAGGAGE environment channel) so its runs, journal facts, and guard verdicts attribute to the job it holds. Letters, digits and -_./: only.

Advisor

One read-only check from the advice suite: it reads the changeset through magus and writes one titled section of findings. The same advisors run as a pull request comment in CI and inside magus diff --impact locally.

Conventions

This page uses none of the site's convention markers. The full set is on the conventions page.