one-code-extension 0.4.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -5
- package/agents/general-purpose.md +2 -2
- package/docs/guide/README.md +2 -1
- package/docs/guide/bring-your-claude-code-setup.md +60 -9
- package/docs/guide/configuration.md +48 -14
- package/docs/guide/differences-from-claude-code.md +40 -28
- package/docs/guide/doctor.md +20 -13
- package/docs/guide/hooks.md +18 -3
- package/docs/guide/installation.md +26 -4
- package/docs/guide/permissions-modes-and-auto-mode.md +225 -49
- package/docs/guide/providers-and-models.md +137 -54
- package/docs/guide/reference.md +27 -15
- package/docs/guide/sessions-and-context.md +69 -16
- package/docs/guide/skills-plugins-and-mcp.md +57 -20
- package/docs/guide/subagents-and-workflows.md +95 -29
- package/docs/guide/tasks-and-background-work.md +101 -26
- package/docs/guide/terminal-interface.md +24 -12
- package/docs/guide/tools.md +46 -5
- package/docs/guide/troubleshooting.md +13 -9
- package/docs/guide/windows.md +58 -31
- package/extensions/artifacts/gallery.ts +227 -0
- package/extensions/artifacts/index.ts +288 -0
- package/extensions/artifacts/store.ts +570 -0
- package/extensions/artifacts/viewer.ts +199 -0
- package/extensions/ask-user/description.ts +67 -0
- package/extensions/ask-user/dialogs.ts +80 -0
- package/extensions/ask-user/index.ts +37 -33
- package/extensions/ask-user/questions.ts +32 -7
- package/extensions/ask-user/widget.ts +45 -25
- package/extensions/auto-mode/actions.ts +6 -0
- package/extensions/auto-mode/cache.ts +88 -0
- package/extensions/auto-mode/classifier-prompt.ts +5 -4
- package/extensions/auto-mode/classifier.ts +290 -65
- package/extensions/auto-mode/config.ts +72 -20
- package/extensions/auto-mode/decision-log.ts +2 -0
- package/extensions/auto-mode/defaults.ts +1 -1
- package/extensions/auto-mode/denials.ts +124 -0
- package/extensions/auto-mode/git-checkout-programs.ts +187 -0
- package/extensions/auto-mode/git-status-meta.ts +159 -0
- package/extensions/auto-mode/history.ts +189 -0
- package/extensions/auto-mode/instructions.ts +58 -52
- package/extensions/auto-mode/model-select.ts +159 -134
- package/extensions/auto-mode/paths.ts +57 -5
- package/extensions/auto-mode/pause.ts +57 -2
- package/extensions/auto-mode/prompt.ts +37 -21
- package/extensions/auto-mode/read-only-options.ts +724 -0
- package/extensions/auto-mode/resolved-paths-meta.ts +133 -0
- package/extensions/auto-mode/rules.ts +18 -1
- package/extensions/auto-mode/safety-floor.ts +361 -18
- package/extensions/auto-mode/setup-run.ts +20 -14
- package/extensions/auto-mode/shell-analysis.ts +764 -490
- package/extensions/auto-mode/shell-parse.ts +885 -0
- package/extensions/auto-mode/system-note.ts +33 -0
- package/extensions/auto-mode/transcript.ts +80 -51
- package/extensions/background/cron.ts +642 -0
- package/extensions/background/index.ts +614 -248
- package/extensions/background/loop-fire.ts +173 -0
- package/extensions/background/loop-preamble.ts +59 -0
- package/extensions/background/loop-skill.ts +163 -0
- package/extensions/background/monitor-batch.ts +53 -0
- package/extensions/background/noop-fold.ts +128 -0
- package/extensions/background/switch-guard.ts +56 -0
- package/extensions/background/wakeup.ts +178 -55
- package/extensions/bash/background.ts +53 -17
- package/extensions/bash/child.ts +7 -0
- package/extensions/bash/description.ts +188 -0
- package/extensions/bash/guards.ts +15 -67
- package/extensions/bash/index.ts +66 -35
- package/extensions/branding/compaction-keep.ts +63 -0
- package/extensions/branding/declined.ts +22 -0
- package/extensions/branding/index.ts +133 -9
- package/extensions/branding/prompt-editor.ts +53 -6
- package/extensions/branding/queued-edit.ts +31 -0
- package/extensions/branding/replaced-builtins.ts +68 -0
- package/extensions/branding/startup.ts +33 -71
- package/extensions/btw/index.ts +250 -78
- package/extensions/btw/panel.ts +228 -100
- package/extensions/btw/prompt.ts +41 -4
- package/extensions/cache-marks/index.ts +42 -0
- package/extensions/claude-compat/index.ts +7 -11
- package/extensions/claude-context/index.ts +436 -63
- package/extensions/compaction/cut.ts +157 -0
- package/extensions/compaction/index.ts +219 -75
- package/extensions/compaction/kept-thinking.ts +62 -0
- package/extensions/compaction/prompt.ts +15 -12
- package/extensions/context-budget/budget.ts +16 -2
- package/extensions/context-budget/index.ts +35 -15
- package/extensions/context-management/index.ts +36 -28
- package/extensions/doctor/build.ts +59 -8
- package/extensions/doctor/builtins.ts +84 -0
- package/extensions/doctor/cli.ts +7 -1
- package/extensions/doctor/compat.ts +88 -23
- package/extensions/doctor/dependencies.ts +41 -5
- package/extensions/doctor/fix-prompt.ts +9 -2
- package/extensions/doctor/index.ts +102 -58
- package/extensions/doctor/models.ts +102 -63
- package/extensions/doctor/presets.ts +42 -27
- package/extensions/doctor/report.ts +19 -2
- package/extensions/doctor/viewer.ts +49 -27
- package/extensions/effort/index.ts +141 -25
- package/extensions/effort/settings.ts +21 -0
- package/extensions/effort/slider.ts +24 -20
- package/extensions/exit/index.ts +32 -1
- package/extensions/file-tracker/index.ts +420 -42
- package/extensions/file-tracker/replay.ts +137 -24
- package/extensions/file-tracker/restore.ts +66 -0
- package/extensions/file-tracker/results.ts +66 -0
- package/extensions/file-tracker/shell-reads.ts +211 -0
- package/extensions/file-tracker/tracker.ts +45 -15
- package/extensions/footer/footer-line.ts +45 -24
- package/extensions/footer/index.ts +47 -2
- package/extensions/footer/pr.ts +34 -5
- package/extensions/hooks/compaction.ts +7 -0
- package/extensions/hooks/executor.ts +32 -30
- package/extensions/hooks/index.ts +209 -58
- package/extensions/hooks/matcher.ts +3 -0
- package/extensions/hooks/prompt-context.ts +59 -0
- package/extensions/hooks/protocol.ts +41 -3
- package/extensions/hooks/settings.ts +50 -19
- package/extensions/hooks/subagent-bridge.ts +2 -0
- package/extensions/hooks/trust.ts +26 -12
- package/extensions/idle-compact/index.ts +119 -0
- package/extensions/idle-compact/policy.ts +143 -0
- package/extensions/init/index.ts +11 -10
- package/extensions/init/prompt.ts +25 -32
- package/extensions/interrupted/index.ts +13 -1
- package/extensions/kept-thinking/index.ts +27 -0
- package/extensions/ledger/index.ts +46 -0
- package/extensions/ledger/wire.ts +154 -0
- package/extensions/lib/agent-cron.ts +146 -0
- package/extensions/lib/agent-loader.ts +18 -3
- package/extensions/lib/agent-view.ts +85 -0
- package/extensions/lib/anthropic-auth.ts +98 -0
- package/extensions/lib/anthropic-payload.ts +82 -1
- package/extensions/lib/anthropic-server-call.ts +230 -0
- package/extensions/lib/anthropic-server-tools.ts +485 -0
- package/extensions/lib/app-launch.mjs +94 -0
- package/extensions/lib/argument-hints.ts +190 -0
- package/extensions/lib/atomic-write.ts +6 -2
- package/extensions/lib/auto-memory.ts +75 -0
- package/extensions/lib/bash-parser.ts +84 -0
- package/extensions/lib/btw-fork.ts +93 -0
- package/extensions/lib/child-extensions.ts +52 -0
- package/extensions/lib/child-writes.ts +45 -0
- package/extensions/lib/claude-context.ts +515 -100
- package/extensions/lib/claude-external-includes.ts +68 -0
- package/extensions/lib/claude-id.ts +22 -0
- package/extensions/lib/claude-rules.ts +323 -0
- package/extensions/lib/claude-settings.ts +76 -4
- package/extensions/lib/compaction-boundary.ts +36 -0
- package/extensions/lib/compaction-keep.mjs +83 -0
- package/extensions/lib/config-mode.ts +112 -0
- package/extensions/lib/consent-dialogs.ts +63 -0
- package/extensions/lib/consent-preview.ts +5 -1
- package/extensions/lib/consent-stores.ts +48 -0
- package/extensions/lib/context-facts.ts +97 -0
- package/extensions/lib/covered-messages.ts +23 -0
- package/extensions/lib/deferred.ts +359 -25
- package/extensions/lib/dock-rows.ts +60 -0
- package/extensions/lib/empty-tool-result.ts +27 -0
- package/extensions/lib/environment-block.ts +76 -0
- package/extensions/lib/fetch-timeout.ts +24 -6
- package/extensions/{system-prompt → lib}/git-status.ts +51 -13
- package/extensions/lib/git.ts +75 -13
- package/extensions/lib/grammars/LICENSE-tree-sitter-bash +21 -0
- package/extensions/lib/grammars/README.md +2 -0
- package/extensions/lib/grammars/tree-sitter-bash.wasm +0 -0
- package/extensions/lib/guide-docs.ts +45 -0
- package/extensions/lib/headless-output.ts +46 -0
- package/extensions/lib/hook-gate.ts +7 -7
- package/extensions/lib/interrupt.ts +20 -4
- package/extensions/lib/key-input.ts +455 -0
- package/extensions/lib/keys.ts +14 -1
- package/extensions/lib/ledger/fold-memo.ts +49 -0
- package/extensions/lib/ledger/fold.ts +265 -0
- package/extensions/lib/ledger/layout.ts +72 -0
- package/extensions/lib/ledger/plan.ts +102 -0
- package/extensions/lib/ledger/records.ts +276 -0
- package/extensions/lib/ledger/state.ts +47 -0
- package/extensions/lib/ledger/validate.ts +141 -0
- package/extensions/lib/ledger/wire.ts +632 -0
- package/extensions/lib/local-command.ts +71 -19
- package/extensions/lib/mcp-overrides.ts +1 -1
- package/extensions/lib/mcp-share.ts +46 -0
- package/extensions/lib/memory-content.ts +146 -0
- package/extensions/lib/memory-index.ts +18 -0
- package/extensions/lib/memory.ts +134 -123
- package/extensions/lib/model-catalog/huggingface.json +178 -0
- package/extensions/lib/model-catalog/models-dev.json +18533 -0
- package/extensions/lib/model-catalog/openrouter.json +5050 -0
- package/extensions/lib/model-catalog-data.ts +513 -0
- package/extensions/lib/model-catalog.ts +462 -0
- package/extensions/lib/model-choice-warnings.ts +137 -0
- package/extensions/lib/model-pairings.ts +152 -0
- package/extensions/{auto-mode → lib}/model-picker.ts +26 -43
- package/extensions/lib/model-policy.ts +112 -15
- package/extensions/lib/model-tier.ts +283 -355
- package/extensions/lib/model-unusable.ts +1 -1
- package/extensions/lib/newer-model.ts +100 -0
- package/extensions/lib/notices.ts +87 -0
- package/extensions/lib/notifications.ts +357 -73
- package/extensions/lib/one-code-settings.ts +74 -8
- package/extensions/lib/open-browser.ts +63 -0
- package/extensions/lib/openrouter-generation.ts +94 -0
- package/extensions/lib/operation-deadline.ts +30 -0
- package/extensions/lib/original-command.ts +4 -4
- package/extensions/lib/package-version.ts +1 -1
- package/extensions/lib/panel-focus.ts +134 -0
- package/extensions/lib/paths.ts +17 -2
- package/extensions/lib/permission-gate.ts +72 -6
- package/extensions/lib/persisted-output.ts +60 -8
- package/extensions/lib/pi-ai-estimate.ts +19 -3
- package/extensions/lib/pi-version.ts +38 -2
- package/extensions/lib/plan-mode-channels.ts +42 -5
- package/extensions/lib/plugins.ts +26 -17
- package/extensions/lib/powershell-parse-script.ts +208 -0
- package/extensions/lib/powershell-parser.ts +344 -0
- package/extensions/lib/previous-mark.ts +101 -0
- package/extensions/lib/process-state.ts +48 -0
- package/extensions/lib/process-tree.ts +132 -8
- package/extensions/lib/prompt-options.ts +82 -0
- package/extensions/lib/queued-delivery.ts +44 -0
- package/extensions/lib/reminders.ts +370 -358
- package/extensions/lib/replaced-builtins.mjs +199 -0
- package/extensions/lib/replay-call.ts +70 -0
- package/extensions/lib/request-replay.ts +547 -0
- package/extensions/lib/scratchpad.ts +81 -14
- package/extensions/lib/send-now-channel.ts +7 -0
- package/extensions/lib/session-model-tier.ts +51 -0
- package/extensions/lib/session-work.ts +64 -0
- package/extensions/lib/settings-channels.ts +4 -4
- package/extensions/lib/shell-exit-semantics.ts +170 -0
- package/extensions/lib/shell-quote.ts +11 -0
- package/extensions/lib/shell-result.ts +70 -0
- package/extensions/lib/shell-spawn.ts +70 -6
- package/extensions/lib/shell-tool.ts +75 -25
- package/extensions/lib/side-call-cache.ts +124 -0
- package/extensions/lib/side-call-run.ts +96 -0
- package/extensions/lib/side-call-usage.ts +38 -0
- package/extensions/lib/side-call.ts +24 -1
- package/extensions/lib/single-flight.ts +18 -0
- package/extensions/lib/skill-body.ts +42 -0
- package/extensions/lib/skill-scan.ts +63 -24
- package/extensions/lib/spill-file.ts +140 -0
- package/extensions/lib/subagent-handback.ts +112 -0
- package/extensions/lib/system-role.ts +156 -0
- package/extensions/lib/terminal-text.ts +114 -0
- package/extensions/lib/text-width.ts +47 -16
- package/extensions/lib/timer-ops.ts +20 -0
- package/extensions/lib/tool-additions.ts +129 -0
- package/extensions/lib/tool-call-corruption.ts +134 -0
- package/extensions/lib/tool-path.ts +66 -0
- package/extensions/lib/tool-variants.ts +69 -0
- package/extensions/lib/tui-render.ts +255 -27
- package/extensions/lib/turn-budget-layout.ts +159 -0
- package/extensions/lib/update-check.mjs +15 -2
- package/extensions/lib/usage-bus.ts +1 -1
- package/extensions/lib/user-denial.ts +38 -0
- package/extensions/lib/workspace-channel.ts +16 -0
- package/extensions/lib/worktree-channel.ts +31 -3
- package/extensions/lib/worktree-isolation.ts +40 -10
- package/extensions/lsp/client.ts +8 -9
- package/extensions/lsp/index.ts +76 -12
- package/extensions/lsp/keep-alive.ts +1 -1
- package/extensions/lsp/trust.ts +119 -0
- package/extensions/lsp/watcher.ts +1 -1
- package/extensions/mcp/announce.ts +90 -43
- package/extensions/mcp/client.ts +161 -48
- package/extensions/mcp/config.ts +132 -8
- package/extensions/mcp/discovery.ts +19 -0
- package/extensions/mcp/index.ts +220 -121
- package/extensions/mcp/oauth/browser.ts +38 -17
- package/extensions/mcp/oauth/flow.ts +25 -17
- package/extensions/mcp/oauth/provider.ts +14 -8
- package/extensions/mcp/oauth/store.ts +34 -16
- package/extensions/mcp/panel/keys.ts +12 -11
- package/extensions/mcp/panel/render.ts +9 -6
- package/extensions/mcp/schema.ts +104 -5
- package/extensions/mcp/trust.ts +164 -73
- package/extensions/memory/entries.ts +23 -14
- package/extensions/memory/index.ts +134 -28
- package/extensions/memory/open-external.ts +33 -18
- package/extensions/memory/panel.ts +135 -26
- package/extensions/model-default/index.ts +86 -19
- package/extensions/newer-model/index.ts +31 -0
- package/extensions/notebook/description.ts +18 -0
- package/extensions/notebook/index.ts +6 -5
- package/extensions/notebook/notebook.ts +1 -1
- package/extensions/permissions/index.ts +1426 -398
- package/extensions/permissions/matcher.ts +425 -74
- package/extensions/permissions/modes.ts +11 -4
- package/extensions/permissions/panel/host.ts +130 -0
- package/extensions/permissions/panel/keys.ts +48 -0
- package/extensions/permissions/panel/render.ts +450 -0
- package/extensions/permissions/panel/state.ts +550 -0
- package/extensions/permissions/powershell-cmdlets.ts +198 -0
- package/extensions/permissions/powershell-paths.ts +197 -0
- package/extensions/permissions/powershell-rules.ts +207 -280
- package/extensions/permissions/powershell-tree.ts +557 -0
- package/extensions/permissions/project-trust.ts +27 -11
- package/extensions/permissions/protected-paths.ts +14 -2
- package/extensions/permissions/session-grant.ts +6 -0
- package/extensions/permissions/settings.ts +166 -31
- package/extensions/permissions/subagent-gate.ts +25 -0
- package/extensions/permissions/workspace.ts +78 -0
- package/extensions/plan-mode/index.ts +276 -92
- package/extensions/plan-mode/reminder.ts +89 -21
- package/extensions/plan-mode/run-state.ts +26 -0
- package/extensions/plan-mode/texts.ts +177 -0
- package/extensions/plan-mode/viewer.ts +92 -27
- package/extensions/plugins/counts.ts +3 -3
- package/extensions/plugins/index.ts +64 -46
- package/extensions/plugins/install/install.ts +16 -0
- package/extensions/plugins/marketplace/sync.ts +9 -3
- package/extensions/plugins/marketplace/types.ts +3 -1
- package/extensions/plugins/panel/keys.ts +21 -24
- package/extensions/plugins/panel/render.ts +12 -6
- package/extensions/plugins/shell-expand.ts +107 -0
- package/extensions/plugins/template.ts +32 -15
- package/extensions/powershell/child.ts +7 -0
- package/extensions/powershell/description.ts +38 -6
- package/extensions/powershell/guards.ts +1 -1
- package/extensions/powershell/index.ts +14 -7
- package/extensions/recap/index.ts +73 -71
- package/extensions/recap/prompt.ts +2 -2
- package/extensions/recap/scheduler.ts +3 -5
- package/extensions/search-tools/grep-merge.ts +39 -0
- package/extensions/search-tools/index.ts +0 -0
- package/extensions/send-now/chord.ts +62 -0
- package/extensions/send-now/index.ts +133 -0
- package/extensions/session-title/index.ts +3 -0
- package/extensions/session-title/title.ts +4 -1
- package/extensions/skill/announce.ts +30 -0
- package/extensions/skill/code-review.ts +97 -0
- package/extensions/skill/index.ts +469 -132
- package/extensions/skill/invoke.ts +118 -75
- package/extensions/skill/listing.ts +133 -9
- package/extensions/skill/panel/keys.ts +15 -16
- package/extensions/skill/panel/render.ts +5 -2
- package/extensions/skill/panel/state.ts +12 -1
- package/extensions/subagents/agent-args.ts +39 -0
- package/extensions/subagents/agent-description.ts +132 -0
- package/extensions/subagents/agents.ts +146 -31
- package/extensions/subagents/default-model.ts +2 -3
- package/extensions/subagents/delegation-steer.ts +4 -4
- package/extensions/subagents/fork-cache.ts +82 -0
- package/extensions/subagents/guide-agent.ts +189 -0
- package/extensions/subagents/hand-back-review.ts +3 -0
- package/extensions/subagents/index.ts +1594 -852
- package/extensions/subagents/live-runs.ts +26 -6
- package/extensions/subagents/model-select.ts +38 -25
- package/extensions/subagents/outcome.ts +5 -2
- package/extensions/subagents/panel-keys.ts +73 -31
- package/extensions/subagents/panel-render.ts +120 -96
- package/extensions/subagents/panel-widget.ts +60 -89
- package/extensions/subagents/parent-mode.ts +50 -0
- package/extensions/subagents/pending-claim.ts +18 -1
- package/extensions/subagents/runner.ts +135 -80
- package/extensions/subagents/runs.ts +44 -5
- package/extensions/subagents/send-to-main-tool.ts +1 -1
- package/extensions/subagents/session-turns.ts +32 -8
- package/extensions/subagents/shell-panel.ts +36 -178
- package/extensions/subagents/tasks-dialog.ts +170 -0
- package/extensions/subagents/viewport-mirror.ts +95 -0
- package/extensions/subagents/worktree.ts +57 -13
- package/extensions/system-prompt/environment.ts +19 -19
- package/extensions/system-prompt/idle-turn.ts +65 -0
- package/extensions/system-prompt/index.ts +165 -47
- package/extensions/system-prompt/template.ts +34 -51
- package/extensions/system-prompt/tiers/common.ts +23 -64
- package/extensions/system-prompt/tiers/frontier.ts +32 -11
- package/extensions/system-prompt/tiers/low.ts +67 -45
- package/extensions/system-prompt/tiers/mid.ts +96 -38
- package/extensions/system-reminder/index.ts +204 -70
- package/extensions/tasks/descriptions.ts +190 -0
- package/extensions/tasks/index.ts +120 -41
- package/extensions/tasks/store.ts +83 -16
- package/extensions/tool-call-corruption/child.ts +7 -0
- package/extensions/tool-call-corruption/index.ts +237 -0
- package/extensions/tool-search/index.ts +366 -144
- package/extensions/tool-style/index.ts +68 -10
- package/extensions/tool-style/write-description.ts +40 -0
- package/extensions/tool-style/write-render.ts +237 -0
- package/extensions/turn-duration/index.ts +7 -3
- package/extensions/turn-duration/line.ts +47 -4
- package/extensions/web/backends.ts +6 -9
- package/extensions/web/description.ts +50 -0
- package/extensions/web/index.ts +118 -53
- package/extensions/web/native-call.ts +15 -0
- package/extensions/web/native-results.ts +41 -0
- package/extensions/web-fetch/description.ts +42 -0
- package/extensions/web-fetch/extract.ts +53 -6
- package/extensions/web-fetch/index.ts +125 -76
- package/extensions/web-fetch/page-content.ts +19 -0
- package/extensions/web-fetch/response.ts +49 -0
- package/extensions/web-fetch/summarize.ts +9 -10
- package/extensions/workflow/agent-session.ts +108 -18
- package/extensions/workflow/args.ts +24 -0
- package/extensions/workflow/description.ts +67 -0
- package/extensions/workflow/globals.ts +17 -3
- package/extensions/workflow/index.ts +157 -162
- package/extensions/workflow/records.ts +1 -0
- package/extensions/workflow/run-manager.ts +33 -6
- package/extensions/workflow/saved-workflows.ts +3 -2
- package/extensions/workflow/types.ts +22 -1
- package/extensions/workflow/viewer.ts +54 -24
- package/extensions/workflow/widget.ts +20 -0
- package/extensions/worktree/descriptions.ts +91 -0
- package/extensions/worktree/guards.ts +316 -54
- package/extensions/worktree/index.ts +162 -44
- package/extensions/worktree/powershell-guards.ts +167 -0
- package/extensions/worktree/rewrite.ts +14 -16
- package/package.json +21 -7
- package/skills/artifact-design/SKILL.md +85 -0
- package/skills/code-review/SKILL.md +20 -20
- package/skills/code-review/cells/arguments-and-flags.md +19 -0
- package/skills/code-review/cells/high-3x5-recall-verify.md +137 -0
- package/skills/code-review/cells/high-8-inline.md +122 -0
- package/skills/code-review/cells/low-1-pass-max4.md +27 -0
- package/skills/code-review/cells/low-1-pass-min-files-4.md +28 -0
- package/skills/code-review/cells/max-5x5-verify-sweep.md +162 -0
- package/skills/code-review/cells/medium-3x5-verify.md +132 -0
- package/skills/code-review/cells/minimal-prompt.md +32 -0
- package/skills/code-review/cells/xhigh-10-inline-sweep.md +149 -0
- package/skills/code-review/cells/xhigh-5x5-verify-sweep.md +162 -0
- package/skills/fewer-permission-prompts/SKILL.md +1 -1
- package/skills/loop/SKILL.md +11 -0
- package/skills/security-review/SKILL.md +2 -5
- package/skills/simplify/SKILL.md +7 -5
- package/skills/workflow-authoring/SKILL.md +143 -0
- package/themes/onecode-light.json +1 -1
- package/themes/onecode.json +1 -1
- package/types/app.d.ts +58 -0
- package/types/community-packages.d.ts +26 -1
- package/extensions/auto-mode/recoverability.ts +0 -229
- package/extensions/lib/capability-index.ts +0 -466
- package/extensions/lib/model-facts.generated.json +0 -2675
- package/extensions/lib/model-facts.ts +0 -162
- package/extensions/tool-search/announce.ts +0 -42
package/extensions/mcp/trust.ts
CHANGED
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
* server found in .mcp.json" and remembers the answer in
|
|
6
6
|
* `enabledMcpjsonServers` / `disabledMcpjsonServers` /
|
|
7
7
|
* `enableAllProjectMcpServers`. One Code honours those three keys READ-ONLY
|
|
8
|
-
* (
|
|
9
|
-
*
|
|
8
|
+
* (the approving two from the user's settings only, the disable list from
|
|
9
|
+
* `.claude/settings.local.json` too — never the checked-in project
|
|
10
|
+
* `settings.json`, which would let a repo approve itself) and keeps its
|
|
10
11
|
* own answers under `~/.onecode`, keyed to a hash of each server's config so a
|
|
11
12
|
* changed command re-prompts (CC keys by name alone). Servers from
|
|
12
13
|
* `~/.claude.json` and plugins never prompt: the user wrote the first, and
|
|
@@ -14,8 +15,9 @@
|
|
|
14
15
|
* ARE prompted (that file can be checked in — `git clone && onecode` would
|
|
15
16
|
* otherwise spawn its servers with no consent, review H1); CC never reads
|
|
16
17
|
* `mcpServers` from that file at all. Its `enableAll*`/`enabledMcpjsonServers`
|
|
17
|
-
* policy keys are honoured
|
|
18
|
-
*
|
|
18
|
+
* policy keys are never honoured, for the same reason: git provenance cannot
|
|
19
|
+
* tell a user's file from one shipped with a copied checkout
|
|
20
|
+
* (`readClaudeMcpjsonPolicy`).
|
|
19
21
|
*
|
|
20
22
|
* A "No" is persisted as a project-scope disable (`lib/mcp-overrides.ts`), so
|
|
21
23
|
* the server shows as disabled in `/mcp` and Enable there brings it back —
|
|
@@ -23,17 +25,16 @@
|
|
|
23
25
|
* only. Same shape as `hooks/trust.ts`.
|
|
24
26
|
*/
|
|
25
27
|
|
|
26
|
-
import { execFile } from "node:child_process";
|
|
27
28
|
import { createHash } from "node:crypto";
|
|
28
|
-
import { promisify } from "node:util";
|
|
29
29
|
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
30
30
|
import { basename, dirname, join } from "node:path";
|
|
31
|
-
import { readSettingsFile,
|
|
31
|
+
import { readSettingsFile, type SettingsSource, settingsSources } from "../lib/claude-settings.ts";
|
|
32
|
+
import { claudeSourcesOn } from "../lib/config-mode.ts";
|
|
32
33
|
import { boundConsentItems } from "../lib/consent-preview.ts";
|
|
33
|
-
import {
|
|
34
|
+
import { consentStorePath } from "../lib/consent-stores.ts";
|
|
35
|
+
import { processState } from "../lib/process-state.ts";
|
|
34
36
|
import type { McpServer } from "./config.ts";
|
|
35
|
-
|
|
36
|
-
const execFileAsync = promisify(execFile);
|
|
37
|
+
import { escapeControlText } from "../lib/terminal-text.ts";
|
|
37
38
|
|
|
38
39
|
interface ProjectApprovals {
|
|
39
40
|
/** "Use this and all future MCP servers in this project" was chosen. */
|
|
@@ -47,19 +48,42 @@ interface ApprovalStore {
|
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
export function approvalStorePath(): string {
|
|
50
|
-
return
|
|
51
|
+
return consentStorePath("mcp");
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
/**
|
|
54
|
-
* A server whose config a repository can ship (a project `.mcp.json
|
|
55
|
-
* checked-in `.claude/settings.local.json
|
|
56
|
-
* plugin's `.mcp.json` (also named `.mcp.json`) is
|
|
57
|
-
* plugin was the consent.
|
|
55
|
+
* A server whose config a repository can ship (a project `.mcp.json`, a
|
|
56
|
+
* checked-in `.claude/settings.local.json`, or pi's project `.pi/mcp.json`) —
|
|
57
|
+
* so it is consent-gated. A plugin's `.mcp.json` (also named `.mcp.json`) is
|
|
58
|
+
* excluded: installing the plugin was the consent. pi's user file
|
|
59
|
+
* (`<agentDir>/mcp.json`) is the user's own, like `~/.claude.json`.
|
|
58
60
|
*/
|
|
59
61
|
export function isProjectScopedServer(server: McpServer, pluginConfigPaths: ReadonlySet<string>): boolean {
|
|
60
62
|
if (pluginConfigPaths.has(server.source)) return false;
|
|
61
63
|
const base = basename(server.source);
|
|
62
|
-
return base === ".mcp.json" || base === "settings.local.json";
|
|
64
|
+
return base === ".mcp.json" || base === "settings.local.json" || server.piOrigin === "project";
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** A server from a project `.mcp.json`: the only kind Claude Code's own answers approve. */
|
|
68
|
+
function definedInMcpjson(server: McpServer): boolean {
|
|
69
|
+
return basename(server.source) === ".mcp.json";
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** The project file a consent-gated server comes from, as the dialog names it. */
|
|
73
|
+
function configLabel(server: McpServer): string {
|
|
74
|
+
if (definedInLocalSettings(server)) return ".claude/settings.local.json";
|
|
75
|
+
// pi's project file is `<dir>/<pi's config dir>/mcp.json`, `.pi/mcp.json` unless pi is rebranded.
|
|
76
|
+
return server.piOrigin === "project" ? `${basename(dirname(server.source))}/mcp.json` : ".mcp.json";
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** "a and b" for the distinct config files of `servers`. */
|
|
80
|
+
function configLabels(servers: McpServer[]): string {
|
|
81
|
+
return [...new Set(servers.map(configLabel))].join(" and ");
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** A server defined in `.claude/settings.local.json` rather than a `.mcp.json`. */
|
|
85
|
+
function definedInLocalSettings(server: McpServer): boolean {
|
|
86
|
+
return basename(server.source) === "settings.local.json";
|
|
63
87
|
}
|
|
64
88
|
|
|
65
89
|
/** The directory the `.mcp.json` lives in — approvals are per config file, not per cwd. */
|
|
@@ -79,12 +103,15 @@ function canonicalize(value: unknown): unknown {
|
|
|
79
103
|
return value;
|
|
80
104
|
}
|
|
81
105
|
|
|
82
|
-
/**
|
|
106
|
+
/**
|
|
107
|
+
* Everything that decides what the server runs or talks to; `source`/`missingEnv` are not part of it.
|
|
108
|
+
* A stdio `cwd` (pi's files only) joins the material only when set, so existing approvals keep their hash.
|
|
109
|
+
*/
|
|
83
110
|
export function hashServerConfig(server: McpServer): string {
|
|
84
111
|
const material =
|
|
85
112
|
server.kind === "stdio"
|
|
86
|
-
? { kind: "stdio", command: server.command, args: server.args, env: server.env ?? {} }
|
|
87
|
-
: { kind: "http", url: server.url, headers: server.headers ?? {} };
|
|
113
|
+
? { kind: "stdio", command: server.command, args: server.args, env: server.env ?? {}, ...(server.cwd ? { cwd: server.cwd } : {}) }
|
|
114
|
+
: { kind: "http", url: server.url, headers: server.headers ?? {}, ...(server.transport ? { transport: server.transport } : {}) };
|
|
88
115
|
return createHash("sha256").update(JSON.stringify(canonicalize(material))).digest("hex");
|
|
89
116
|
}
|
|
90
117
|
|
|
@@ -100,45 +127,36 @@ function stringArray(value: unknown): string[] {
|
|
|
100
127
|
}
|
|
101
128
|
|
|
102
129
|
/**
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
130
|
+
* Claude Code's answers that One Code honours. The approving keys
|
|
131
|
+
* (`enableAllProjectMcpServers`, `enabledMcpjsonServers`) count only from the
|
|
132
|
+
* user's `~/.claude/settings.json`. Until 2026-09-27 they also counted from a
|
|
133
|
+
* `.claude/settings.local.json` that git reported untracked, but a directory
|
|
134
|
+
* that carries its own `.git` (a tarball of a working copy, a copied or
|
|
135
|
+
* synced checkout) makes a shipped file untracked too, so its servers
|
|
136
|
+
* connected with no prompt, headless included. No check of the local file
|
|
137
|
+
* can tell who wrote it, so it no longer approves anything: its servers go
|
|
138
|
+
* through One Code's own dialog and hash-keyed store. Its
|
|
139
|
+
* `disabledMcpjsonServers` only tightens, so it is still honoured. Async for
|
|
140
|
+
* its callers; nothing here shells out any more.
|
|
111
141
|
*/
|
|
112
|
-
async function localPolicyFileIsTrusted(cwd: string, path: string): Promise<boolean> {
|
|
113
|
-
try {
|
|
114
|
-
await execFileAsync("git", ["ls-files", "--error-unmatch", "--", path], { cwd, timeout: 5_000 });
|
|
115
|
-
return false; // exit 0 → tracked → do not trust its policy keys
|
|
116
|
-
} catch (error) {
|
|
117
|
-
// execFile rejects with `code` = the numeric exit code on a non-zero exit
|
|
118
|
-
// (1 = untracked in a repo, 128 = not a repo — both mean "not tracked, safe
|
|
119
|
-
// to trust"); a spawn failure gives a string code (e.g. "ENOENT") and a
|
|
120
|
-
// timeout gives a non-numeric code — those are "could not decide" → closed.
|
|
121
|
-
return typeof (error as { code?: unknown }).code === "number";
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
142
|
export async function readClaudeMcpjsonPolicy(cwd: string, home: string): Promise<ClaudeMcpjsonPolicy> {
|
|
126
|
-
|
|
143
|
+
// Independent mode (lib/config-mode.ts) reads the same keys from One Code's
|
|
144
|
+
// user file, and only the tightening one from its per-repo file.
|
|
145
|
+
const claude = claudeSourcesOn();
|
|
146
|
+
const userScope: SettingsSource = claude ? "claude-user" : "onecode-user";
|
|
147
|
+
const localScope: SettingsSource = claude ? "project-local" : "onecode-project";
|
|
127
148
|
const policy: ClaudeMcpjsonPolicy = { enableAll: false, enabled: new Set(), disabled: new Set() };
|
|
128
|
-
// Deliberately not
|
|
149
|
+
// Deliberately not the project file: a checked-in settings.json granting
|
|
129
150
|
// enableAllProjectMcpServers would be the repo approving its own servers.
|
|
130
|
-
// The local file is
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
// servers (review H1).
|
|
134
|
-
const sources = [paths.user];
|
|
135
|
-
if (await localPolicyFileIsTrusted(cwd, paths.local)) sources.push(paths.local);
|
|
136
|
-
for (const path of sources) {
|
|
151
|
+
// The local file is in the checkout too, whatever git says about it.
|
|
152
|
+
for (const [source, path] of settingsSources(cwd, home)) {
|
|
153
|
+
if (source !== userScope && source !== localScope) continue;
|
|
137
154
|
const file = readSettingsFile(path);
|
|
138
155
|
if (!file) continue;
|
|
156
|
+
for (const name of stringArray(file.disabledMcpjsonServers)) policy.disabled.add(name);
|
|
157
|
+
if (source === localScope) continue;
|
|
139
158
|
if (typeof file.enableAllProjectMcpServers === "boolean") policy.enableAll = file.enableAllProjectMcpServers;
|
|
140
159
|
for (const name of stringArray(file.enabledMcpjsonServers)) policy.enabled.add(name);
|
|
141
|
-
for (const name of stringArray(file.disabledMcpjsonServers)) policy.disabled.add(name);
|
|
142
160
|
}
|
|
143
161
|
return policy;
|
|
144
162
|
}
|
|
@@ -182,25 +200,81 @@ export function persistEnableAll(projectRoot: string, storePath = approvalStoreP
|
|
|
182
200
|
writeStore(storePath, store);
|
|
183
201
|
}
|
|
184
202
|
|
|
203
|
+
/**
|
|
204
|
+
* Why `/mcp`'s Reconnect must not connect a server, or undefined. A server
|
|
205
|
+
* whose config references an unset variable is never connected (startup
|
|
206
|
+
* skips it and never asks for consent), so Reconnect must not either: it
|
|
207
|
+
* would spawn the command with the variable expanded to nothing, and a
|
|
208
|
+
* project server would run with no consent.
|
|
209
|
+
*/
|
|
210
|
+
export function reconnectRefusal(server: McpServer): string | undefined {
|
|
211
|
+
if (!server.missingEnv?.length) return undefined;
|
|
212
|
+
const names = server.missingEnv.join(", ");
|
|
213
|
+
return `"${server.name}" needs ${names} set in the environment. Set ${server.missingEnv.length === 1 ? "it" : "them"} and restart One Code.`;
|
|
214
|
+
}
|
|
215
|
+
|
|
185
216
|
export const CHOICE_ALL = "Use this and all future MCP servers in this project";
|
|
186
217
|
export const CHOICE_THIS = "Use this MCP server";
|
|
187
218
|
export const CHOICE_THESE = "Use these MCP servers";
|
|
188
219
|
export const CHOICE_NO = "No";
|
|
189
220
|
|
|
190
|
-
/** Claude Code's dialog title for one or several newly found servers. */
|
|
191
|
-
export function promptTitle(names: string[]): string {
|
|
221
|
+
/** Claude Code's dialog title for one or several newly found servers; `file` names where they were found. */
|
|
222
|
+
export function promptTitle(names: string[], file = ".mcp.json"): string {
|
|
192
223
|
return names.length === 1
|
|
193
|
-
? `New MCP server found in
|
|
194
|
-
: `${names.length} new MCP servers found in
|
|
224
|
+
? `New MCP server found in ${file}: ${escapeControlText(names[0])}`
|
|
225
|
+
: `${names.length} new MCP servers found in ${file}`;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Environment variables that change what a stdio server's command runs, or
|
|
230
|
+
* where it loads code from: an interpreter's preload and search paths, the
|
|
231
|
+
* dynamic loader's, `PATH`, and npm's config. Matched case-insensitively
|
|
232
|
+
* (Windows environment names are). The consent dialog shows these values in
|
|
233
|
+
* full, because `npx -y some-mcp` with `NODE_OPTIONS=--require ./x.js` is not
|
|
234
|
+
* the command it looks like.
|
|
235
|
+
*/
|
|
236
|
+
const EXECUTION_ENV = new Set([
|
|
237
|
+
"PATH",
|
|
238
|
+
"NODE_OPTIONS",
|
|
239
|
+
"NODE_PATH",
|
|
240
|
+
"LD_PRELOAD",
|
|
241
|
+
"LD_LIBRARY_PATH",
|
|
242
|
+
"LD_AUDIT",
|
|
243
|
+
"PYTHONPATH",
|
|
244
|
+
"PYTHONSTARTUP",
|
|
245
|
+
"PYTHONHOME",
|
|
246
|
+
"PERL5OPT",
|
|
247
|
+
"PERL5LIB",
|
|
248
|
+
"RUBYOPT",
|
|
249
|
+
"RUBYLIB",
|
|
250
|
+
"BASH_ENV",
|
|
251
|
+
"ENV",
|
|
252
|
+
"JAVA_TOOL_OPTIONS",
|
|
253
|
+
"_JAVA_OPTIONS",
|
|
254
|
+
"JDK_JAVA_OPTIONS",
|
|
255
|
+
"ELECTRON_RUN_AS_NODE",
|
|
256
|
+
"GIT_SSH_COMMAND",
|
|
257
|
+
"GIT_EXEC_PATH",
|
|
258
|
+
"COMSPEC",
|
|
259
|
+
"PATHEXT",
|
|
260
|
+
]);
|
|
261
|
+
const EXECUTION_ENV_PREFIXES = ["DYLD_", "NPM_CONFIG_"];
|
|
262
|
+
|
|
263
|
+
/** Whether an env key changes what a server's command executes (`EXECUTION_ENV`). */
|
|
264
|
+
export function changesExecution(key: string): boolean {
|
|
265
|
+
const upper = key.toUpperCase();
|
|
266
|
+
return EXECUTION_ENV.has(upper) || EXECUTION_ENV_PREFIXES.some((prefix) => upper.startsWith(prefix));
|
|
195
267
|
}
|
|
196
268
|
|
|
197
269
|
/**
|
|
198
270
|
* One line per server naming what would run, for the dialog body. Commands and
|
|
199
|
-
* URLs are shown in full (a truncated one hides where a padded attack lives)
|
|
200
|
-
* env
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
271
|
+
* URLs are shown in full (a truncated one hides where a padded attack lives).
|
|
272
|
+
* Every `env` key a stdio server sets is named; the values of the keys that
|
|
273
|
+
* change what executes (`changesExecution`) are shown in full, quoted, and the
|
|
274
|
+
* rest are not echoed, since they are usually credentials. The variable NAMES
|
|
275
|
+
* a server's command/args/env/headers reference are listed too (from
|
|
276
|
+
* `referencedEnv`, captured before expansion) — approving a URL should not
|
|
277
|
+
* silently ship a credential the header interpolates (review M5).
|
|
204
278
|
*/
|
|
205
279
|
export function describeServers(servers: McpServer[]): string {
|
|
206
280
|
const lines = servers.map((server) => {
|
|
@@ -210,14 +284,17 @@ export function describeServers(servers: McpServer[]): string {
|
|
|
210
284
|
: `${server.name}: ${server.url}`;
|
|
211
285
|
const vars = server.referencedEnv ?? [];
|
|
212
286
|
const headerNames = server.kind === "http" ? Object.keys(server.headers ?? {}) : [];
|
|
287
|
+
const env = server.kind === "stdio" ? Object.entries(server.env ?? {}) : [];
|
|
213
288
|
const notes = [
|
|
289
|
+
server.kind === "stdio" && server.cwd ? `cwd: ${server.cwd}` : "",
|
|
290
|
+
env.length ? `env: ${env.map(([key, value]) => (changesExecution(key) ? `${key}=${JSON.stringify(value)}` : key)).join(", ")}` : "",
|
|
214
291
|
vars.length ? `uses ${vars.map((v) => `$${v}`).join(", ")}` : "",
|
|
215
292
|
headerNames.length ? `headers: ${headerNames.join(", ")}` : "",
|
|
216
293
|
].filter(Boolean);
|
|
217
294
|
return notes.length ? `${what}\n (${notes.join("; ")})` : what;
|
|
218
295
|
});
|
|
219
296
|
// Bound the modal: a very long command/url or many servers cannot flood it.
|
|
220
|
-
return boundConsentItems(lines,
|
|
297
|
+
return boundConsentItems(lines, `review ${configLabels(servers)} before approving`);
|
|
221
298
|
}
|
|
222
299
|
|
|
223
300
|
export interface McpTrustDeps {
|
|
@@ -237,8 +314,14 @@ export interface McpTrustOutcome {
|
|
|
237
314
|
withheld: { server: McpServer; reason: "declined" | "not-approved" | "disabled-by-claude-settings" }[];
|
|
238
315
|
}
|
|
239
316
|
|
|
240
|
-
/**
|
|
241
|
-
|
|
317
|
+
/**
|
|
318
|
+
* Process-lifetime memory per project+server+hash, so /clear (a new
|
|
319
|
+
* session_start) and /reload do not re-ask a "No". Process state
|
|
320
|
+
* (lib/process-state.ts), not module scope: pi evaluates this module again
|
|
321
|
+
* at `/reload` and at a `/resume` into another directory (lifecycle grid
|
|
322
|
+
* R3-L13).
|
|
323
|
+
*/
|
|
324
|
+
const sessionDecisions = () => processState("mcp:trust-decisions", () => new Map<string, boolean>());
|
|
242
325
|
const pendingPrompts = new Map<string, Promise<string | undefined>>();
|
|
243
326
|
|
|
244
327
|
/**
|
|
@@ -255,9 +338,8 @@ export async function approveMcpServers(
|
|
|
255
338
|
const approved: McpServer[] = [];
|
|
256
339
|
const withheld: McpTrustOutcome["withheld"] = [];
|
|
257
340
|
const pending: McpServer[] = [];
|
|
258
|
-
// Reading CC's policy
|
|
259
|
-
//
|
|
260
|
-
// user-scope or plugin servers must not pay a git spawn at connect.
|
|
341
|
+
// Reading CC's policy reads two settings files, so only do it when a
|
|
342
|
+
// server actually needs consent.
|
|
261
343
|
const anyProjectScoped = servers.some((s) => isProjectScopedServer(s, pluginConfigPaths));
|
|
262
344
|
const claude: ClaudeMcpjsonPolicy = anyProjectScoped
|
|
263
345
|
? await readClaudeMcpjsonPolicy(cwd, home)
|
|
@@ -272,7 +354,12 @@ export async function approveMcpServers(
|
|
|
272
354
|
withheld.push({ server, reason: "disabled-by-claude-settings" });
|
|
273
355
|
continue;
|
|
274
356
|
}
|
|
275
|
-
|
|
357
|
+
// Claude Code's own answers approve `.mcp.json` servers only. A server
|
|
358
|
+
// DEFINED in settings.local.json must never be approved by that same
|
|
359
|
+
// file's `enableAllProjectMcpServers` (SECURITY-REVIEW-2026-09-23 H4), and
|
|
360
|
+
// one from pi's `.pi/mcp.json` is not a file those answers were about: both
|
|
361
|
+
// go through One Code's hash-keyed consent below, like any other.
|
|
362
|
+
if (definedInMcpjson(server) && (claude.enableAll || claude.enabled.has(server.name))) {
|
|
276
363
|
approved.push(server);
|
|
277
364
|
continue;
|
|
278
365
|
}
|
|
@@ -283,7 +370,7 @@ export async function approveMcpServers(
|
|
|
283
370
|
approved.push(server);
|
|
284
371
|
continue;
|
|
285
372
|
}
|
|
286
|
-
const remembered = sessionDecisions.get(`${root}:${server.name}:${hash}`);
|
|
373
|
+
const remembered = sessionDecisions().get(`${root}:${server.name}:${hash}`);
|
|
287
374
|
if (remembered === true) approved.push(server);
|
|
288
375
|
else if (remembered === false) withheld.push({ server, reason: "declined" });
|
|
289
376
|
else pending.push(server);
|
|
@@ -293,8 +380,12 @@ export async function approveMcpServers(
|
|
|
293
380
|
|
|
294
381
|
if (!deps.hasUI) {
|
|
295
382
|
for (const server of pending) withheld.push({ server, reason: "not-approved" });
|
|
383
|
+
// enabledMcpjsonServers approves `.mcp.json` servers only (above), so the
|
|
384
|
+
// hint names it only when one of those is waiting.
|
|
385
|
+
const fromMcpjson = pending.some(definedInMcpjson);
|
|
386
|
+
const sources = configLabels(pending);
|
|
296
387
|
deps.notify(
|
|
297
|
-
`Skipped ${pending.length} MCP server${pending.length === 1 ? "" : "s"} from
|
|
388
|
+
`Skipped ${pending.length} MCP server${pending.length === 1 ? "" : "s"} from ${sources} (${pending.map((s) => s.name).join(", ")}): not yet approved and no UI to ask. Approve once in an interactive session${fromMcpjson ? ", or set enabledMcpjsonServers in ~/.claude/settings.json" : ""}.`,
|
|
298
389
|
);
|
|
299
390
|
return { approved, withheld };
|
|
300
391
|
}
|
|
@@ -306,7 +397,7 @@ export async function approveMcpServers(
|
|
|
306
397
|
if (!prompt) {
|
|
307
398
|
const useLabel = pending.length === 1 ? CHOICE_THIS : CHOICE_THESE;
|
|
308
399
|
prompt = deps
|
|
309
|
-
.select(`${promptTitle(names)}\n\n${describeServers(pending)}\n\nThese run on your machine.`, [CHOICE_ALL, useLabel, CHOICE_NO])
|
|
400
|
+
.select(`${promptTitle(names, configLabels(pending))}\n\n${describeServers(pending)}\n\nThese run on your machine.`, [CHOICE_ALL, useLabel, CHOICE_NO])
|
|
310
401
|
.finally(() => pendingPrompts.delete(key));
|
|
311
402
|
pendingPrompts.set(key, prompt);
|
|
312
403
|
}
|
|
@@ -316,25 +407,25 @@ export async function approveMcpServers(
|
|
|
316
407
|
const root = projectRootOf(server);
|
|
317
408
|
const decisionKey = `${root}:${server.name}:${hashServerConfig(server)}`;
|
|
318
409
|
if (choice === CHOICE_ALL || choice === CHOICE_THIS || choice === CHOICE_THESE) {
|
|
319
|
-
sessionDecisions.set(decisionKey, true);
|
|
410
|
+
sessionDecisions().set(decisionKey, true);
|
|
320
411
|
if (choice === CHOICE_ALL) persistEnableAll(root, deps.storePath);
|
|
321
412
|
persistApproval(root, server, deps.storePath);
|
|
322
413
|
approved.push(server);
|
|
323
414
|
} else {
|
|
324
|
-
sessionDecisions.set(decisionKey, false);
|
|
415
|
+
sessionDecisions().set(decisionKey, false);
|
|
325
416
|
withheld.push({ server, reason: "declined" });
|
|
326
417
|
// An explicit "No" is remembered as a disable; Escape is this session only.
|
|
327
418
|
if (choice === CHOICE_NO) deps.disable(server);
|
|
328
419
|
}
|
|
329
420
|
}
|
|
330
421
|
if (choice !== CHOICE_ALL && choice !== CHOICE_THIS && choice !== CHOICE_THESE) {
|
|
331
|
-
deps.notify(`MCP server${pending.length === 1 ? "" : "s"} from
|
|
422
|
+
deps.notify(`MCP server${pending.length === 1 ? "" : "s"} from ${configLabels(pending)} not connected (${names.join(", ")}); enable in /mcp.`);
|
|
332
423
|
}
|
|
333
424
|
return { approved, withheld };
|
|
334
425
|
}
|
|
335
426
|
|
|
336
427
|
/** Test seam. */
|
|
337
428
|
export function resetMcpTrustSessionState(): void {
|
|
338
|
-
sessionDecisions.clear();
|
|
429
|
+
sessionDecisions().clear();
|
|
339
430
|
pendingPrompts.clear();
|
|
340
431
|
}
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
ONECODE_DESCRIPTOR,
|
|
25
25
|
ONECODE_GLOBAL_DESCRIPTOR,
|
|
26
26
|
PROJECT_DESCRIPTOR,
|
|
27
|
+
instructionRule,
|
|
27
28
|
} from "../lib/claude-context.ts";
|
|
28
29
|
import { forwardSlashes, isRelativeInside, tildify } from "../lib/paths.ts";
|
|
29
30
|
import { tryReadFile } from "../lib/plugins.ts";
|
|
@@ -69,12 +70,16 @@ export function buildMemoryEntries(opts: {
|
|
|
69
70
|
home: string;
|
|
70
71
|
homeClaudeDir: string;
|
|
71
72
|
homeOneCodeDir: string;
|
|
72
|
-
|
|
73
|
+
/** The auto-memory folder; undefined while auto-memory is off (no folder row, as in Claude Code). */
|
|
74
|
+
memoryDir: string | undefined;
|
|
73
75
|
}): MemoryEntry[] {
|
|
74
76
|
const { cwd, home, homeClaudeDir, homeOneCodeDir, memoryDir } = opts;
|
|
75
|
-
//
|
|
76
|
-
|
|
77
|
-
|
|
77
|
+
// The same rule the # claudeMd block uses, so the list matches what it sends.
|
|
78
|
+
const rule = instructionRule(home);
|
|
79
|
+
// Independent mode (lib/config-mode.ts) reads no CLAUDE.md: its always-offered
|
|
80
|
+
// files are the global ONECODE.md and the project's AGENTS.md instead.
|
|
81
|
+
const independent = rule === "agents-md";
|
|
82
|
+
const discovered = discoverContextFilePaths({ cwd, homeClaudeDir, homeOneCodeDir, rule });
|
|
78
83
|
const referenced = referencedImports(discovered, home);
|
|
79
84
|
// (descriptor, dir) → the discovered path, so per-dir lookups reuse the real
|
|
80
85
|
// on-disk casing discovery already resolved (no second stat/readdir here).
|
|
@@ -91,15 +96,15 @@ export function buildMemoryEntries(opts: {
|
|
|
91
96
|
const disp = (path: string) => displayPath(path, cwd, home);
|
|
92
97
|
|
|
93
98
|
// Global user instructions — always offered, matching CC (created on save).
|
|
94
|
-
const
|
|
99
|
+
const globalOneCode = found.get(`${ONECODE_GLOBAL_DESCRIPTOR}\0${homeOneCodeDir}`);
|
|
100
|
+
const globalUser = independent ? (globalOneCode ?? join(homeOneCodeDir, "ONECODE.md")) : join(homeClaudeDir, "CLAUDE.md");
|
|
95
101
|
add({
|
|
96
102
|
title: "User instructions",
|
|
97
|
-
description: `Saved in ${disp(
|
|
98
|
-
path:
|
|
103
|
+
description: `Saved in ${disp(globalUser)}`,
|
|
104
|
+
path: globalUser,
|
|
99
105
|
kind: "file",
|
|
100
|
-
exists: found.has(`${GLOBAL_DESCRIPTOR}\0${homeClaudeDir}`),
|
|
106
|
+
exists: independent ? globalOneCode !== undefined : found.has(`${GLOBAL_DESCRIPTOR}\0${homeClaudeDir}`),
|
|
101
107
|
});
|
|
102
|
-
const globalOneCode = found.get(`${ONECODE_GLOBAL_DESCRIPTOR}\0${homeOneCodeDir}`);
|
|
103
108
|
if (globalOneCode) {
|
|
104
109
|
add({
|
|
105
110
|
title: "One Code user instructions",
|
|
@@ -114,13 +119,14 @@ export function buildMemoryEntries(opts: {
|
|
|
114
119
|
const isCwd = d === cwd;
|
|
115
120
|
const claude = join(d, "CLAUDE.md");
|
|
116
121
|
if (isCwd) {
|
|
117
|
-
// Project instructions — always offered (created on save).
|
|
122
|
+
// Project instructions — always offered (created on save): AGENTS.md in independent mode.
|
|
123
|
+
const [name, descriptor] = independent ? ["AGENTS.md", AGENTS_DESCRIPTOR] : ["CLAUDE.md", PROJECT_DESCRIPTOR];
|
|
118
124
|
add({
|
|
119
125
|
title: "Project instructions",
|
|
120
|
-
description: `Checked in at ${disp(
|
|
121
|
-
path:
|
|
126
|
+
description: `Checked in at ${disp(join(d, name))}`,
|
|
127
|
+
path: join(d, name),
|
|
122
128
|
kind: "file",
|
|
123
|
-
exists: found.has(`${
|
|
129
|
+
exists: found.has(`${descriptor}\0${d}`),
|
|
124
130
|
});
|
|
125
131
|
} else if (found.has(`${PROJECT_DESCRIPTOR}\0${d}`)) {
|
|
126
132
|
add({ title: disp(claude), path: claude, kind: "file", exists: true });
|
|
@@ -143,6 +149,9 @@ export function buildMemoryEntries(opts: {
|
|
|
143
149
|
exists: true,
|
|
144
150
|
});
|
|
145
151
|
}
|
|
152
|
+
// `.claude/AGENTS.md`, which the AGENTS.md fallback loads too.
|
|
153
|
+
const dotClaudeAgents = found.get(`${AGENTS_DESCRIPTOR}\0${join(d, ".claude")}`);
|
|
154
|
+
if (dotClaudeAgents) add({ title: disp(dotClaudeAgents), path: dotClaudeAgents, kind: "file", exists: true });
|
|
146
155
|
|
|
147
156
|
const oneCode = found.get(`${ONECODE_DESCRIPTOR}\0${d}`);
|
|
148
157
|
if (oneCode) {
|
|
@@ -156,7 +165,7 @@ export function buildMemoryEntries(opts: {
|
|
|
156
165
|
}
|
|
157
166
|
}
|
|
158
167
|
|
|
159
|
-
add({ title: "Open auto-memory folder", path: memoryDir, kind: "folder", exists: true });
|
|
168
|
+
if (memoryDir) add({ title: "Open auto-memory folder", path: memoryDir, kind: "folder", exists: true });
|
|
160
169
|
return entries;
|
|
161
170
|
}
|
|
162
171
|
|