Muse Spark Code puts Meta's Muse Spark model to work inside VS Code as a coding agent. A chat panel streams answers, reads and edits your files with reviewable diffs, runs commands behind permission modes, and delegates to subagents you can watch and steer. It also remembers past conversations and takes dictation from your microphone. It runs on your Muse subscription through the Muse Code CLI, or on a Meta Model API key, and never mixes the two.
Unofficial. Not affiliated with or endorsed by Meta. "Muse Spark" and "Muse Code" are Meta trademarks. You bring your own credentials.
Contents: What's new · Highlights · Screenshots · Get started · Backends · Permission modes · Rules, skills and memory · Muse Code's own tools · The panel · Voice dictation · Paid features · Languages · Limits · Commands · Settings · Requirements · Privacy · Troubleshooting · Development
- Install and sign in from the panel. Without Muse Code, Install Muse Code shows Meta's install command for your system and runs it in a terminal you can watch, then offers sign-in. Sign in with your Meta account now shows its approval code right in the panel.
- PDFs and text files. Attach, paste or drop PDFs (up to 32 MB) on the Model API backend, and pick UTF-8 text files from the workspace on either backend. The Model API agent also reads workspace PDFs and images itself.
- The Model API backend catches up with Muse Code:
- the MCP servers from Muse Code's settings and the same memory notes;
- session goals,
!shell commands and background work; - opt-in hooks and subagents.
- Paid extras, opt in and loud. Web search, image generation and edits,
Muse Voice, subagents and scheduled
/loopprompts on your Model API key. Each is off until you turn it on and accept its price, every use is marked paid, and Account & usage tallies them. - Rewind the conversation, or take a side chat. Any sent message can branch the conversation before itself; Side chat opens a Plan-mode branch without stopping the main one.
- More of Muse Code in the panel. A row for every tool Muse Code runs, workflows as live cards, goals, and background tasks you can stop.
- Behind a corporate network. Muse Code gets VS Code's proxy,
museSpark.sandboxNetworksets its sandbox network, a request that never reached Meta says why, and Muse Spark: Diagnostics reports the network posture.
0.8.0 brought the panel in fourteen languages; 0.7.0 brought / as in
Claude Code, skills, MCP servers and hooks in the panel, worktrees, export
and the accessibility gate.
Every change is in the CHANGELOG.
- Streaming chat with tools you can see. Every read, edit, write and shell command is a row in the transcript: green when done, pulsing while running, red when refused, grey when a stopped turn cut it off. Edit rows show the diff, the path opens the file with the changed lines selected, Click to expand opens VS Code's diff editor, and any output opens in an editor tab with a click.
- Permission modes, like Claude Code. Manual, Edit automatically, Plan and
Auto (Bypass behind a setting), switched from the mode button or
Shift+Tab. Gated commands arrive as approval cards with the CLI's own choices; questions from the agent arrive as question cards with radios, checkboxes, tabs and an "Other" answer. /for everything. The palette holds the actions, the model, effort and thinking, the permission mode and your skills; type a letter after the/and it narrows to the slash commands, as in Claude Code.- Subagents on a map. When Muse Code delegates, or the Model API backend runs the paid subagents you turned on, each agent is a row and an N agents pill opens the Agent map: role, status, tokens, each agent's own transcript, and the controls the backend offers.
- Workflows you can follow. When Muse Code runs a multi-agent workflow, the run is a card that keeps updating after the reply: its agents with their state, time and tokens, and the result it returned. Owner controls wait for a live accepted-command capture.
- Reply and quote with context. A reply's ⋯ menu has Reply to this output; highlight anything in the chat and right-click for Ask about this or Comment on this. The passage, its author and your intent travel with the message.
- Voice dictation at no cost. Tap or hold the microphone (
Ctrl+D) and speak; the words land at the caret. Windows and macOS use the recogniser built into the operating system, so no audio goes to a paid service unless you turn on Muse Voice. - Paid extras, only if you ask. On a Model API key: web search with its sources, image files made on request, and Meta's Muse Voice for dictation. Each is off until you turn it on and accept its price, marked paid wherever it is used, and tallied in Account & usage.
- Scheduled prompts under your control. On the Model API backend,
/loopsaves a recurring prompt in this conversation. A due prompt waits for you to run and confirm it; your key is never spent unattended. - Two backends, never mixed. Your Muse subscription through the Muse Code CLI, or a Meta Model API key (pay as you go) with the extension's own tools. The pasted key is never handed to the CLI.
- Set up from the panel. No Muse Code yet? Install Muse Code shows Meta's command and runs it in a terminal; Sign in with your Meta account shows its approval code in the panel.
- Context the way you work.
@mentions with.gitignore-aware fuzzy search, the open file or selection as a chip, images and PDFs pasted or dropped, andAlt+Kto mention the editor selection. On the CLI backend the agent can also read the Problems panel. - History that survives the window. Every conversation in the workspace, searchable, resumable with its full transcript, archivable, with fork and rewind on every sent message. The sidebar picks its last conversation back up within ten minutes, and an editor-tab conversation comes back after a window reload.
- Account & usage. On Muse Code, your subscription's current and weekly
windows; this conversation's tokens (and cache hits, on the Model API); and
what has been eating your usage (reminder agents, subagents, long
sessions), from
/usage. - In your language. Fourteen of VS Code's display languages, with the model's side kept in English so it behaves the same everywhere.
- Accessible and observable. Checked against WCAG 2.2 AA in every default theme, and a log that records what happened without what you wrote.
- No telemetry, no hosted server of its own. What leaves your machine and where it goes is written down in PRIVACY.md.
Rendered from the shipped panel by its own UI harness (npm run harness:shots) against a scripted session, so they match the build.
-
Install Muse Spark Code from the Marketplace (VS Code 1.125 or newer), or from a
.vsixattached to a GitHub Release:code --install-extension muse-spark-code-0.9.0.vsix
-
Open the Muse Spark view from the activity bar (or press
Ctrl+Shift+Alt+Escon Windows,Cmd+Shift+Escon macOS,Ctrl+Shift+Escon Linux for a conversation in an editor tab). -
If Muse Code is missing, Install Muse Code opens a confirmation dialog showing Meta's exact command for this operating system. The same action is in Account & usage while you work with a Model API key. Run installer opens a visible VS Code terminal; the panel checks for the CLI and offers sign-in when it appears. You can also open Meta's installation instructions. If VS Code cannot open the installer terminal, the panel reports that directly and keeps the manual instructions available. Sign in, one of two ways:
- Sign in with your Meta account shows an approval code in the panel. Open its sign-in page in your browser and approve the code within ten minutes, before it expires. Cancel sign-in stops the temporary CLI sign-in process; if the browser approved just before, the panel follows what Muse Code saved. If you deny the code, it expires, or Muse Code cannot save the sign-in, the panel says so; an ending Muse Code has not been seen to send is shown in its own word. Work is billed to your Muse subscription.
- Use a Model API key takes a key from dev.meta.ai (Meta's current
keys start with
LLM_; older ones look likeLLM|<id>|<secret>), stores it in VS Code's secret storage and runs the Model API backend with the extension's own tools, pay as you go. Account & usage lets you add or replace that key while Muse Code is signed in; there the key pays only for paid features you turn on. After a CLI install, Account & usage also offers Sign in with your Meta account.
Signing out ends the old account's conversations and clears them from the panel; your unsent draft stays. If sign-out cannot finish, see Troubleshooting.
-
Type a message and press
Enter./shows the palette,@mentions a file, the microphone dictates.
VS Code opens the extension's four-step walkthrough on install; Muse Spark: Open Walkthrough brings it back.
Each panel is its own conversation, started on the first message with the
standard muse-spark-1.3 model (never a contributor-tier model by default).
The model pill shows the model as soon as the panel opens.
| Backend | Sign-in | Billing | Tools |
|---|---|---|---|
Muse Code CLI (muse serve, Muse Session Protocol via @muse-code/sdk) |
The CLI's own device-code browser sign-in | Your Muse subscription | The CLI's, inside its OS sandbox where that works (see shellSandbox); its bundled skills, your user rules, its own memory, subagents, and the Problems panel through the extension |
Meta Model API (https://api.meta.ai/v1) |
A key from dev.meta.ai, kept in SecretStorage, sent only to Meta | Pay as you go | The extension tools: read, edit, write, search, list, shell, skills, questions, todos, goals, memory and diagnostics; configured MCP servers; opt-in hooks and bounded subagents; paid web search and image tools when turned on; workspace rules and skills |
museSpark.backend picks: auto (default) uses the CLI when it is installed
and signed in, otherwise the Model API when a key is stored; museCode and
modelApi force one. The palette's Backend row shows which one this
window runs on. The CLI looks for muse through museSpark.museBinaryPath,
then PATH, then the platform's install folder (%LOCALAPPDATA%\Programs\muse
on Windows, ~/.local/bin elsewhere).
Conversations on the Model API backend are saved as they go under VS Code's workspace storage for the extension, so the History dialog lists them after a reload, and a resumed one continues with its transcript and its edit patches while the same Model API key is stored. History, resume, reads and forks are limited to that key's sessions. Replacing the key starts a fresh conversation; older sessions remain on disk for their original key. Sessions saved before ownership was recorded remain on disk but cannot be reopened because their account cannot be proved. The CLI backend keeps its own session store. Replacing its secondary Model API key keeps the Muse Code conversation running. A paid image awaiting its popup or a retry stops if that key changes; the old request cannot use the new key. If the panel itself ever fails to render, it shows the error and a Reload button instead of going blank; Reload brings the conversation back as it was, running turn and waiting cards included.
Sign-out and account replacement clear the panel's transcript, loaded tool
output, agent transcripts and retained file chips before another account
signs in. Unsent draft text stays in the composer. When an installer makes a
signed-in Muse Code CLI available in auto mode, the current Model API
session ends before the next message starts a fresh CLI session.
| Mode | Model API backend | Muse Code backend |
|---|---|---|
| Manual | Asks before every edit and every command | The CLI decides: it applies edits inside the workspace without asking (Muse Code 1.3.0) and asks before commands |
| Edit automatically | Approves plain file edits, asks before commands | As Manual, plus the file approvals the CLI does raise are approved for you |
| Plan | Refuses edits and commands | The CLI plans without editing |
| Auto | Runs edits, asks before commands (no safety-check model on this backend) | The CLI runs its own safety check and asks for anything risky |
| Bypass | Only with allowDangerouslySkipPermissions; nothing asks |
The same |
A Manual approval still needs your answer if you open the conversation in another panel set to Edit automatically. Joining a conversation never approves a card that was already waiting. A Manual panel's new edit approval also stays Manual when an older Edit automatically panel remains open on that conversation. While two panels share a conversation, every approval needs an explicit choice. Edit automatically resumes when it is the only panel holding that session.
"Always allow in this session" on a command allows that exact command line
again, nothing broader; on an MCP tool, that tool. An MCP tool asks like a
command on the Model API backend; Auto runs one its server marks read-only
without asking, as Muse Code does, and Plan refuses all but those, which ask. The Model API backend's file tools refuse any path
that leaves the workspace, including through a symbolic link or junction
inside it. Muse Code refuses such a write while its sandbox runs; without
the sandbox (shellSandbox set to off, or auto for a Windows workspace
under your profile) its file tools may write outside the workspace, so
choose the permission mode with that in mind.
Protected writes. On the Model API backend, writes to files that
configure or run code always ask, whatever the mode: .git, .husky,
.vscode, .idea, .devcontainer, .github/workflows, .agents (the
agent's own skills and memory), .muse (Muse Code's hooks), AGENTS.md,
CLAUDE.md, .envrc and .gitmodules. Plan refuses them and Bypass skips
the card. On Muse Code the CLI decides which writes are protected, and the
extension never approves one for you. A note saved with the memory tools is
the one exception under .agents: those tools write only Markdown notes in
the memory folders, so they are treated as ordinary edits (see
Memory).
In a trusted workspace the agent follows the same files Muse Code does:
- Rules:
AGENTS.mdat the workspace root (CLAUDE.mdwhere there is noAGENTS.md), and the same files in subdirectories, which apply once the agent touches a path beneath them; the deeper file wins. - Skills:
.agents/skills/<id>/SKILL.mdin the workspace (project scope) and Muse Code's personal root~/.config/muse/skills($XDG_CONFIG_HOME/muse/skillswhen set). The palette's Skills group lists them,/id argumentsinvokes one, and the model loads one itself when a task matches its description.user-invocable: falsein the front matter keeps a skill out of the palette. - Memory: Markdown notes the agent keeps for later conversations, in Muse Code's three places, on both backends; see Memory.
Muse Spark: Create AGENTS.md starts the rules file for a workspace that
has none. muse init writes it when the CLI is installed and the workspace
is trusted (the CLI's own scaffold, no model call); otherwise the extension
writes the same layout. An existing file is opened, never overwritten.
On the CLI backend Muse Code loads all of this itself (the extension starts
it with --trust-workspace), plus its bundled skills and your user rules.
On the Model API backend the extension loads the files above and nothing
else:
- Sizes: a rules file or a
SKILL.mdover 64 KB is skipped with a warning in the log; the rules together are cut at 256 KB, and each scope'sMEMORY.mdat 200 lines or 32 KB. - Encodings: UTF-8, or UTF-16 with a byte-order mark; a file that is not text is skipped with a line in the log. Memory notes are UTF-8 only, as Muse Code reads them.
- Links: a skill folder may be a symbolic link or junction. In the workspace it must lead to a place inside it or it is skipped; links in the personal root are followed wherever they lead.
- The system prompt also carries the date, the git branch, the number of
changed files and the latest commit subjects at session start (metadata
only), and a short set of working rules (read before editing, no commits
unless asked,
path:linereferences).
In VS Code's Restricted Mode (an untrusted folder), neither backend loads
rules or skills. The Model API backend loads no memory, offers no memory
tools, starts no MCP servers and runs no hooks. No shell command or git
runs (git reads
the repository's own config, which can name programs to run): @ mentions
come from VS Code's file search and the prompt carries no git facts. Trust
the workspace to enable them. Muse Code itself, by its documentation,
still reads a repository's committed project memory in an untrusted
workspace: treat a checkout's .agents/memory/MEMORY.md as text someone
else wrote.
Muse Code keeps memory in three scopes, and both backends read and write the same notes, so a fact saved in one is known in the other:
| Scope | Where the notes are | Who sees them |
|---|---|---|
| Your memory for this project (the default) | ~/.local/share/muse/memory/projects/<folder>-<hash>, outside the repository |
You, in this workspace |
| Project memory | .agents/memory in the repository |
Everyone who clones it |
| Your memory for every project | ~/.local/share/muse/memory/personal |
You, everywhere |
$XDG_DATA_HOME replaces ~/.local/share when it is set (on Windows too, as
Muse Code does). Each scope may keep a MEMORY.md index, one line per note:
- [Title](file.md) | hook.
Names with spaces or Markdown punctuation are encoded in the index link, so
the note can still be found and its line removed when the note is deleted.
- Memory… in the palette (
/memory, or Muse Spark: Memory in the Command Palette) lists up to 500 Markdown notes per scope, nested up to eight folders, with each note's scope and what it is about. Pick one to open it in an editor, where you read and change it like any file, or to delete it (to the trash, after a confirmation). New note… asks for the scope, a name and a one-line description, creates the note and opens it. A note the view creates gets its line in the scope'sMEMORY.md, and a note it deletes loses its lines, so the index the next conversation reads stays true. - On the Model API backend the model has Muse Code's own memory tools,
read_memory,add_memoryandedit_memory, with the same arguments and results, so their rows look the same as on the CLI backend. At the start of a conversation it is given each scope'sMEMORY.mdand the names of the other notes (up to 48 per scope), as Muse Code gives them. A new note gets its line in its scope's index. A write asks in Manual, is made in Auto and Edit automatically, and is refused in Plan, like any edit; a read never asks. A path Muse Code would refuse (outside the scope, hidden, not a.mdfile, or through a link) is refused before any card. - On the CLI backend Muse Code runs its memory tools itself.
A new note is published only if its path is still free. The extension writes
and syncs it under a hidden temporary name, then hard-links the complete file
to the note's name in one step. Another writer's file is never replaced or
exposed half written; a filesystem without hard-link support refuses the
create rather than using a partial-write fallback. The index line is added
only after publication. Updates to an existing note replace it whole (a
temporary file renamed over it). The extension does not take Muse Code's own
lock, so two agents updating the same note or index in the same instant could
lose one of the writes.
The .muse-memory.lock file can remain after its owner exits; its presence
or stored PID alone does not show that a write is in progress.
These use the Muse Code CLI, except worktrees, MCP servers and hooks, which the Model API backend has too (each says how below); memory works on both backends as Memory describes.
What its tools show. Every tool Muse Code runs has a named row, and the ones that answer in JSON are shown as what they mean:
- Memory (Read memory, Save memory, Edit memory): the note saved or read back, where it lives (your memory for this project, the project's shared memory, or your memory for every project), and an edit as the text replaced beside its replacement.
- Goals (Set goal, Check goal, Update goal, Goal progress): the objective, its status, a progress bar, what the agent is doing now and next, and the tokens spent against any budget.
- Scheduled prompts (
/loopand cron): each prompt with its schedule, whether it repeats, its next run and how often it has run. These rows report Muse Code's native cron tools, not the extension's Model API schedules described below. - Web search: the results as links that open in your browser, with their snippets. Search rows on the Model API backend look the same.
- Background work: a command Muse Code moved to the background shows what it printed and that it is still running, and it stays running after the turn ends instead of reading "Interrupted". See Background work under The panel for moving one there yourself and stopping it.
- Pictures: when the agent reads an image, or the Model API backend generates one, the row shows it; click it to open the file. Only images inside the workspace are shown. The preview reads the checked target with the same 10 MiB file cap if a workspace link or file changes meanwhile.
- MCP tools read "tool (server)", and any tool the panel has no special view for shows its arguments and result as indented JSON.
Skills. The palette's Skills group has two more rows on the CLI backend:
- Manage skills… is a checklist of every skill Muse Code knows
(built-in, yours, this project's, plugins); unchecking one turns it off
(
muse skills disable). - Import skills… shows what
muse skills importwould copy from Claude Code or Codex into your Muse skills folder, imports it once you confirm, and reports what was imported, skipped, failed or quarantined.
Muse Code reads skill changes when it starts, so both end by offering to
restart it; the conversation continues on your next message. Where the
session offers Muse Code's resume-claude and resume-codex skills, the
palette's Context group has Continue a Claude Code session and
Continue a Codex session.
MCP servers and hooks. Muse Code reads both from its own settings file
(~/.config/muse/settings.json, or under XDG_CONFIG_HOME), and project
hooks from .muse/hooks.json. The extension shows them and never edits them:
- MCP servers… lists each server:
- Its transport, where it points (a URL is cut to its scheme and host), and whether Muse Code stops when it fails ("required") or skips it.
- The names of its environment variables and headers. The values stay in the file.
- A remote server can be signed in to or out of. That runs
muse mcp loginormuse mcp logoutin a terminal, with the server's name quoted. - Restart Muse Code to load changes, since Muse Code reads the file when it starts.
- Loud warnings for the two settings mistakes that make Muse Code load no
server at all: both
mcpServersand the oldermcp_serversin one file, orrequiredbesidemodeon a server. - On the Model API backend the window runs the same servers itself, so
their tools work with your key as they do in Muse Code:
- When: they start with the first conversation, and the first message waits for them; they stop with the window, and Restart the MCP servers in the view restarts them with the settings as they are then. At most four start together, so a long server list can make the first message wait longer. None runs in Restricted Mode.
- The view shows each one's state: connected with how many tools, still
starting, turned off, or not running and why. A server's row opens the
log, where its stderr goes. The extension's own diagnostics server is
listed as
ide, built in. - Loud: a server that is not running is a warning in the panel, once
per conversation; a required one (the default, unless its entry says
"mode": "optional") stops the message with the reason and how to fix it, as Muse Code refuses to start without it. Both keys in one file, orrequiredbesidemode, loads none, as in Muse Code, and says so. - What an entry may hold:
command,args,env,cwdandframing(auto,line_delimited_json,content_length) for a local server;urlandheadersfor a remote one (streamable HTTP);enabled,mode,startup_timeout_sec,tool_timeout_sec,enabled_toolsanddisabled_toolsfor either.${VAR}reads an environment variable of VS Code's; an unset one keeps the server from starting. A local server sees only a short list of VS Code's environment variables (PATH,HOME,TEMPand the like) plus its ownenv. On Windows a.cmdlauncher such asnpxruns throughcmd.exe, and an argument with"or%is refused there. A hidden Windows job helper passes stdin, stdout and stderr as binary pipes, assigns the server to its job before it runs, after a private handshake confirms this extension process still owns the launch. It ends descendants on Stop, server exit or extension shutdown. If Windows cannot load the helper, local stdio servers do not start; the view gives the reason. Remote HTTP servers can still connect. - Sign-in:
muse mcp loginsigns in Muse Code only. A remote server that needs a credential takes it in its entry'sheaders("Authorization": "Bearer ${MY_TOKEN}"). - Tools are named
mcp__<server>__<tool>and read "tool (server)" in the transcript. Their results reach the model as text and pictures; audio and files are described instead. Resources, prompts and sampling are not supported.
- Hooks… lists the project's, yours and your administrator's hooks, and opens the file behind each. A hook runs through your shell outside Muse Code's sandbox and approvals, so read a repository's hooks before you trust its folder.
On the Model API backend, museSpark.modelApiHooks is a machine-scoped
setting, off by default. When enabled, a new session in a trusted workspace
reads the same managed, user and project hook sources. No hook loads or runs
while the folder is in Restricted Mode.
The implementation currently fires SessionStart, UserPromptSubmit,
PreToolUse, PermissionRequest, PostToolUse, PostToolUseFailure,
PostToolBatch, PreLLMCall, PostLLMCall, PreCompact, PostCompact,
SubagentStart, SubagentStop, Stop, StopFailure, SessionEnd and
Notification;
unsupported events and handlers are reported and skipped. Hook commands run as your user outside
the agent's sandbox, with a narrow environment that excludes the Model API key.
They get JSON on stdin, have a timeout and output cap, and may approve an
ordinary tool call that would otherwise ask. Paid calls and protected writes
still need your confirmation. A PreToolUse hook that asks forces a human
card for memory reads or writes, including in Bypass and Edit automatically;
Plan still refuses memory writes. Review each source with
Muse Spark: Hooks in the Command Palette before enabling the setting.
On the Model API backend, that picker shows the machine setting's on/off state
and opens it. Turning the setting off stops hook dispatch in an open session;
source file changes are read at the next session start.
Model-call hooks receive bounded summaries without inline image bytes or the
Model API key. A pre-call veto stops the request before it reaches Meta. A
post-call veto stops returned tools and follow-up requests. An isolated Muse
Code echo capture also ended the run as failed without another model request.
Pasted media data URLs inside ordinary text are removed before any model-call
hook preview is shortened; the original text still reaches the model.
Tool hooks receive bounded previews of arguments and output, with media data
URLs and credential-named fields omitted. MCP tools and the model still use
the original arguments and results. A required MCP server failure ends the
turn even if a post-tool hook asks to stop it.
Worktrees. New worktree… asks for a new branch and its base (the current commit or any local branch), creates it in a folder of its own, and offers to open it in a new window, so a conversation there leaves your checkout alone:
- Where it goes:
<repository>.worktrees/<branch>, beside the repository, so the second copy never lands inside your workspace. A/in the branch name becomes-in the folder's. - Refused: a name git rejects, a branch that already exists, and a folder that is already there.
Remove a worktree… lists the others (never the main checkout or the one this window is in) and deletes the chosen folder. Its branch stays. A worktree with uncommitted changes is removed only after a second confirmation that says the changes will be lost. Both commands need a trusted workspace, since git does not run in Restricted Mode.
Give a conversation a goal and Muse keeps working toward it across turns, on
both backends, as Muse Code's /goal does.
- Set one with
/goal <objective>in the prompt, or choose/goalin the/menu, which leaves/goalready for the objective. When nothing is running, Muse starts on it at once; a reply that is running takes it up instead. - The goal strip above the task list shows the objective, its status (Active, Paused, Complete, Blocked, or a limit reached), a progress bar, and what the agent says it is doing now and next.
- Its controls: Pause or Resume, Edit (the objective changes in place;
a paused goal stays paused) and Clear. Typed, they are
/goal pause,/goal resume,/goal edit <objective>and/goal clear. Stop pauses an active goal. A command that cannot apply (there is no goal, or the goal is finished) says why. - On Muse Code these are Muse Code's own goal verbs. Its goal loop also continues unfinished work on its own and checks the work before the goal closes; each of those is a model turn on your subscription. A resumed conversation shows its goal.
- On the Model API the agent has the same four goal tools (Set goal, Check goal, Update goal, Goal progress, with Muse Code's rows), the goal is kept with the conversation, and it is pinned into every request while it is active. A turn starts only when you set, edit or resume a goal while nothing runs: the backend never continues on its own and runs no check of its own, so your key pays for nothing you did not ask for. A token budget the agent gives a goal stops it once spent.
On the Model API backend, /loop 10m Review the build saves a prompt in the
current conversation to become due every ten minutes. Use m, h, or d
for minutes, hours, or days; /loop "0 9 * * 1-5" Summarize new bugs uses
a five-field cron expression in your machine's local time. /loop <prompt>
defaults to ten minutes. /loop list refreshes the panel's schedule list,
and /loop cancel <id> removes one. The list above the composer shows each
prompt, cadence, next run or due state, run count, and ID, with Run now
and Cancel schedule controls.
Each job belongs to this workspace, conversation, and stored Model API key.
Signing out or switching backends hides its prompts immediately; a temporary
CLI sign-in attempt leaves the still-active Model API list in place.
It expires after seven days; /loop 7d ... has no run before that deadline
and is refused. A due prompt stays pending until Run, Cancel or expiry.
Only a loaded conversation checks for due work;
closing VS Code stops checks. A missed recurring interval leaves one due
occurrence, without a backlog. A due prompt never runs by itself: turn
on Scheduled prompts (paid) and accept both published standard and
contributor token rates, then choose Run now and allow that
occurrence's prompt, model and exact tier rates in the paid-use popup
(Allow once, Allow always in this workspace, or Deny). An
unpriced model cannot be approved. Declining leaves it due until expiry and
makes no API call. Bypass
permissions does not skip either one; only Allow always in this workspace
skips the per-run popup, and Run now is still yours to press. A changed model, prompt,
conversation or paid setting refuses an old confirmation; the client checks
the key it actually reads before HTTP. A receipt claimed just before such a
change is never replayed, so that occurrence may be skipped without a charge.
A run that reaches its first Model API request has a paid row
in the transcript and a count in Account & usage; its token cost is already
in that conversation's token estimate. A run admitted just before a crash
is not replayed, even if its result was never seen. Cancel does not stop a
turn that already began.
Muse Code has its own subscription-backed cron_create, cron_list and
cron_delete tools. Ask it in chat to schedule, list or cancel its jobs;
those are not the Model API jobs shown by this panel. Muse Code 1.3.0 does
not expose scheduler controls over MSP or a muse cron CLI command, so the
panel cannot present an authoritative native job list or direct cancel.
Composer.
Entersends andShift+Enterbreaks a line (or send withCtrl+Enterthrough a setting). The box grows with your draft up to ten rows, then scrolls inside.- While a turn runs,
Entersteers it and Stop cancels it; Stop also drops messages still queued, which read "Not sent". A picked text file on Muse Code queues a new turn so its file annotation survives History resume. - The
+button attaches images (PNG, JPEG, GIF, WebP), PDFs on the Model API backend, and UTF-8 text files up to 1 MiB from trusted, indexed workspace paths. Text files travel with their names as text on both backends. Files attached to Muse Code share its 10 MiB message limit; the composer counts their serialized content, including escaping, and refuses combinations that leave too little room for the prompt. Remove an attachment or shorten the message if that happens. Switching backends keeps visible chips; Muse Code checks them again before a send or steer and may require removal of an image attached under Model API. Model API text attachments share a separate 768 KiB allowance for their UTF-8 content and file-name wrappers. A large single file can be refused despite the 1 MiB per-file read cap; attach a shorter excerpt or remove another text attachment. A long conversation may still exceed the Model API context limit. Files outside that set become@path mentions; known binary types and private files are refused. A PDF picked under a.pngor.txtname follows its detected PDF header and 32 MB limit; Muse Code gives its PDF refusal. Ordinary unindexed text remains a path mention, and private filenames are refused before any PDF check. Images and PDFs also paste and drop. A dismissible banner gives the specific size, media, backend, text or private-file refusal; unknown file reasons keep generic unsupported-type guidance. Muse Code's MSP 1.3.0 cannot take a PDF part, so a PDF attachment there names the Model API backend instead. The Model API agent can read a workspace PDF or image throughread_file; other workspace files use its existing UTF-8 text reader. Excluded text files share only a path mention, and the Model API reader confines paths to the workspace. Picker reads stop at the file's size cap even if it grows during the read. A native picker still open after New Conversation or sign-out cannot add an old file or mention to the new draft. Model API text, image and PDF reads use the checked canonical workspace target if a link changes after confinement. Host file I/O also rejects an observed change to that checked path when a parent directory becomes a junction after the first check; paid image output reservations recheck before fill and cleanup. Combined image and PDF data URLs are capped at 48 million encoded characters per message; an excess pasted or dropped attachment is refused before the browser reads and encodes it. Replayed requests use the same cap and keep newer media, announcing when older media is omitted from the request. Paste/drop checks the first 1 KiB of image-labelled files: a PDF named.pngor.txtuses the 32 MB PDF limit and PDF media type, while a real image over 10 MiB is refused without encoding its full bytes. The check is discarded if the conversation changes before it finishes. Plain text clipboard content keeps its normal paste behavior; text-named files without clipboard text are probed and ignored when they are not PDFs. Private names are refused first. A PDF whose page tree cannot be counted without ambiguity reserves all 50 image slots, including when comments, escaped names or indirect/Countor/Typereferences obscure the real tree beside a visible decoy. The original attachments remain in local history. A batch of Model APIread_filetool calls uses the same media cap; a file over that batch cap gets a failed tool result before its bytes are retained. PDF and image tool rows use the installed panel language and number format; the model receives its English result. - A path with a space,
#or"is written in quotes,@"my notes/a b.md"#5-10, and the menu searches what you type after@". - The model pill reads
model effort(effort tiers Minimal to Max, each verified per model); the mode button opens the Modes menu; the microphone dictates. - The context indicator is a button: click it to compact now; its tooltip carries the pressure level Muse reports.
/: the palette and the slash commands. A / on an empty prompt stays
in the box and shows the palette above it; the / button opens the same
palette with a filter box of its own. Its groups:
- Context: attach, mention, clear, resume, new and remove worktree, and Continue a Claude Code or Codex session (CLI backend).
- Model: switch model, effort (Left and Right step it), thinking.
- Customize: permission mode, Focus view, Send with Ctrl+Enter, MCP servers, hooks, memory, settings, keybindings.
- Account & usage (with the paid features' toggles where the backend can use them), Skills (the session's own, plus Manage and Import on the CLI backend), Slash commands and Support.
Type a letter after the / and the palette gives way to a flat list of slash
commands narrowed as you type: /agents, /clear, /compact, /config,
/cost, /export, /goal, /hooks, /logout, /mcp, /memory,
/model, /permissions, /resume, /usage, /loop (Model API backend),
and the session's skills. Names that start with your letters come first. Up
and Down move, Enter runs a command (a skill, or /goal, is completed so
you can add what follows it), Tab completes the name and Esc closes the
list. With nothing matching, Enter sends the text as it is.
Transcript.
- Replies render as GitHub-flavoured markdown with highlighted code and
Copy, Insert at cursor and Apply on every block; a finished
reply carries Copy on hover. A relative link in a reply
(
src/parser.ts#L12) opens that workspace file at those lines. - Tool rows show the diff or the command and its output from the start; read rows open on click, and a chevron marks the rows that open. Previews show 12 lines or 2,000 characters, with Show more. A backgrounded call carries a "background" badge.
- The path of an edit or read row opens the file with the changed lines selected. Click a tool's output to open it in a read-only editor tab (a stored output in full, up to 16 MiB); Click to expand on an edit diff opens VS Code's diff editor (the file side is editable).
- Thinking rows stream their summary while the model thinks and end as "Thought for Ns" (a resumed conversation's read "Thought").
- A reply's ⋯ menu has Reply to this output: the next message carries that output to the agent as context. Highlight any text in the chat and right-click it for Copy, Ask about this or Comment on this; the passage, its author and your intent travel with the message. The composer shows a chip for either; × drops it.
- Approval cards carry the CLI's own choices (Allow once, Always allow in this workspace or Allow for this session, Reject, with optional feedback); multi-step shell lines are approved one step at a time. Question cards stack radio buttons for one answer and checkboxes for several, put multiple questions on tabs, always offer Other, and keep Submit greyed until every question has an answer; Cancel declines the prompt, and Explain instead answers in your own words (up to 500 characters) rather than choosing, so the agent reads it and decides again.
- The transcript follows new entries while you are at the end; scrolled up,
it holds still and New messages jumps to the newest. The agent's task
list pins above the composer, and the composer shows how much of the
context window is used. Focus view (
Ctrl+Alt+F) folds tool and reasoning rows behindShow N steps.
Edits and rewind. Muse applies in-workspace edits as it goes, so review comes after: the edit row shows the diff, its path opens the file at the change, and Click to expand opens the diff editor. To undo, use the rewind button on any sent message (on hover):
- Fork conversation from here.
- Rewind conversation to here starts a branch before that message and puts its prompt back in the composer. The original conversation stays in History. Images return when the backend still has their bytes; the panel warns if it cannot restore one. A Model API conversation cannot be rewound before its latest compaction. A rewind queued for a session the tab has since left is ignored. Messages steered into one turn use the last earlier turn as their branch point; if none exists, the conversation rewind choice is hidden. Wait for the selected turn to finish before rewinding its conversation. A just-sent Model API image can be restored before History is reopened. Conversation rewind is hidden for each PDF or named text file card because its bytes cannot be restored reliably on every backend and History path; an earlier text-only card in the same turn keeps its rewind choice. A request made outside the menu is checked against the served card and cut before the conversation changes.
- Rewind code to here reverts every edit made after that message, the conversation's and its subagents', in the reverse of the order they landed. A file the edit created goes to the trash, unless you have added to it since, in which case your lines stay.
- Fork conversation and rewind code.
Side chat. Use Side chat in the header to open a separate Plan-mode
conversation with the completed turns as reference. Its inherited goal is
cleared; the original tab keeps its session, goal and running turn. A delayed
side-chat request is ignored if the original tab has since changed sessions.
On the Model API backend, the side branch keeps Plan mode after reopen,
suppresses local hooks and refuses external MCP tools, including ones their
server labels read only. It also refuses scheduled prompt creation, cancellation
and paid runs before any job claim or Model API request. Muse Code applies its
own project and session rules in Plan mode;
review those rules before treating that branch as read only. Close the side
tab to return to the main one; its branch stays in History. It uses the
selected backend's normal model allowance or key billing; it does not route
Model API calls through a Muse subscription. In a side chat, Shift+Tab
moves keyboard focus normally because its permission mode is fixed. A side
panel's History shows only its own side branches; the same boundary applies
when the window reloads.
Each edit is undone only where its own lines (the changed lines and the few around them) are still exactly as the edit left them. If you added or removed lines above them since, they are found where they moved to, as long as they appear in exactly one place. An edit whose lines you changed, or that could match more than one place, is left alone and says why, rather than guessed at; your other changes to the file are kept. A file's BOM and line breaks survive both.
Unsaved editors. Muse reads and edits the files on disk. With
museSpark.autosave on (the default) every message saves your editors
first; with it off the panel names the files whose unsaved changes Muse will
not see. On the Model API backend the file tools also refuse a file an
editor holds unsaved changes to, keep a file's BOM, line breaks and final
line break, refuse files that are not UTF-8 text rather than rewrite them,
and replace an existing file with write_file only after reading it (as
Claude Code does). A linked path checks both its requested and canonical
editor locations for unsaved changes.
History. The clock icon lists the workspace's conversations by day with
search, resume (full transcript), archive and Show archived. Archive with
the row's × or, while the search box is empty, Delete on the highlighted
row, which also restores an archived one. Sessions idle for
archiveInactiveSessions days are hidden, not deleted. Click the header's
title to rename the conversation. A hidden panel shows a dot when Muse
finished or needs a decision.
Export. /export (or Muse Spark: Export Conversation) saves the
conversation as Markdown where you choose: messages, thinking, and tool calls
with their arguments and visible output. Your ! commands include an exit
code or termination signal when Muse Code reports one. On the CLI backend Export session
log… also saves Muse Code's own JSON record of the session (muse export), which includes everything, stored outputs too; it needs a folder
on this machine. An export asked for while a reply runs is refused until it
finishes, and a conversation too long for Muse Code to replay is pointed to
the session log.
Your own shell commands. Start a message with ! to run it as a shell
command in the workspace instead of sending it to the agent, as Muse Code's
! does: !git status. The prompt switches to the editor's font and says
Shell; the command runs at once, outside any turn (also while a reply
runs), and gets its own row: You ran with the command, its exit code
and run time, and what it printed, which opens whole in an editor tab. The
agent sees the command and its output with your next message. No approval
card asks first, since you typed it, whatever the permission mode; nothing
runs while the workspace is in Restricted Mode, and a command that could not
run comes back to the prompt with the reason. On Muse Code it runs through
the CLI's own shell and sandbox (a missing Windows sandbox offers the setup,
as the shell tool does); on the Model API backend it runs through the shell
tool's runner, for ten minutes at most, and its row has a Stop.
While a Model API command is still running, another surface sharing that
session shows its row and can stop it. A session loaded in another VS Code
window shows the saved row as interrupted, since that window cannot
control the original runner.
Background work. A shell command the agent is waiting on can go on in the
background while the agent carries on: Move to background on its row, or
Ctrl+B (also on a Mac) while the conversation in view runs one; VS Code's
own Ctrl+B (the sidebar) works as usual otherwise, including while a shell
permission card waits for your answer. A background command
keeps running after its turn ends, marked "background", with Stop on its
row; the header pill counts the ones still running, and the Agent map lists
every background task with its own Stop and a Stop all (also
Muse Spark: Stop Background Tasks). On Muse Code these are the CLI's own
task/background, task/stop and task/stopAll, and Muse Code tells the
agent what the command printed when it ends. On the Model API backend the
agent is answered at once that the command moved; it then runs without its
time limit until it ends or you stop it, and what it printed reaches the
agent with its next request (no model call is made for it on its own).
When the last surface leaves a conversation, its remaining background
commands are stopped; another open surface keeps them running. A resumed
conversation restores Ctrl+B for a shell command still in the foreground.
A second surface sharing a live Model API session also shows its running
foreground command and can move it with Ctrl+B.
If that shell is still awaiting permission, the second surface shows the
same card and leaves Ctrl+B to VS Code until approval resolves.
A fork has no running commands from its source; it carries the ending or
lost-output context into the agent's next request for any inherited task.
Subagents. When either backend spawns subagents they appear as rows and
an N agents pill in the header opens the Agent map (also /agents):
this conversation, its agents with role, objective, status, duration and
tokens, the background tasks, and each agent's own transcript.
- Muse Code hides its subagent tools unless
run.subagent_delegation_modeis"auto"in its settings file (~/.config/muse/settings.json, or under$XDG_CONFIG_HOME). The map says so and opens the file for you; the extension never edits it. - Muse Code gates
subagent_spawnbehind an approval: in Manual mode the card appears (Allow once / Allow for this session); Plan mode refuses it. - An agent's own replies and tool calls stay in its transcript in the map, and the map's details offer the controls Muse Code provides: Interrupt and Stop while it runs, a note to it, Resume, Close, and a follow-up task once its result is ready. A ready result can be marked read; a closed agent can be reopened on the Model API backend. Muse Code's Reopen and Mark result read controls wait for a live capture of their accepted MSP commands; its captured Interrupt, Stop, Resume and Close controls remain available.
- On the Model API backend, the agent can spawn up to eight child sessions at once; more wait in order, up to 64 per conversation. A child has its own conversation and the same workspace tools and approvals, but cannot spawn again or ask you a question. Children share the workspace and use your Model API key; their tokens count in the conversation's usage. Paid subagents are off by default. Enabling them accepts the published model rates; each new child task then asks again before it starts, including in Bypass mode. Plan refuses the task. One approval allows at most four actual response requests, including retries and tool rounds. A running note uses that same allowance; a follow-up or reopen needs a new approval. This is a request limit, not a dollar limit. Failed requests without a usage report appear as unknown cost in Account & usage. A resumed child whose queued notes survived a window restart shows those notes in its fresh approval before they run. Stopping a queued child drops its unsent notes; reopening it starts from its retained objective without those canceled notes. A second panel joining during a child's pending tool approval sees the same card. Child tokens spent on an active goal count against that goal's budget; a replacement goal does not inherit an earlier child's cost.
Workflows. Muse Code can run a multi-agent workflow: a short script, written by the model for the task or saved in Muse Code beforehand, that starts child agents, up to 1,000 over a run, each making its own model calls on your subscription. The Workflow row shows the inline script when the model wrote one and says whether the run was launched. It does not infer a source file for a resumed run; that input shape has not been captured from Muse Code. The run itself is a card below it that keeps changing after the reply ends, as the run goes on in the background:
- its captured generated label ("Written for this task"), or the entry ID or fallback text Muse Code sent for another run, plus its status, how many agents, their tokens, and what started it;
- each agent with its label, state (queued, running, completed, failed…), attempt, time and tokens;
- a status Muse Code adds later shown in its own words with a neutral mark;
- the result the run returned, or the failure it reported;
- The run and its agents are read-only in this version. Cancel, Skip and Retry will need a live capture of accepted Muse Code commands before the panel can offer them.
The token figure is the panel's sum of the latest usage reported for each agent row. It is not a billed total for a run with retries; use Muse Code's subscription usage for that. A reload of the same session keeps child labels and usage the panel saved earlier; without that saved state, Muse Code's final history item may omit those details.
The header's N agents pill counts workflow agents too, and the Agent
map lists the runs with the same read-only cards. The map also says how Muse Code
is set to start workflows, from run.workflow_trigger_mode in its settings
file (auto, its default: the model may start one for large work, and
starts one when you ask; explicit: only when you ask; off: no workflow
tool), with the file a click away; the extension never edits it. Pausing
and resuming a run are Muse Code's terminal UI's alone (/workflows), and a
workflow agent keeps no transcript of its own to open. The Model API
backend runs no workflows.
Account & usage (/usage, /cost) is a modal over the transcript:
- Account: auth method, plan, backend, Muse Code version and model.
- Usage (Muse Code): the subscription's current window and week. Muse Code reports them only after a reply. The modal reads the latest report from the signed-in CLI when opened; it does not use an account-agnostic snapshot after a host restart or sign-out. Countdowns update each minute while the modal is open. Once a reported reset has passed, that row waits for a fresh Muse Code report instead of showing an expired percentage or reset countdown. Each observation is dated "as of". The numbers are the CLI's account-level percentages and reset times: changing the selected model does not create a separate local quota or reset calculation, and an opaque plan ID is shown as "Muse Code subscription". Personal Muse Power/Maximum plan grants are separate from this CLI usage report.
- This conversation: token totals (on Muse Code, prompt tokens as it counts them once). On the Model API also the cached tokens, the cache-hit rate and a dollar estimate from Meta's published per-token prices (standard versus contributor tier, read 2026-09-26; the dev.meta.ai dashboard is the bill).
- What's contributing to your usage, over the last day or week, read from the Muse Code CLI's trace logs on this machine: the share of model attempts from Muse's reminder agents (which run after every reply), from subagents, and from sessions active for 8+ hours. Approximate, this machine only.
Prompt caching. The Model API backend sends a stable key for requests that share a model, instructions and tools, so repeated prefixes can be billed at the cached rate; the CLI caches on its own. The retention setting asks Meta for its shorter in-memory default, or up to 24 hours when you choose that machine-scoped setting. Either is a hint rather than a guaranteed lifetime. The modal shows the cache-hit rate instead of a "warm for N minutes" countdown.
Diagnostics. The agent can read the Problems panel through a
getDiagnostics tool. On the CLI backend the extension serves it on a
loopback MCP server, bound to 127.0.0.1 with a per-window token and
started when a session first needs it; nothing else is exposed. On the
Model API backend it runs inside the extension under the same name
(mcp__ide__getDiagnostics), as a read in every mode. It reports the workspace's files only (the
first folder), by relative path, each message cut at 1,000 characters, and
past 200 problems a count instead of the rest.
Accessibility. Every screen the panel shows is checked against WCAG 2.2 AA's automated rules in Light Modern, Dark Modern and both High Contrast themes on every change.
- Menus and lists work from the keyboard: the palette and History lists are
Tab stops, the effort row moves with Left and Right, History rows archive
with
Delete, andEsccloses whatever is open. - Screen readers hear when Muse finishes, fails or is stopped, when an approval or a question arrives, when a tool fails, and when dictation starts and stops.
- The operating system's "reduce motion" setting stops every animation.
- Text in right-to-left scripts reads right to left, and with an input
method
Entercommits the candidate instead of sending.
Tap the microphone to start and again to stop; hold it (or Ctrl+D /
Cmd+D in the composer, or Space on the focused button) to record while
held. The placeholder reads "Listening…", the mic pulses red, and each phrase
lands at the caret followed by a space. Recognition runs in a small helper
on the operating system's own engine, kept warm for five minutes after a
recording. Nothing is billed and no third-party engine is involved, unless
you turn on Muse Voice, the paid engine on a Model API
key.
Dictation is off in a remote window (SSH, WSL, containers, tunnels, Codespaces): the extension runs on the remote machine, which cannot hear your microphone.
| Platform | How |
|---|---|
| Windows | native/windows/dictate.ps1 under Windows PowerShell 5.1 on the .NET Framework's System.Speech, the desktop recogniser that ships with Windows (English always; other languages with Windows speech packs). Audio never leaves the machine. Accuracy is the classic engine's, below Windows 11's voice typing; Windows' Speech Recognition training improves it for your voice. |
| macOS | native/darwin/muse-dictate, a Swift helper on Apple's Speech framework, built by CI on a Mac and shipped in the Marketplace package. Dictation (System Settings > Keyboard) or Siri must be on. Apple picks on-device recognition when its model is installed, otherwise its servers under Apple's terms at no charge (--on-device refuses the servers). See the macOS notes below the table. |
| Linux | Not available for free: no distribution ships a speech recogniser and the extension adds none. The button is dimmed with that reason as its tooltip. With Muse Voice on, the system's arecord or parec records and Meta transcribes. |
On macOS, two things can stop the helper, and the panel's error says which:
- A permission. The first time you dictate, macOS asks for speech recognition and the microphone on behalf of the helper itself, muse-dictate, with its own usage descriptions, rather than for Visual Studio Code; the grants are managed under System Settings > Privacy & Security > Speech Recognition and > Microphone. The helper asks under its own name because Visual Studio Code, which starts it, declares no speech-recognition purpose (microsoft/vscode#307364), and macOS would refuse VS Code without asking; to do so it disclaims VS Code's responsibility with a private macOS call (the one Chromium, Qt and Electron use), and where that call is missing it asks as VS Code and the panel's error explains the refusal. The helper is ad-hoc signed, so macOS ties the grant to the build: after an update that changes the helper, macOS asks again.
- The helper itself. The helper is ad-hoc signed, not notarised; VS Code's installer does not quarantine it, so Gatekeeper does not stop it. If the error names no permission step, macOS refused to run the helper: its file carries the quarantine flag, which a copy through a browser download or an archive tool can add. This clears it:
xattr -d com.apple.quarantine ~/.vscode/extensions/randynorthrup.muse-spark-code-*/native/darwin/muse-dictateDiagnosing on Windows: the helper can replay a WAV file instead of the microphone, which separates a recogniser problem from a microphone one.
& "$env:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -ExecutionPolicy Bypass -File native\windows\dictate.ps1 -InputWav C:\path\to\speech.wavType start and press Enter; phrases print as JSON lines, then stopped.
Muse Voice's recorder takes the same -InputWav (a 16 kHz, 16-bit mono
file) and prints the audio as audio lines instead:
native\windows\capture.ps1 -InputWav ….
On macOS the helper takes --input-device <CoreAudio UID> to capture from
one specific device; a Mac without any input device reports "no audio input
device is available", and step markers on stderr name where a start failed.
Five settings gate what costs money on your Model API key beyond an ordinary chat turn. They are always billed to your Model API key, never to your Muse Code subscription, and all five are off until you turn them on. All five work on the Model API backend; images and Muse Voice also work on the Muse Code backend while a key is stored (web search is Muse Code's own there, on the subscription):
| Feature | Price (Meta, read 2026-09-24) | What it does |
|---|---|---|
| Web search | $2.50 per 1,000 searches | The model may search the web while it answers; the reply lists the pages it cites |
| Image generation | $0.01 per image | The model may create a PNG file in the workspace with muse-image-1.0, or edit workspace images into a new one, asking you each time |
| Muse Voice | $0.18 per hour of audio | The microphone uses Meta's Muse Voice Transcribe instead of your computer's own recogniser |
| Subagents | Selected model's published input, cached input and output token rates | Child tasks on the Model API backend; every task asks again and admits at most four response requests |
| Scheduled prompts | Selected model's published input, cached input and output token rates | A due /loop prompt runs only after you choose Run now and allow that run's model and rates |
Scheduled prompts use ordinary Model API tokens, rather than an extra per-run service fee. The off-by-default paid gate names both standard ($1.25/$0.15/$4.25) and contributor ($0.10/$0.002/$0.20) rates per million input/cached/output tokens. Each due run names only its selected model's exact tier before any model call; an unpriced model cannot be approved. Other paid tools you have enabled may add their own charges during that confirmed turn.
Turn one on from the palette (Account & usage group, where the backend
can use it) or with its setting (museSpark.modelApiWebSearch,
modelApiImageGeneration, modelApiVoice, modelApiSubagents,
modelApiScheduledPrompts). Either way a confirmation
names the price first; declining it turns the setting back off, and turning
a setting off means the next time asks again. The settings are
machine-scoped, so a repository cannot turn one on.
Every paid use then asks first, in a popup, in every permission mode, Bypass included. The popup names what is about to be billed and its price, and offers three answers:
- Allow once: this use only.
- Allow always in this workspace: this use, and every later use of the same feature in this workspace, without asking. Offered only in a trusted workspace with a folder open. It lapses in every workspace when you turn the feature off (or accept a new price), and Ask again every time in Account & usage takes it back.
- Deny (or closing the popup): nothing is billed.
What asks, and when:
- Web search: once per prompt, before its first request, because Meta runs the searches inside the response and the model decides whether to search at all. Deny sends that prompt without web search. A child task searches only if its parent's prompt was allowed to.
- Images: before every image, with its path, prompt, the images an edit
starts from, and the price. Plan refuses it (it writes a file), and a
path that is taken, outside the workspace, or not a
.png, or a source that is missing, outside the workspace, not a PNG, JPEG or WebP image, or over 10 MB, is refused before anything is asked or billed. Edit sources are read from their checked canonical workspace targets, even if a link changes after the check. An image written to a protected path (D24) asks even when images are allowed always. - Muse Voice: before each recording.
- Subagents: before every new child task, with its objective, model, published rates and four-request ceiling; Plan refuses it. Retries count; a running note spends the same grant.
- Scheduled prompts: before each run, with its prompt, model and rates.
While one is on, you can always tell, even when it no longer asks:
- The composer's badge names every paid feature that is on ("Paid: Web search, Images"), with the prices in its tooltip and the features allowed always in this workspace; it opens Account & usage.
- Every use is its own row marked paid: each search, with its query and results; each image, with its path; each child task; and each admitted scheduled run. The child estimate in Account & usage is part of the conversation's total, not an extra charge added to it.
- On the Muse Code backend, images come from the extension itself: its
idetool server, which every Muse Code session loads, offers Muse Code an image and an image-edit tool while image generation is on and a key is stored. Muse Code's own permission mode decides whether it may use the tool; then the same popup asks before the image is bought, billed to your key and not to the subscription. The key never leaves the extension, and the row is marked paid as on the Model API. - The microphone says so: ringed, and named "Record voice with Muse Voice (paid)" with the price in its tooltip.
- Account & usage keeps the tally and names each feature allowed always in this workspace: this window's searches, images, seconds of audio, child request attempts and scheduled runs, with estimated cost when usage was reported. An attempt with no usage report has unknown cost. Scheduled-run tokens are included in the session token estimate rather than added to the extra-features total. The dev.meta.ai dashboard is the bill.
Web search's count errs high: Meta does not say how it bills a search with several queries, so each query counts. Muse Voice counts the whole seconds sent, as Meta bills them.
![]() A search marked paid, the reply's sources, and the badge |
![]() What no longer asks in this workspace, and Ask again |
Muse Voice records the same way as free dictation (tap or hold), and the
transcript lands at the caret when you stop. The recording is made by a
helper that only records: native/windows/capture.ps1 on Windows (the
waveIn API that ships with Windows), the macOS helper's capture mode (which
asks for the microphone only), and on Linux the system's arecord or
parec, so Linux gets a microphone on this engine. Audio leaves the machine
only while it records, and only to Meta.
The panel, its notices, the Command Palette's commands and the settings follow VS Code's display language:
- Simplified and Traditional Chinese
- Japanese and Korean
- German, French, Spanish, Italian and Brazilian Portuguese
- Russian, Polish, Czech, Hungarian and Turkish
Any other display language gets English. Change it with Configure Display Language in the Command Palette and reload the window.

Account & usage in German, with its numbers written the German way
The translations are machine-made, by the same AI that wrote the code,
and checked by a gate rather than by native speakers. That gate checks that
every string is present, every value and code span is kept, and every count
uses the language's own plural forms. If a translation reads wrong,
open an issue
naming the language and the text; a correction is one line in
l10n/ui.<language>.json or package.nls.<language>.json.
What stays in English:
- Text sent to the model: the context notes, the compaction prompt and the tool errors. The model behaves the same in every language.
- What Muse and the tools write: replies, tool output, and Muse Code's own approval choices.
- The walkthrough's pages: VS Code translates the step titles, not the pages.
- Log lines no one sees in the panel, and the names of commands, files and settings.
| What | Limit |
|---|---|
| Images and PDFs | 20 attachments per message together; images 10 MiB each (PDFs: next row) |
| PDFs on the Model API backend | 32 MB each locally (Meta allows 50 MB per inline file); images and PDF page images together: 50 per message. Meta reads text from the first 100 pages and page images from the first 50. |
| Model API encoded media | 48 million data URL characters total per new message and replay request; older replayed media is named but omitted when over the cap. |
| Picked UTF-8 text attachments | 1 MiB per-file read cap from trusted and indexed workspace paths; Model API also caps combined text and file-name wrappers at 768 KiB to leave context room. |
| A message to Muse Code | 10 MiB. Attachment admission reserves 2 MiB for the prompt, context and frame; serialized text and base64 images count toward the rest. The exact outbound frame is checked at send. |
| Model API: tool rounds | 50 per turn |
| Model API: shell commands | 2 minutes by default, 10 at most |
| Model API: retries | Up to 5 attempts on 429, 500, 502 and 503, and when a reply stream ends because the server shut down or was overloaded, honouring Retry-After, shown in the transcript; Stop cuts the wait short |
| Model API: a silent reply stream | Ended after 5 minutes with nothing from the server; send again to retry |
| Model API: file tools | Text and images up to 10 MiB, PDFs up to 32 MB; the search tool skips files over 1 MiB |
| Opened tool outputs | 16 MiB each; the latest 20, and 32 million characters together |
| Command | Default keybinding | What it does |
|---|---|---|
| Muse Spark: Open in Sidebar | — | Focus the chat view in the activity bar |
| Muse Spark: New Conversation | Ctrl+N (Cmd+N) when enableNewConversationShortcut is on, Muse focused |
Clear the active panel to a new conversation, or open one where preferredLocation says |
| Muse Spark: Sign Out | — | Forget the stored Model API key and sign the CLI out when it is signed in (its account/logout, else muse logout) |
| Muse Spark: Open in Terminal | — | Run the Muse Code CLI's own interactive interface in a VS Code terminal at the workspace root |
| Muse Spark: Create AGENTS.md | — | Write the rules file with muse init (or the same template without the CLI) and open it; an existing file is opened |
| Muse Spark: Open Walkthrough | — | Open the four-step Get Started walkthrough |
| Muse Spark: Open in New Tab | Ctrl+Shift+Alt+Esc on Windows, Cmd+Shift+Esc on macOS, Ctrl+Shift+Esc on Linux |
Open an independent conversation as an editor tab (also the + in the view title); the panel header's own button starts a new conversation in place |
| Muse Spark: Toggle Focus | Ctrl+Alt+Esc on Windows, Cmd+Esc on macOS, Ctrl+Esc on Linux |
Move keyboard focus between the editor and the composer |
| Muse Spark: Insert @-Mention for Selection | Alt+K, editor focused |
Insert @path#start-end for the active editor selection into the composer |
| Muse Spark: Toggle Focus View | Ctrl+Alt+F, Muse focused |
Flip the museSpark.focusView setting (hides tool calls and reasoning) |
| Muse Spark: Toggle Thinking | Ctrl+Alt+T (macOS Option+T, Linux Ctrl+Alt+O), composer only |
Turn reasoning on or off for this conversation. Claude Code uses Alt+T; on Windows that opens the Terminal menu, on GNOME Ctrl+Alt+T opens a terminal |
| Muse Spark: Set Up Shell Sandbox | — | Windows: run Muse Code's one-time muse sandbox windows setup through a UAC prompt and report the result; elsewhere reports that no setup is needed |
| Muse Spark: Show Logs | — | Open the "Muse Spark" log channel (keys redacted) |
| Muse Spark: Diagnostics | — | Write the versions, the backend and CLI facts, credential facts, never a value, the dictation state, the network posture and muse config status to the log and open it: what a bug report needs |
| Muse Spark: Manage Skills | — | Turn Muse Code's skills on or off (muse skills enable/disable), then offer to restart it so the change takes effect |
| Muse Spark: Import Skills from Claude Code or Codex | — | Preview what muse skills import would copy, import it once you confirm, report what was imported, skipped or failed |
| Muse Spark: Export Conversation | — | Save the conversation in front of you as Markdown where you choose, and open it |
| Muse Spark: MCP Servers | — | Show the MCP servers Muse Code will load (on the Model API backend, how each is running), sign in to or out of a remote one, open the settings file |
| Muse Spark: Hooks | — | Show where Muse Code's hooks come from (project, yours, managed) and open each file; on the Model API backend also whether modelApiHooks is on, with a link to it |
| Muse Spark: Memory | — | List Muse Code's memory notes for this workspace, open one to edit, create one, or delete one to the trash, keeping each MEMORY.md index in step |
| Muse Spark: New Worktree… | — | Ask for a new branch and its base, create it in its own folder beside the repository, then offer to open it in a new window |
| Muse Spark: Remove Worktree… | — | Delete another worktree's folder (its branch stays), asking again before discarding uncommitted changes |
| Muse Spark: Move Running Command to Background | Ctrl+B (also on macOS), while the conversation in view runs a shell command |
Let the running shell commands go on in the background while the agent carries on; VS Code keeps Ctrl+B otherwise |
| Muse Spark: Stop Background Tasks | — | Stop every background task of the conversation in view |
| (composer) Record voice | Ctrl+D (Cmd+D), composer only |
Tap to start or stop voice dictation, hold to record while held |
| (composer) Run a shell command | Start the message with ! |
Run it in the workspace as you, outside any turn; the agent sees it with your next message |
Windows keeps Ctrl+Esc for Start and Ctrl+Shift+Esc for Task Manager,
which is why its two shortcuts add Alt. Nine commands appear in the
Command Palette only where they can act: Insert @-Mention with an editor
open, Toggle Thinking, Export Conversation and Stop Background Tasks with a
Muse panel in view, Move Running Command to Background while one runs, Set
Up Shell Sandbox on Windows (or in a remote window), Create AGENTS.md and
the two worktree commands with a folder open.
All settings live under museSpark.*; changes apply to open panels
immediately. The settings that choose what runs and what is billed
(initialPermissionMode, backend, shellSandbox, sandboxNetwork,
allowDangerouslySkipPermissions, museBinaryPath, environmentVariables,
modelApiHooks, modelApiPromptCacheRetention and the five paid features,
modelApiWebSearch, modelApiImageGeneration, modelApiVoice,
modelApiSubagents and modelApiScheduledPrompts) are machine-scoped: they
take effect from your user settings only, never from a repository's
.vscode/settings.json. In a remote window (SSH, WSL, a dev
container) machine settings live on the remote side, where a dev container
definition can set them; there the extension never starts a conversation in
Bypass permissions and asks you once before entering it. Turning
allowDangerouslySkipPermissions off moves every open conversation out of
Bypass at once.
| Setting | Default | Purpose |
|---|---|---|
preferredLocation |
panel |
Where new conversations open: sidebar or panel (editor tab) |
initialPermissionMode |
manual |
manual, acceptEdits, plan, auto or bypassPermissions for new conversations; bypassPermissions applies only while allowDangerouslySkipPermissions is on, otherwise the conversation starts in manual |
autosave |
true |
Save all dirty editors before every turn |
attachOpenFile |
true |
Show the open-file chip and send the active file / selection with each message |
useCtrlEnterToSend |
false |
Send with Ctrl/Cmd+Enter instead of Enter |
enableNewConversationShortcut |
false |
Ctrl+N / Cmd+N starts a new conversation while a Muse panel is focused |
hideOnboarding |
false |
Hide the getting-started tips |
focusView |
false |
Show only prompts and responses |
respectGitIgnore |
true |
Exclude .gitignore patterns from file searches and @-mentions |
confidentialWorkspace |
false |
Block contributor-tier models (Meta may train on their traffic) in this workspace |
allowDangerouslySkipPermissions |
false |
List Bypass permissions in the Modes menu and the Shift+Tab cycle (sandboxes only) |
archiveInactiveSessions |
14 |
Hide sessions idle for this many days from the History dialog (1, 2, 7, 14, or 0 for never); they stay on disk and Show archived lists them |
cleanupPeriodDays |
30 |
Delete Model API conversations idle for more than this many days when a window lists them (0 keeps them); Muse Code's own sessions are the CLI's to keep |
backend |
auto |
auto: Muse Code when the CLI is signed in, else the Model API when a key is stored; museCode / modelApi force one. The pasted key never reaches the CLI. Changing it restarts the host |
shellSandbox |
auto |
auto: Muse Code's OS sandbox, except for Windows workspaces under your profile where it cannot run commands; muse: always the sandbox; off: commands run directly as you, gated by approvals (Claude Code style). Without the sandbox Muse Code's file tools may also write outside the workspace. Changing it restarts the host |
sandboxNetwork |
default |
The network Muse Code's shell sandbox gives commands: proxy-only asks before each new destination, restricted allows none, enabled allows all; default passes nothing, leaving Muse Code's own default (proxy-only) or your administrator's managed configuration. Applies while the sandbox is on. Changing it restarts the host |
museBinaryPath |
"" |
Absolute path to the Muse Code executable (a relative one is refused); empty discovers it on PATH or the install dir. Changing it restarts the host |
modelApiWebSearch |
false |
Paid: web search on the Model API backend, $2.50 per 1,000 searches; asks you to confirm the price when turned on, then asks before each prompt that may search |
modelApiImageGeneration |
false |
Paid: the model creates PNG files in the workspace or edits workspace images into new ones, $0.01 per image, on the Model API backend and on Muse Code while a key is stored (billed to the key); every image asks first, in every mode, unless allowed always in this workspace |
modelApiVoice |
false |
Paid: Muse Voice as the microphone's engine, $0.18 per hour of audio, on the Model API backend and on Muse Code while a key is stored; each recording asks first |
modelApiPromptCacheRetention |
in_memory |
How long Meta is asked to keep the cached start of Model API requests: in_memory by default, or up to 24h when you choose it. Both have the same cached-input price; longer retention may improve cache hits after a pause. Meta may evict sooner. Machine-scoped, so a repository cannot extend it |
modelApiSubagents |
false |
Paid: Model API child tasks, with a model-rate confirmation and a fresh four-request popup for every task |
modelApiScheduledPrompts |
false |
Paid: a due prompt can run only after this machine-scoped gate and a separate confirmation of that occurrence's Model API token rates; never unattended |
modelApiHooks |
false |
Run Muse Code's hook commands on the Model API backend in a trusted workspace: your administrator's, yours and the project's. They run as you, outside the agent's sandbox, without the Model API key; review them with Muse Spark: Hooks first. Machine-scoped |
environmentVariables |
[] |
{ name, value } pairs for the Muse Code process and the terminals that run the CLI (Open in Terminal, MCP sign-in, muse logout); an XDG_CONFIG_HOME here is where the extension looks for the CLI's sign-in and settings too. Never put API keys here; use Sign in. Changing it restarts the host |
The Model API backend's shell tool applies terminal.integrated.env.* the
way VS Code's terminal does. A restart of Muse Code, for a setting, trust
granted, a sign-in or a crash, keeps the conversation: the running turn is
stopped and the next message resumes the same session.
- The extension's own requests (the Model API, the paid features, Muse
Voice's socket) go through VS Code's network support, as every
extension's
fetchand WebSocket do from VS Code 1.125:http.proxy, or the system's proxy settings or PAC file; proxy authentication as VS Code handles it (Basic and Kerberos);http.noProxy; and the operating system's certificate store whilehttp.systemCertificatesis on.http.proxySupport,http.fetchAdditionalSupportandhttp.webSocketAdditionalSupportmust stay on (their defaults) for that. A network that inspects HTTPS needs its root in the system store. Naming the root's file inNODE_EXTRA_CA_CERTSbefore VS Code starts works only withhttp.systemCertificatesoff: in the M56 drill the variable did not help while that setting was on (its default). - Muse Code reads proxy variables from its environment (
HTTPS_PROXY,HTTP_PROXY,ALL_PROXY,NO_PROXY). The extension hands it VS Code'shttp.proxy(andhttp.noProxy) when neither its environment norenvironmentVariablessets one, in either case; a proxy VS Code finds in the system settings or a PAC file does not reach it, so sethttp.proxyorHTTPS_PROXYinenvironmentVariables; keep proxy credentials out of shared workspace settings. Ifhttp.proxyorhttp.noProxyhas the wrong type, the extension ignores that value for Muse Code instead of passing it into the CLI's environment; correct the VS Code setting to restore it. Loopback bypasses an environment proxy, so Muse Code reaches the extension'sidetools. Muse Code also has its ownendpoint_transport.proxysetting, which this extension does not manage. Muse Code 1.3.0 trusts the operating system's certificate store;SSL_CERT_FILEorSSL_CERT_DIRreplace that store for it entirely, so a file named there must hold every root it needs. - Muse Spark: Diagnostics reports which of these are set (never a
proxy's address) and known-safe source and generation fields from
Muse Code's managed configuration (
muse config status). Unrecognized lines and failed-command output stay out of the public-issue report.
- VS Code 1.125.0 or newer, on Windows, macOS or Linux.
- The Muse Code CLI signed in with a Meta account (subscription), or a Meta Model API key (pay as you go).
gitonPATHfor.gitignore-aware@mentions, worktrees and the Model API prompt's git facts (optional; VS Code's file search is used without it). The extension runs git only in a trusted workspace and only from an absolutePATHentry, never a copy inside the workspace.- Voice dictation: Windows, or macOS with Dictation or Siri enabled, in a local window.
- A trusted workspace for rules, skills, memory, MCP servers, hooks and
shell commands; in
Restricted Mode the panel chats and edits under approval, nothing more.
The first workspace folder is the root: the open-file chip,
@mentions, drops, the Problems panel the agent reads and relative file links all belong to it (a folder added inside it counts as part of it); a file in another folder is mentioned by its absolute path. Virtual workspaces are not supported.
- Your prompts, attachments, mentioned files and tool output go to Meta
only when you press Send. The exceptions are ones you set up: on the
Model API backend an MCP server you configured receives its tool calls'
arguments, and with
museSpark.modelApiHookson your hook commands receive your prompt and bounded previews of tool and model calls. By default each message also carries the open file's path and any selected text (attachOpenFile); on the CLI backend each turn carries a short hidden note asking the model to offer choices through the question card. The extension has no telemetry and no hosted server of its own. Details: PRIVACY.md. - A pasted Model API key lives only in VS Code's SecretStorage, is sent only
to
api.meta.ai, is never passed to any child process, and never reaches settings, logs or the CLI. - Contributor-tier models (Meta may train on their traffic) are opt-in with
one confirmation per conversation, and refused outright with
museSpark.confidentialWorkspace. Resuming a contributor-tier conversation asks again, or in a confidential workspace moves it to a standard model. - Voice audio stays on the machine on Windows; on macOS Apple recognises on the device or on its servers under Apple's terms. With Muse Voice on (paid, off by default), the recording goes to Meta's Muse Voice Transcribe while you record, and nowhere else.
- The paid features (web search, image generation, Muse Voice, Model API subagents and scheduled prompts) are off until you turn one on and accept its price; a repository's settings cannot turn one on.
- Model API conversations are stored, per workspace, in VS Code's storage
directory for the extension (not in the repository); ones idle longer than
museSpark.cleanupPeriodDays(30 days by default) are deleted, and removing that directory deletes them all. The History dialog archives, it does not delete. - The log records what happened (sessions, turns and their times, approvals, failures) and never your prompts, files, dictated words or the model's output; keys are redacted.
- The usage insights read the Muse Code CLI's trace logs on this machine and send nothing anywhere.
- On the Model API backend Meta caches the start of each request to answer
the next one faster and cheaper; the extension asks for the shorter
in_memoryretention by default. Only your machine-scopedmuseSpark.modelApiPromptCacheRetentionsetting can request up to 24 hours; a repository cannot extend your choice. The cache key is a digest of the model, instructions and tools it starts with, not a session or user id. - Behind a corporate network the extension's requests use VS Code's proxy and certificate settings, and Muse Code gets the proxy and certificate variables described under Proxies and certificates.
- Workspace rules, skill files and the memory snapshot are read only in a
trusted workspace; on the Model API backend their text is part of what
goes to Meta with each request, on the CLI backend Muse Code sends them
under its own terms. The memory snapshot is each scope's
MEMORY.mdand its notes' names, your personal scopes included; a note's text goes only when the model reads it. - The Model API backend's file tools resolve every path through the file
system before touching it: a path that leaves the workspace, directly or
through a link, is refused, and Windows names that would be reinterpreted
(alternate data streams, device names, trailing dots) are refused too.
Text reads and writes use the checked canonical target if a workspace
link changes between the check and the operation. Paid image output is
reserved at that same checked target before the API request.
Its shell tool starts PowerShell or bash by absolute path with the
environment VS Code's own terminal would give (the editor's internal
variables removed). Stop and a timeout end everything a command started:
its process group on macOS and Linux; on Windows the job object each
command runs in, through a small helper the extension compiles once into
its own storage with PowerShell's
Add-Type(where policy forbids that, the log says so and a sweep of the process table stands in). - The webview runs under a strict CSP (
default-src 'none', per-load script nonce, no remote origins, no inline styles); every message between host and webview is validated with a zod schema.
- What happened, in order — Muse Spark: Show Logs opens the log.
- What it records: every failure the panel or a popup showed, and anything that failed unseen, including an error inside the panel itself.
- With ids and times: each session as it started, resumed or forked; each turn with its result, its duration and when its first output came; approvals; sign-in changes; and why the backend restarted.
- Kept out: your prompts, files, dictated words and the model's output. Keys are redacted.
- More detail: set the channel's level to Trace (the gear in the Output view) to see how long each Muse Code command and Model API request took.
- A Model API request fails with "The server's certificate is not
trusted" — the network inspects HTTPS and re-signs it with its own
root. Install that root in the operating system's certificate store and
keep
http.systemCertificateson, or turnhttp.systemCertificatesoff and name the root's file inNODE_EXTRA_CA_CERTSbefore starting VS Code; the variable does not help while that setting is on. Muse Code reads the system store too. - "The proxy asked for credentials" or "The proxy refused the
connection (HTTP 403)" — the proxy wants a sign-in VS Code did not give
it, or does not allow
api.meta.ai. Checkhttp.proxyandhttp.proxyAuthorization, or ask for the host to be allowed. - Muse Code cannot reach Meta behind a proxy the browser uses — the
proxy comes from the system settings or a PAC file, which only VS Code
reads. Set
http.proxy, orHTTPS_PROXYinmuseSpark.environmentVariables, and the next message restarts Muse Code with it. Muse Spark: Diagnostics says where Muse Code's proxy comes from. - A permission mode is refused with "Muse Code's configuration … does not
allow this permission mode" — its default permission profile or a
policy your administrator manages caps the modes; choose a stricter one.
Muse Spark: Diagnostics prints
muse config status. - A Model API reply ends with "sent nothing for 300 s" — the stream stalled, so the turn was ended rather than left running until Stop. Send the message again to retry.
- The agent says a file is too large (Model API backend) — the file tools read and edit text and images up to 10 MiB and read PDFs up to 32 MB; the search tool skips files over 1 MiB. The agent can read part of a larger file with a shell command.
- Sign-out does not finish, or the panel stays gated — sign-out asks
Muse Code to sign itself out (
account/logout). Only when Muse Code still reads signed in afterwards does it openmuse logoutin a terminal, withmuseSpark.environmentVariables, so it signs out the same config home. WithMETA_API_KEYset, Muse Code cannot confirm the logout itself; the extension then reads the sign-in again and opens no terminal once it shows none.- Waiting for the terminal: the panel stays gated, with Check
again, until
muse logouthas run. That command leaves~/.config/muse/auth.jsonbehind with no sign-in in it, and the extension reads that as signed out. Choose Check again once the terminal is done. If the terminal could not open, runmuse logoutyourself. - An inherited
META_API_KEY: it stays outside the extension. Remove it from your environment or VS Code's configured environment variables, then choose Check again. Browser approval cannot override that key's billing priority. - Sign-out protection could not be saved: finish
muse logoutand removeMETA_API_KEYbefore reopening VS Code. - The old CLI sign-in remains: a fresh browser approval can replace it. The panel uses that sign-in only after Muse Code confirms it.
- The stored Model API key cannot be deleted: sign-out stops this window's backend and keeps it gated until the key can be cleared.
- Waiting for the terminal: the panel stays gated, with Check
again, until
- The panel says Muse Code cannot start because its sign-in file is in
the macOS format — the
auth.jsonit names came from a Mac: a version-2 file, or one whose sign-in lives in the Keychain. Muse Code 1.4.0 on Windows and on Linux exits at startup with such a file, even an empty one. Move or rename the file, then sign in again. WithMETA_API_KEYset, Muse Code starts anyway and uses the key. - The panel shows signed in on macOS, but the first message asks you to
sign in — on a Mac the token is in the login Keychain, and the
extension asks Muse Code about it only when you act: a click in the
panel (sign-in, sign-out, Check again), or the Sign Out or
Diagnostics command. That goes for any
auth.jsonon a Mac but the empty one a sign-out leaves, since what Muse Code 1.4.0 does there with another file has not been seen. A Keychain prompt never appears just because VS Code opened. Choose Check again to have Muse Code asked afresh now. Muse Spark: Diagnostics says whether the Keychain item exists, looked up without reading the secret; it also asks Muse Code for its sign-in, and Muse Code may read the Keychain to answer, which can show the Keychain's prompt. - Browser sign-in fails with "keychain write failed (internal error
-2147483648)" on Windows or Linux — Muse Code 1.4.0-R4161.1 could not
save a sign-in there
(#38,
#53). R4302.1
fixed it, and Muse Code's launcher updates itself; 1.4.0-R4302.1 or later
needs nothing more (Muse Spark: Diagnostics shows the version). Only
if you are stuck on R4161.1: add
TBH_CREDENTIAL_BACKENDwith the valuefiletomuseSpark.environmentVariablesand to the terminal you sign in from. That undocumented switch, which Meta's own SDK tests use, keeps the sign-in inauth.json. Remove it after updating, and never set it on macOS, where it hides a Keychain sign-in. - Every shell command fails with
sandbox enforcement unavailable— Muse Code runs commands inside an OS sandbox that needs a one-time administrator setup on Windows. The panel offers it in a notification ("Set up now" relaunchesmuse sandbox windows setupthrough the UAC prompt); the same flow is Muse Spark: Set Up Shell Sandbox. Start a new conversation afterwards. Linux and macOS need no setup. - Shell commands run in
C:\Windows\System32\WindowsPowerShell\v1.0instead of the project — Muse Code's Windows sandbox (1.3.0 and 1.4.0; on 1.3.0 the first command also takes about half a minute) cannot enter folders underC:\Users\<you>(meta-models/muse-code-sdk#26). WithmuseSpark.shellSandboxatautothe extension starts Muse Code without the sandbox for such workspaces: commands run directly as you, in the project, still gated by the approval cards, and the panel says so once per conversation.musekeeps the sandbox regardless;offnever sandboxes. - No Rename, conversation rewind or Side chat with Muse Code on Windows —
Muse Code refuses
session/renameandsession/forkon Windows (1.3.0 and 1.4.0; #30, #31), so the panel does not offer fork-based actions there, whatever the version, until a release is verified to fix them; Rewind code to here still works, and the Model API backend offers all of them. - A warning that "Muse Code reported an error for the decision (the tool may have run anyway): … approval ledger durability fence …" — Muse Code on Windows (seen on 1.3.0) sometimes fails its own ledger write after applying your decision (#29). The tool row shows what happened; nothing needs redoing.
- Model API charges while using the CLI — the extension never hands your
pasted key to the CLI (the "muse serve credentials" line in the Muse Spark
log says which credential it started with). If the CLI itself holds a
pay-as-you-go key (
muse auth set) orMETA_API_KEYis exported in your environment, the CLI uses it, exactly as Meta documents. - The Agent map says delegation is off — Muse Code hides its subagent
tools until
run.subagent_delegation_modeis"auto"in its own settings file; the map's button opens that file. The extension never edits it. - Muse never starts a workflow — Muse Code's
run.workflow_trigger_modemay beoff(no workflow tool) orexplicit(only when you ask); the Agent map says which and opens the settings file. - A workflow has no Cancel, Skip or Retry button — this increment follows its progress read-only. Owner controls wait for a captured accepted-command and outcome shape from Muse Code.
- The microphone says "Voice dictation failed: No microphone is available" — Windows sees no recording device from this session (Remote Desktop hides the host's devices unless the client redirects a microphone). On macOS, "Siri and Dictation are disabled" means Dictation must be switched on in System Settings > Keyboard.
git clone https://github.com/RandyNorthrup/muse-spark-code.git
cd muse-spark-code
npm ci # also installs the pre-commit hook (lint-staged + gitleaks)Press F5 to launch the Extension Development Host with a fresh build. CONTRIBUTING.md has the rules for a pull request; SECURITY.md the way to report a vulnerability.
Prerequisites.
- Node 22 or newer (
.npmrcenforcesengine-strict). - gitleaks on
PATHfor the hook andnpm run security:secrets. - semgrep for
npm run security:sast, at CI's version:pip install -r .github/semgrep/requirements.txt. - Google Chrome (or
CHROME_PATH) fortest:a11y,harness:shotsandimages. - On Windows, PSScriptAnalyzer 1.25.0 for
npm run lint(Install-Module PSScriptAnalyzer -RequiredVersion 1.25.0 -Scope CurrentUser).
Stack. TypeScript 6.0.3 (pinned: typescript-eslint does not yet
support TS 7); the extension host bundled with esbuild to CommonJS, with the
Model API backend as a second bundle (dist/modelApi.js) that loads when
that backend first starts; the webview is React 19 bundled to one IIFE with
its stylesheet; zod/mini validates every host ⇄ webview message; the voice
helpers are Windows PowerShell and Swift with no dependencies.
| Command | What it does |
|---|---|
npm run build:dev |
Dev bundles for the extension, the Model API backend, the search worker, the webview and the integration tests, with source maps |
npm run watch |
Rebuild the extension, the Model API backend, the search worker and the webview on change |
npm run harness:shots |
Screenshots of the webview in headless Chrome behind a fake host (test/harness/), every scenario or the names you pass; needs build:dev. The README's screenshots are these renders, copied from harness-shots/ into media/readme/: tools (as turn.png), agents, slash-palette (as palette.png), slash-commands, approval, question, quote-menu (as quote.png), rewind, modes, history, usage, dictation (as voice.png), paid and paid-always, and the Languages section's is usage --lang=de (as languages.png); the walkthrough's are empty, tools, slash-palette and signin (as open.png, welcome.png, chat.png and sign-in.png in resources/walkthrough/); --lang=<id> renders them in a table from l10n/ (--lang=pseudo in the pseudo-locale) |
npm run harness:pseudo |
Write the pseudo-locale (test/harness/l10n/ui.pseudo.json): every string accented, bracketed and lengthened by about a third, with its slots kept, so English left outside the table and text that overflows stand out in harness:shots --lang=pseudo |
npm run test:a11y |
The accessibility gate: axe-core checks every harness scenario in VS Code's four default themes against WCAG 2.2 AA and fails on any violation, on anything axe leaves undecided, and on a page without a result or whose scenario threw; needs a build. node scripts/capture-themes.mjs refreshes the theme colours from a real VS Code; --lang=<id> checks the scenarios in a table from l10n/ |
npm run images |
Render the Marketplace icon, the README banner and the social preview from their SVGs (headless Chrome) |
npm run build |
Minified production bundles, then enforces the size budgets in scripts/check-bundle-size.mjs, fails if the Model API backend's files are in the activation bundle (scripts/check-bundle-split.mjs) or a host bundle reads navigator, and checks THIRD_PARTY_NOTICES.txt against the bundled packages |
npm run notices |
Regenerates THIRD_PARTY_NOTICES.txt from the production bundles |
npm run format / npm run format:check |
Prettier write / check |
npm run lint |
eslint --max-warnings=0 (type-aware), stylelint --max-warnings=0, and PSScriptAnalyzer 1.25.0 over native/windows (Windows only; a reported skip elsewhere) |
npm run typecheck |
tsc --noEmit for the host, webview, unit-test, e2e-test and integration-test projects |
npm run deadcode |
knip: unused files, exports, dependencies (no --strict; see knip.jsonc) |
npm run cycles |
dpdm circular-import check from the extension's, the Model API backend's and the webview's entry points |
npm run duplication |
jscpd copy-paste detection (threshold 0) |
npm run test:unit |
vitest with coverage thresholds (90 % statements/lines/functions, 85 % branches); includes test/e2e/, where a fake Muse Code CLI is spawned as a real child process (a compiled stub on Windows) and driven through the real backend manager |
npm run test:e2e:live |
One real turn on the installed Muse Code CLI, opt-in with MUSE_LIVE_E2E=1; bills the signed-in subscription (25 to 45 model attempts measured for a reply-only turn: one for the answer, the rest for Muse Code's bundled reminder agents, which loop a varying number of times; budget 60, counted from the CLI's trace log); never in CI |
npm run test:e2e:live:modelapi |
The Model API sweep: the production backend against Meta's real API in empty temporary workspaces, one case per feature (-- -t case07 runs one); opt-in with MUSE_LIVE_MODEL_API=1 and the key in MUSE_LIVE_MODEL_API_KEY, contributor tier only; bills the key (about $0.03 a full run, $0.02 of it two images; it stops sending past $0.50); never in CI |
npm run test:integration |
Builds, downloads VS Code stable and the engines.vscode floor into .vscode-test/, runs test/integration/** in each; after npm run build:dev, npm run test:integration:run -- --label stable (or minimum) runs one |
npm run test |
Unit then integration |
npm run security:audit |
scripts/audit.mjs: fails on a high or critical advisory without a dated, reviewed entry in .github/audit-exceptions.json |
npm run security:sast |
semgrep scan --config auto --error through scripts/sast.mjs, which also finds a semgrep that pip put in Python's user Scripts folder when that folder is not on the shell's PATH |
npm run security:secrets |
gitleaks git over the repository history |
npm run check:l10n |
The localization gate: every table in l10n/ has every key of the English one (src/shared/l10n/en.ts) with the same {slots}, code spans and bold markers, exactly the plural forms its language uses, and nothing left in English but the names l10n/untranslated.json allows; every string package.json shows is a %key% of package.nls.json; and nothing reads UI_TEXT while its module loads |
npm run quality:gates |
format:check, lint, typecheck, check:l10n, deadcode, cycles, duplication, test:unit, build, security:audit: what CI runs on all three platforms |
npm run quality |
quality:gates, then test:a11y, security:secrets and security:sast; exits non-zero on any finding |
npm run quality:ci |
quality:gates, test:a11y, then test:integration (no secrets or SAST); CI itself runs these as separate steps, see Releases |
npm run package |
vsce package --no-dependencies (after vscode:prepublish runs npm run build) → .vsix; it carries the macOS helper only if bash native/darwin/build.sh built it first, on a Mac |
npm run clean |
Remove dist/ and coverage/ |
Tests. Unit tests (test/unit/**) run under vitest with vscode aliased
to test/unit/mocks/vscode.ts and webview components under jsdom; the fakes
in test/unit/helpers/ implement the full VS Code interfaces. The e2e tests
(test/e2e/**) drive the real backend manager against a fake Muse Code CLI
that answers the Muse Session Protocol, including approvals, questions and
subagents. Integration tests (test/integration/**) run under mocha inside a
real VS Code launched by @vscode/test-cli (on Linux under xvfb-run -a),
against test/fixtures/workspace/.
Quality gates. Every gate fails the build rather than printing, and each
was seen to fail on a deliberate break before being trusted; the records are
in docs/certification/, one file per milestone.
Accessibility is a gate too: every screen the harness shows passes axe-core's
WCAG 2.2 AA rules in Light Modern, Dark Modern and both High Contrast themes
(PLAN.md D32); CI runs it on Linux and Windows. So is localization
(PLAN.md D33): text the user reads goes in the English table
src/shared/l10n/en.ts, read as UI_TEXT.key when the code runs. A
sentence around a value is a {slot} template filled with fill, and a
count is forms({ one, other }) read with plural. Numbers and times go
through the Intl helpers beside them. Text for the model is MODEL_TEXT
and stays English. Escape hatches
(eslint-disable, @ts-expect-error, casts) need an inline reason and a row
in PLAN.md §8. Bundle budgets: 600 KiB for the extension, 400 KiB for the
Model API backend's own bundle, 50 KiB for the search worker, 900 KiB for
the webview.
Environment variables. Credentials live in SecretStorage, never in
files. .env.example documents META_API_KEY, which the Muse Code CLI
inherits untouched if you export it yourself (and prefers over its sign-in,
as Meta documents); the extension never sets it. The tooling also reads
MUSE_LIVE_E2E, CHROME_PATH and VSCODE_TEST_VERSION, as described above.
Project structure.
src/extension.ts activation: the view, the panel, the commands, the output and file openers
src/host/ VS Code-facing code: views and webview wiring, conversation, backend managers, the Model API bundle's entry and the search worker, commands, auth, settings, mentions, editor tracking, usage trace logs, voice, the diagnostics MCP server, the MCP servers' spawner, the network posture, the paid features' host side and the ide image tools
src/core/ backend-agnostic logic, no `vscode` import: MSP host, Model API client and tools, the MCP client, rules/skills/memory, export, worktrees, usage insights, dictation driver, PDF and text attachments, the paid gate, Muse Voice, network failures
src/shared/ constants + zod message protocol shared with the webview
src/shared/l10n/ the English table (en.ts), the fill, plural and Intl helpers, and the table checks
l10n/ the translated tables (ui.<language>.json) and the gate's list of names left in English
package.nls.json the manifest's text: commands, settings, the walkthrough
src/webview/ React app (own tsconfig, browser libs)
native/windows/ dictate.ps1 (dictation, System.Speech) and capture.ps1 (Muse Voice's recorder); MuseSparkJob.cs, MuseSparkMcpLauncher.cs, MuseSparkMcpJob.cs: the Windows job helpers' C#, compiled on first use
native/darwin/ Dictation.swift, Info.plist, build.sh, check-disclaim.sh: the macOS helper (built and checked in CI)
resources/walkthrough/ the Get Started walkthrough
test/unit/ vitest tests, vscode mock, fakes
test/e2e/ the fake Muse Code CLI and the tests that drive the real backend through it; the opt-in live drill
test/integration/ @vscode/test-cli suites
test/fixtures/workspace/ the workspace the integration tests open
test/harness/ the webview behind a fake host, for screenshots and the accessibility gate; themes/ holds VS Code's four default themes
scripts/ esbuild build; bundle-size, bundle-split, host-globals, notices, audit, PSScriptAnalyzer, accessibility and localization gates; the pseudo-locale; theme capture, harness screenshots, image rendering; CHANGELOG notes and VS Code versions for the workflows
docs/ PRIVACY.md, and certification/: per-milestone gate-fire records
media/ icons, banner, social preview, README screenshots
.github/ workflows (ci, build, release), issue and pull-request templates, audit exceptions, pinned semgrep, CODEOWNERS, Dependabot, FUNDING
Releases. CI (ci.yml, every pull request and optional manual branch
dispatch) calls
build.yml:
quality:gateson Ubuntu, Windows and macOS;- the accessibility gate and the integration tests (VS Code stable and the
engines.vscodefloor) on Ubuntu and Windows; - gitleaks over the full history and semgrep, as jobs of their own;
- a
native-darwinjob that compiles the macOS helper and checks its disclaim; - a
packagejob (Ubuntu) that packs the.vsixwith both helpers as themuse-spark-code-vsixartifact.
A tag v1.2.3 runs release.yml. It checks that the tag matches the
manifest and is on main, runs the same build, creates a GitHub Release with
that .vsix and the CHANGELOG section as its notes, and publishes it to the
Marketplace (publisher RandyNorthrup) from the marketplace environment,
which only version tags reach; without VSCE_PAT the publish is skipped and
reported. A .vsix packed locally has no macOS helper, so only CI's is
published.
Build troubleshooting.
npm cifails with an engine error — Node 22+ is required.- Pre-commit hook says
gitleaks: command not found— install gitleaks (Windows:winget install Gitleaks.Gitleaks). - Type-aware lint rules stop reporting —
npm ls typescriptmust show 6.0.x; TypeScript 7 is outsidetypescript-eslint's peer range. npm run test:integrationcannot download VS Code — the download goes to.vscode-test/; on a restricted network setVSCODE_TEST_VERSIONor pre-populate the folder from another machine.- Webview is blank after a change — run
npm run build:dev(F5 does this via the pre-launch task) and reload the window.
The extension is developed by a small team of AI agents under one human
owner. The process below has been in use since 2026-09-28. Each milestone's
record in docs/certification/ says what was actually run for it; the
records of milestones before that date describe their own checks, which
sometimes differed (for example, M7 was certified against a fake server and
M44 took a response shape from Meta's documentation).
- The owner sets the plan (
PLAN.md), makes the product decisions, and approves anything that spends money, signs in or publishes. - Claude Code is the lead engineer: it turns the plan into briefs, builds the harder milestones itself (security-sensitive and stateful work), verifies every review finding in the code, and merges.
- Muse Code, the product's own backend, builds too. Up to four
headless
muse execinstances draft well-scoped milestones in their own git worktrees, on the Muse Spark contributor model; a Claude Code agent checks and finishes each draft, and it goes through the same review and gates. - Reviewers. A change is reviewed before it is pushed, one defect class at a time (concurrency and lifecycle; wire evidence, validation and security; failure paths, honesty and docs), by Grok Build on a test machine (reading files and inspecting git only) or by Claude Code review agents. On the pull request, Codex reviews again. A finding is fixed with every sibling of its class in one commit, and a change that reaches a third review round is redesigned instead of patched.
- Gates. AGENTS.md requires
npm run qualityto exit 0 before a commit is proposed. Every commit is gated before it is pushed: one completenpm run qualityrun (formatting, lint, types, tests with coverage, the accessibility suite, the secret scan and semgrep) on one of three dedicated test machines (a Windows 11 virtual machine, a Kubuntu virtual machine and a Mac mini), so it never competes with the owner's workstation. The PowerShell lint runs only on Windows, so a change to a PowerShell script gets its run there. CI then runsquality:gateson Ubuntu, Windows and macOS, and the other gates as the jobs listed above. A milestone's new guards get red drills: each guard is broken on purpose, its test must fail, and the file is restored byte for byte; the record lists the drills and anything not drilled. - Evidence. Under AGENTS.md rule 13, a shape parsed from Muse Code or the Model API is written from a live capture, and the record names it or says it did not have one. Live checks run on the contributor model in throwaway workspaces and record their model-call counts.
If Muse Spark Code saves you time, you can buy me a coffee via PayPal. Thank you!
- CHANGELOG.md: what shipped, version by version.
- PLAN.md: decisions, research, milestones and their certification.
- docs/PRIVACY.md: what leaves your machine.
- SECURITY.md and CONTRIBUTING.md.
- Issues.














