Skip to content

Muse Code ​

Integrate Intutic governance with Muse Code — Meta's beta terminal coding agent (binary muse, model Muse Spark, beta since 2026-08-05).

Not live-verified — beta, no public release channel

The muse binary could not be installed in the environment this integration was built in (no npm/pip/Homebrew entry, no PATH-installable artifact, no documented fixture-runner to substitute for one). Everything below the hook block/deny wire contract in particular is stated as an assumption, not a confirmed fact — see the callout further down this page. The Grok Build and Xirp pages mark their own unconfirmed pieces the same way.

How it works ​

Muse Code reads project rules from AGENTS.md once the workspace is trusted, falling back to CLAUDE.md when there is no AGENTS.md. Intutic writes the rule sets as a marked section of the workspace's AGENTS.md and keeps your own text in it. The section is shared with every other harness in the workspace that reads AGENTS.md (see Where rule sets go). Once Intutic creates AGENTS.md in a workspace that only had a CLAUDE.md, Muse Code reads AGENTS.md in its place.

The governance-critical half, hook registration, is written by museHooks.ts, the same split Goose's plugin installer uses (MCP proxy-wrapping is separate and needs a control plane). Hooks are registered at two tiers:

  • Project-level: <repo>/.muse/hooks.json
  • Managed (pre-approved) tier: an Intutic-owned ~/.config/muse/intutic-managed-hooks.json, referenced by a narrow merge into ~/.config/muse/settings.json's managed_hooks_path key. This tier is meant to keep a hook registered through it from triggering a user trust/approval prompt the way a plain user-level hooks.json entry would — taken as given, not exercised against a real muse process.

Both tiers are written every time for defense in depth: managed_hooks_path is a single global setting, so a machine where it has not landed yet (a failed settings.json write) still gets project-scoped coverage from the same write.

Muse Code exposes twelve lifecycle hook events; only two are blocking, and both are registered against the same gate script:

  • PreToolUse
  • PermissionRequest

Setup ​

1. Muse Code detection ​

Muse Code is detected by any of:

  • A .muse/ directory in the project, or
  • ~/.config/muse/settings.json existing (installed but never run in this workspace), or
  • The muse binary being found in your PATH

No config file needs to exist beforehand.

2. Initialize Intutic ​

bash
intutic init
  ✔ muse-code → /path/to/project/AGENTS.md

intutic init only detects the harness and records it in ~/.intutic/config.json; it writes no harness files. The files described on this page are written by intutic gates install (open core, no control plane), from the rule sets in .intutic/sops/ — see What writes harness files:

bash
intutic gates install

3. Start the proxy ​

bash
intutic start

4. LLM egress — launcher/env-var only, not a persistent setting ​

Muse exposes a META_API_KEY env var and a --base-url CLI flag for routing model traffic, but no persistent proxy base-URL key could be confirmed in settings.json from available docs/source. This is a materially different situation from every SDK-gated framework on this site: there, the gap is "which provider is proxy-routable"; here, the gap is "whether Muse Code has a config-file-level proxy setting at all." Route via the launcher flag or the env var per-invocation if you want LLM egress governed; do not expect intutic init/intutic gates install --route to write one into settings.json for you — nothing is written for egress today. The client hook (PreToolUse/PermissionRequest, both tiers) is the primary, confirmed enforcement surface regardless of how (or whether) egress is routed.

What gets written ​

  • Rules: the section between <!-- INTUTIC:RULES:START --> and <!-- INTUTIC:RULES:END --> in AGENTS.md, written when at least one SOP targets Muse Code or another AGENTS.md reader in the workspace. The rest of the file is yours.

  • Hook registration: <repo>/.muse/hooks.json (project tier) and ~/.config/muse/intutic-managed-hooks.json (managed tier, referenced via managed_hooks_path in ~/.config/muse/settings.json). Both are assumed to share the same { hooks: { <Event>: [{ matcher, hooks: [{ type, command }] }] } } shape codexHooks.ts established for Codex's hooks.json — the closest architectural analog, not a confirmed Muse-specific schema.

  • Hook script: .intutic/hooks/muse-check.js — the same shared gate evaluator (compiled protection floor + policy snapshot + WHERE/argPattern rules) every other JavaScript-family harness in this product runs, registered for both PreToolUse and PermissionRequest.

  • ~/.config/muse/settings.json: narrow merge-write — only managed_hooks_path is set/updated; schema_version (defaulted to 1 if the file is new) and everything else (mcp_servers, any user-set key) is preserved.

  • Skills: nothing Muse-specific. The product's skill inventory reads the workspace's .agents/skills/; a user-level ~/.agents/skills is not scanned.

To undo what intutic gates install writes here, run intutic disconnect --harness muse-code: each file goes back to what it held before Intutic first wrote it, or is deleted if Intutic created it, and edits you made since are kept. In AGENTS.md only the marked section is taken out, and it stays while another harness that writes it is still connected. See intutic disconnect.

Pre-tool hooks (blocking, but the block contract is ASSUMED) ​

Muse's own documentation confirms that PreToolUse and PermissionRequest are blocking lifecycle hooks, but does not state how a hook signals a refusal. muse-check.js uses exit code 2 — the same contract codexHooks.ts uses for Codex — because it is the closest architectural analog (a JS gate reading JSON on stdin, registered at a project-level and a user-scoped hooks.json), not because it has been observed against a real muse process. If the real contract turns out to be a JSON object on stdout instead, every Muse Code block today exits 2 with nothing on stdout — which a stdout-reading harness would treat identically to an ALLOW. State this plainly to anyone relying on this integration in production: it would look correct in every test this repository runs (which drives the emitted script directly and asserts on its exit code) while doing nothing against the real product.

Every decision is appended to .intutic/events/hook-events.jsonl, same as every other harness — that audit trail itself does not depend on which block contract turns out to be correct.

Four assumptions, not four facts

  1. The block/deny wire contract — exit code 2, copied from Codex, not confirmed for Muse.
  2. The hooks.json schema — the { hooks: { <Event>: [...] } } shape is Codex's, assumed to transfer.
  3. managed_hooks_path's actual behaviour — whether it is additive to the project/user tiers or overrides them, and whether it is read once at startup or on every hook-eligible call, is unconfirmed.
  4. The mcp_servers entry shape for streamable_http — assumed url/headers-keyed, matching every other JSON-map harness's remote-transport convention; if Muse nests it differently, the entry is silently left unwrapped rather than erroring.

Each is a small, isolated edit in museHooks.ts/mcpAutoWrite.ts once a real install is available to test against.

Config details ​

PropertyValue
Harness typemuse-code
Rules fileAGENTS.md (a marked section)
Hook files<repo>/.muse/hooks.json, ~/.config/muse/intutic-managed-hooks.json, ~/.config/muse/settings.json (managed_hooks_path merge), .intutic/hooks/muse-check.js
Detection.muse/ or muse in PATH, or ~/.config/muse/settings.json present
FormatMarkdown (rules), JSON (hooks/settings)
Write strategyAtomic (write to .intutic-tmp, then rename)
Block contractExit code 2 — ASSUMED, copied from Codex's confirmed contract, not verified against a real muse install
LLM egressMETA_API_KEY env var / --base-url flag — launcher-only; no persistent settings.json key confirmed, nothing written by intutic init/intutic gates install

The circuit breaker for AI agents