feat(claude): active-project status line + /mcpctl switcher, and stop tests writing to ~/.claude
Claude Code had neither of the things opencode, pi and prime-agent all have: a
visible active project, and a way to change it from inside a session. It has no
plugin API that can draw a widget or open a picker, but it does run a command
for its status line and it does load slash commands — which is enough for both.
- `mcpctl statusline` prints the active project (from .mcp.json, falling back
to a .mcpctl-project marker) and is wired into settings.json. It reads the
directory out of the JSON Claude Code pipes in, so it follows /cwd rather
than reporting wherever the binary was launched. Prints nothing when no
project is active: an empty line beats "none" on every unrelated repo.
- `/mcpctl [project]` switches and reminds you to reconnect from /mcp.
allowed-tools is scoped to the four exact mcpctl invocations it needs.
Three things found by running it rather than reasoning about it:
- Claude Code REWRITES settings.json against its own schema and strips
unknown keys from `statusLine` — our `_mcpctl_managed` marker came back
gone, so ownership is now determined by the command string. (Hooks keep
their marker; statusLine does not.) A composed line like
`my-prompt && mcpctl statusline` is deliberately not claimed.
- Every `!`-prefixed block in a slash command is permission-checked against
allowed-tools. Omitting `statusline` failed the whole command before the
model saw anything. A test now asserts every pre-executed command is
covered.
- Setting ANTHROPIC_AUTH_TOKEN *and* ANTHROPIC_API_KEY makes Claude Code warn
that auth may not work; claude-vllm now sets only the former and clears an
inherited API key.
Also fixes a pre-existing test-isolation bug this work would have made worse:
`config claude` wrote into the developer's real ~/.claude when the suite ran,
which is how an untagged duplicate of the skills-sync SessionStart hook got
there. Both the hook installer and the new UI installers now honour
CLAUDE_CONFIG_DIR (Claude Code's own override — correct behaviour first,
isolation second), `config claude` gains --claude-dir for parity with --pi-dir
and --opencode-dir, and the suite is verified to leave ~/.claude byte-identical.
Verified live: status line renders `mcpctl:homeautomation`, `/mcpctl docmost`
switches and the line updates to `mcpctl:docmost` in the same session.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVwuCjuMoA13gmzYEfcrNP
This commit is contained in:
@@ -5,7 +5,7 @@ _mcpctl() {
|
||||
local cur prev words cword
|
||||
_init_completion || return
|
||||
|
||||
local commands="status login logout config get describe delete logs create edit apply chat chat-llm patch passwd errors backup approve review skills console cache provider test migrate rotate"
|
||||
local commands="status statusline login logout config get describe delete logs create edit apply chat chat-llm patch passwd errors backup approve review skills console cache provider test migrate rotate"
|
||||
local project_commands="get describe delete logs create edit attach-server detach-server favourites"
|
||||
local global_opts="-v --version --daemon-url --direct -p --project -h --help"
|
||||
local resources="servers instances secrets secretbackends llms agents personalities templates projects users groups rbac prompts promptrequests serverattachments proxymodels inference-tasks all"
|
||||
@@ -94,6 +94,9 @@ _mcpctl() {
|
||||
status)
|
||||
COMPREPLY=($(compgen -W "-o --output -h --help" -- "$cur"))
|
||||
return ;;
|
||||
statusline)
|
||||
COMPREPLY=($(compgen -W "-d --directory --prefix -h --help" -- "$cur"))
|
||||
return ;;
|
||||
login)
|
||||
COMPREPLY=($(compgen -W "--mcpd-url -h --help" -- "$cur"))
|
||||
return ;;
|
||||
@@ -119,10 +122,10 @@ _mcpctl() {
|
||||
COMPREPLY=($(compgen -W "-h --help" -- "$cur"))
|
||||
;;
|
||||
claude)
|
||||
COMPREPLY=($(compgen -W "-p --project -o --output --inspect --stdout --skip-skills --skip-marker --dry-run -h --help" -- "$cur"))
|
||||
COMPREPLY=($(compgen -W "-p --project -o --output --inspect --stdout --skip-skills --skip-marker --skip-ui --claude-dir --dry-run -h --help" -- "$cur"))
|
||||
;;
|
||||
claude-generate)
|
||||
COMPREPLY=($(compgen -W "-p --project -o --output --inspect --stdout --skip-skills --skip-marker --dry-run -h --help" -- "$cur"))
|
||||
COMPREPLY=($(compgen -W "-p --project -o --output --inspect --stdout --skip-skills --skip-marker --skip-ui --claude-dir --dry-run -h --help" -- "$cur"))
|
||||
;;
|
||||
pi)
|
||||
COMPREPLY=($(compgen -W "-p --project --extension-dir --skip-skills --settings --pi-dir -h --help" -- "$cur"))
|
||||
|
||||
Reference in New Issue
Block a user