Configure YakShaver Desktop (yakshaver CLI)
⚠️ Availability: this skill is INERT until the
yakshaverCLI lands. It documents and drives theyakshaverCLI introduced by PR #910 (src/cli/**+ the localhost config bridge), which is not yet merged tomain. Until #910 is merged (or you are on a branch that includessrc/cli/**), there is nodist/cli/index.jsto build and noyakshavercommand on PATH — the Prerequisites below will fail with command not found / missingdist/cli/index.js. Before running any command in this skill, verify the CLI exists (e.g.yakshaver --help, ortest -f dist/cli/index.js); if it doesn't, tell the user the CLI hasn't shipped yet and stop — do not fall back to editing config files by hand.
Drive the yakshaver CLI to configure YakShaver Desktop's MCP servers and supported
settings from the terminal. The CLI does NOT touch config files directly — it talks to
the running desktop app over a localhost-only, token-authenticated HTTP bridge, so
the app must be running and every change goes through the same services the app's own UI
uses (no duplicated logic, shared Zod validation, secrets redacted).
This skill depends on the yakshaver CLI introduced by PR #910 (src/cli/**), which must be
merged before the skill is usable (see the availability note above).
What this skill is for
Use it when the user asks Claude Code to:
- Add / remove an MCP server for YakShaver Desktop — a backlog provider (GitHub, Azure DevOps, Jira) or any custom stdio / HTTP (streamable-HTTP) MCP server.
- List / inspect the configured MCP servers, the LLM config, or user settings.
- Enable / disable an existing MCP server.
- Change a supported setting (tool-approval mode, open-at-login).
If the request is about something the CLI can't do (see Guardrails — e.g. setting LLM API keys, or the orchestration backend toggle from #908), say so and direct the user to the app's Settings UI instead of guessing.
Prerequisites — check these FIRST
YakShaver Desktop must be RUNNING. The CLI reads a token file the app writes at startup and connects to the app's bridge. If the app is not running (or the bridge is disabled), every command exits 3 and prints:
YakShaver Desktop doesn't appear to be running (or the CLI bridge is disabled). Start the app and retry.When you see exit code 3 or that message, stop and surface it to the user — ask them to start YakShaver Desktop, then retry. Do not try to edit config files as a workaround.
- Token file:
userData/yakshaver-tokens/cli-bridge.json(random 256-bit bearer token- the port; same-user readable,
mode 0o600).userDatais%APPDATA%/YakShaveron Windows,~/Library/Application Support/YakShaveron macOS,$XDG_CONFIG_HOME/~/.configunderYakShaveron Linux. For a dev build it'sYakShaverDev— pass--dev.
- the port; same-user readable,
- Bridge binds 127.0.0.1 only, tries port 8765, falls back to an ephemeral port
(recorded in the token file). It can be disabled with
YAKSHAVER_DISABLE_CLI_BRIDGE.
- Token file:
The
yakshaverCLI must be built and available. This requires PR #910 to be merged (or to be on a branch that includessrc/cli/**) — see the availability note at the top. Ifsrc/cli/is absent,npm run buildwill not emitdist/cli/index.jsand there is noyakshavercommand; stop and tell the user the CLI hasn't shipped yet. Otherwise, from the repo root:npm run build # emits dist/cli/index.js (with a node shebang) npm link # exposes the `yakshaver` command on PATHIf you can't / don't want to
npm link, invoke it directly instead:node dist/cli/index.js <command> [options]Everywhere below that shows
yakshaver ...you can substitutenode dist/cli/index.js ....Confirm reachability with a harmless read before making changes:
yakshaver mcp listIf that succeeds the app is up and the bridge is working.
Command reference
Global flags: --dev (target the dev build's YakShaverDev userData), --json (raw JSON
instead of pretty output), -h / --help. Exit codes: 0 ok, 1 runtime/request error,
2 usage error, 3 app/bridge not reachable.
MCP servers
yakshaver mcp list
yakshaver mcp add --name <name> --transport stdio --command <cmd> [--arg <a> --arg <b> ...] [--env "K=V,K2=V2"]
yakshaver mcp add --name <name> --transport http --url <url> [--header "K=V"]
yakshaver mcp remove <id>
yakshaver mcp enable <id> [--off] # without --off enables; --off disables
--transportacceptsstdioorhttp(aliased to the internalstreamableHttp).- Launch args (
stdio): use the repeatable--arg <value>flag — this is the primary, robust mechanism. Pass one--argper launch argument; each value is taken verbatim, so a single argument may contain spaces (e.g. a Windows path:--arg "C:\My Tools\server.js") and may itself begin with--(a flag-shaped argument:--arg --port --arg 3000). For example,--arg -y --arg @azure-devops/mcp --arg <org>becomes["-y", "@azure-devops/mcp", "<org>"]. - Legacy
--args "a b c"is kept only as a convenience for the trivial, space-free case: it's a single string that the CLI splits on spaces into the argument list. Because the split is on whitespace,--argscannot express an individual argument that itself contains a space — use--arg "C:\My Tools\server.js"for that instead. --argand--argsare mutually exclusive — passing both is a usage error (Use either --arg (repeatable, supports spaces) or --args (space-separated), not both). Prefer--arg; reach for--argsonly for a quick, space-free arg list.--envand--headerare comma-separatedKEY=VALUElists (e.g.--env "A=1,B=2").mcp removeandmcp enableselect the target server by its positional id (get the id fromyakshaver mcp list). There is no--nameselector for remove/enable in this CLI surface — always look up the id withmcp listfirst.--descriptionis optional onadd.
Config (settings + LLM)
yakshaver config get [llm|settings] # defaults to "settings" if omitted
yakshaver config set settings --tool-approval-mode <yolo|wait|ask>
yakshaver config set settings --open-at-login <true|false>
config get llmreturns the LLM config with secrets redacted (see Guardrails).config set settingsrequires at least one of the supported keys above, otherwise it's a usage error. Multiple keys can be combined in one call.config set llmis intentionally not supported (it would require secrets) — the CLI tells you to configure providers in the app UI.
Common workflows (concrete examples)
Always run yakshaver mcp list first so you know the current state and the server ids.
Add a GitHub MCP server (HTTP / streamable-HTTP)
GitHub's hosted MCP server is HTTP-based and authenticated with a token header. Ask the user for the real URL and token — never invent them.
To keep the literal PAT out of shell history and the process table (see the secrets guardrail), set it in an environment variable first and reference it in the header rather than typing the token inline:
export GITHUB_PAT="<USER_PROVIDED_PAT>" # not persisted to history if you prefer; clear afterward
yakshaver mcp add \
--name "GitHub" \
--transport http \
--url "https://api.githubcopilot.com/mcp/" \
--header "Authorization=Bearer $GITHUB_PAT"
yakshaver mcp list # confirm it appears
Add a stdio MCP server (e.g. Azure DevOps via npx)
Pass each launch argument with its own repeatable --arg flag (each value is taken verbatim):
yakshaver mcp add \
--name "Azure DevOps" \
--transport stdio \
--command "npx" \
--arg -y \
--arg @azure-devops/mcp \
--arg <your-org> \
--arg --authentication \
--arg pat \
--env "PERSONAL_ACCESS_TOKEN=$ADO_PAT_B64"
(Set export ADO_PAT_B64="<USER_PROVIDED_BASE64_EMAIL_COLON_PAT>" first so the literal token
isn't typed into the command line — see the secrets guardrail. Clear your history afterward.)
(Each --arg value above — -y, @azure-devops/mcp, <your-org>, --authentication, pat
— becomes one argument verbatim. Note --arg --authentication works because --arg takes its
following token literally even when that token is itself flag-shaped. If any argument needed to
contain a space — e.g. a Windows path — you'd quote it: --arg "C:\My Tools\server.js".)
Get the auth wiring from the official docs — don't invent it. The example above is the
Microsoft @azure-devops/mcp server, which selects its auth method with the
--authentication / -a flag (one of interactive | azcli | envvar | pat), not an
arbitrary *_PAT env var. With no --authentication flag it defaults to interactive
browser login, which fails in a headless Claude Code context — so a non-interactive setup
must pass the flag explicitly:
--authentication patreadsPERSONAL_ACCESS_TOKEN, which must be the base64 encoding of<email>:<pat>(the email can be any non-empty string).--authentication envvarreads a raw bearer token fromADO_MCP_AUTH_TOKEN(handy in CI).
Confirm the exact org, package, flag, and env var with the user against the server's own getting-started doc (https://github.com/microsoft/azure-devops-mcp/blob/main/docs/GETTINGSTARTED.md) before running this — never guess the env var name (see the "Never invent values" guardrail).
List / inspect
yakshaver mcp list # pretty: name [transport] (enabled/disabled), id, url/command
yakshaver mcp list --json # raw JSON for parsing
yakshaver config get settings # current user settings
yakshaver config get llm # LLM config (keys redacted, hasApiKey booleans)
Enable / disable a server
Select the server by its id — run yakshaver mcp list first to find it (the list shows
each server's name alongside its id).
yakshaver mcp list # find the id for "Jira"
yakshaver mcp enable <id> # enable by id
yakshaver mcp enable <id> --off # disable by id
Change the tool-approval mode
yakshaver config set settings --tool-approval-mode wait # one of: yolo | wait | ask
Remove a server
yakshaver mcp list # find the id for the server to remove
yakshaver mcp remove <id> # confirm with the user first (see Guardrails)
Guardrails
- Never invent values. Do not make up server URLs, commands, package names, env vars, headers, tokens, or API keys. If you don't have a real value, ask the user for it.
- Secrets are redacted by the bridge.
config get llmandmcp listreturn***redacted***for api keys, header values, and env values (andhasApiKeybooleans). Don't expectconfig getto echo a key back — you can't read existing secrets through the CLI, only set new ones where supported. - Setting LLM secrets is not supported via the CLI.
config set llmerrors on purpose — direct the user to the app's Settings UI to configure providers / API keys. - Inline secrets in
--header/--envleak into shell history and the process table. A PAT or token typed directly into ayakshaver mcp addcommand line (e.g.--header "Authorization=Bearer <PAT>",--env "PERSONAL_ACCESS_TOKEN=<PAT>") is persisted to the operator's shell history (.bash_history/ PSReadLine) and is visible to other processes on the host (ps,/proc/<pid>/cmdline) for the lifetime of the command. Prefer routing credential-bearing setup through the app's Settings UI, where the bridge redacts secrets (mirroring the unsupportedconfig set llm). If you must use the CLI, reference the secret from an environment variable rather than typing the literal token (e.g. set$GITHUB_PATfirst, then--header "Authorization=Bearer $GITHUB_PAT"), and warn the user to clear their shell history afterward. - The orchestration-backend toggle (#908) is NOT settable via the CLI yet.
config set settingsonly supports--tool-approval-modeand--open-at-login. For orchestration mode, tell the user to change it in the app's Settings. - Confirm before removing.
mcp remove <id>is destructive — show the user which server (name + id, frommcp list) you're about to remove and get confirmation first. - Built-in servers.
mcp listmarks built-ins with[builtin]; prefer enabling/disabling these over removing them, and check with the user. - App-not-running (exit 3). Surface the friendly message and ask the user to start the app; don't fall back to editing config files by hand.
Verifying a change
After any mutating command, re-run a read to confirm the app accepted it:
- After
mcp add/mcp remove/mcp enable:yakshaver mcp list. - After
config set settings ...:yakshaver config get settings.
Because the bridge calls the same services the UI uses, changes should also be visible in the running app's UI.