agent-trellis 0.7.0 → 0.8.2
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 +48 -153
- package/dist/adapters/claude-code.js +3 -2
- package/dist/adapters/codex.js +3 -2
- package/dist/adapters/jsonMcp.d.ts +3 -1
- package/dist/adapters/jsonMcp.js +18 -4
- package/dist/adapters/kimi-code.d.ts +21 -0
- package/dist/adapters/kimi-code.js +107 -0
- package/dist/adapters/kiro.js +3 -2
- package/dist/adapters/mcpPlan.d.ts +6 -1
- package/dist/adapters/mcpPlan.js +106 -8
- package/dist/adapters/pi.js +22 -3
- package/dist/adapters/symlinkPlan.d.ts +7 -0
- package/dist/adapters/symlinkPlan.js +16 -7
- package/dist/adapters/zcode.d.ts +21 -0
- package/dist/adapters/zcode.js +234 -0
- package/dist/cli.js +145 -29
- package/dist/commands/doctor.d.ts +7 -2
- package/dist/commands/doctor.js +40 -2
- package/dist/commands/init.d.ts +4 -2
- package/dist/commands/init.js +29 -13
- package/dist/commands/kimi.d.ts +16 -0
- package/dist/commands/kimi.js +64 -0
- package/dist/commands/manage.d.ts +39 -0
- package/dist/commands/manage.js +126 -0
- package/dist/commands/mcp.d.ts +77 -14
- package/dist/commands/mcp.js +169 -29
- package/dist/commands/mcpGateway.d.ts +6 -0
- package/dist/commands/mcpGateway.js +35 -14
- package/dist/commands/mcpImport.d.ts +46 -0
- package/dist/commands/mcpImport.js +359 -0
- package/dist/commands/memory.d.ts +17 -3
- package/dist/commands/memory.js +27 -8
- package/dist/commands/migrate.d.ts +16 -5
- package/dist/commands/migrate.js +93 -17
- package/dist/commands/onboard.d.ts +74 -2
- package/dist/commands/onboard.js +469 -71
- package/dist/commands/rollback.js +28 -2
- package/dist/commands/secretsAudit.js +4 -1
- package/dist/commands/skill.d.ts +52 -6
- package/dist/commands/skill.js +114 -15
- package/dist/commands/sync.js +5 -1
- package/dist/core/adapter.d.ts +11 -1
- package/dist/core/canonical.d.ts +15 -7
- package/dist/core/canonical.js +101 -13
- package/dist/core/capabilitySelection.d.ts +45 -0
- package/dist/core/capabilitySelection.js +124 -0
- package/dist/core/types.d.ts +25 -2
- package/dist/core/types.js +8 -0
- package/dist/lib/agentBridge.d.ts +169 -0
- package/dist/lib/agentBridge.js +367 -0
- package/dist/lib/agentBridgeProvider.d.ts +14 -0
- package/dist/lib/agentBridgeProvider.js +95 -0
- package/dist/lib/backup.d.ts +32 -0
- package/dist/lib/backup.js +20 -1
- package/dist/lib/builtinSkills.d.ts +2 -0
- package/dist/lib/builtinSkills.js +4 -0
- package/dist/lib/chatAgents.d.ts +42 -0
- package/dist/lib/chatAgents.js +59 -0
- package/dist/lib/cliMetadata.d.ts +1 -0
- package/dist/lib/cliMetadata.js +14 -0
- package/dist/lib/envVarNames.d.ts +3 -0
- package/dist/lib/envVarNames.js +19 -0
- package/dist/lib/gatewayBackend.d.ts +28 -0
- package/dist/lib/gatewayBackend.js +72 -1
- package/dist/lib/installAgent.d.ts +7 -5
- package/dist/lib/installAgent.js +4 -3
- package/dist/lib/mcpConnect.js +5 -1
- package/dist/lib/mcpMigrateRead.d.ts +2 -0
- package/dist/lib/mcpMigrateRead.js +22 -1
- package/dist/lib/mcpRuntime.d.ts +46 -0
- package/dist/lib/mcpRuntime.js +185 -0
- package/dist/lib/mcpStatusProvider.d.ts +10 -0
- package/dist/lib/mcpStatusProvider.js +25 -0
- package/dist/lib/mcpToolRegistry.d.ts +18 -0
- package/dist/lib/mcpToolRegistry.js +107 -14
- package/dist/lib/memoryGraph.d.ts +1 -1
- package/dist/lib/memoryGraph.js +9 -3
- package/dist/lib/memoryProvider.d.ts +58 -0
- package/dist/lib/memoryProvider.js +175 -0
- package/dist/lib/memoryStatus.d.ts +17 -0
- package/dist/lib/memoryStatus.js +88 -0
- package/dist/lib/nativeMemory.d.ts +19 -0
- package/dist/lib/nativeMemory.js +129 -0
- package/dist/lib/realHomeSnapshot.js +5 -0
- package/dist/lib/runtimeControlProvider.d.ts +16 -0
- package/dist/lib/runtimeControlProvider.js +170 -0
- package/dist/lib/secretEnv.d.ts +2 -1
- package/dist/lib/secretEnv.js +6 -2
- package/dist/lib/skillProvider.d.ts +13 -0
- package/dist/lib/skillProvider.js +210 -0
- package/dist/lib/taskProvider.d.ts +7 -0
- package/dist/lib/taskProvider.js +43 -0
- package/dist/lib/taskStore.d.ts +46 -0
- package/dist/lib/taskStore.js +156 -0
- package/dist/lib/terminalPicker.d.ts +23 -49
- package/dist/lib/terminalPicker.js +80 -218
- package/dist/lib/zcodeOwnership.d.ts +17 -0
- package/dist/lib/zcodeOwnership.js +37 -0
- package/dist/pi-bridge/bundle.js +476 -37
- package/dist/pi-bridge/index.js +42 -21
- package/dist/pi-bridge/schemaTranslate.d.ts +4 -8
- package/dist/pi-bridge/schemaTranslate.js +4 -8
- package/dist/probes/codex.d.ts +7 -0
- package/dist/probes/codex.js +37 -5
- package/dist/probes/kimi-code.d.ts +12 -0
- package/dist/probes/kimi-code.js +55 -0
- package/dist/probes/zcode.d.ts +32 -0
- package/dist/probes/zcode.js +140 -0
- package/dist/sdk.d.ts +1 -1
- package/docs/architecture.md +230 -28
- package/docs/assets/brand-v3/trellis-mark-v3-a.png +0 -0
- package/docs/assets/brand-v3/trellis-mark-v3-a.svg +10 -0
- package/docs/assets/poster-series-v3/README.md +60 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-horizontal-en.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-horizontal-en.svg +51 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-horizontal-zh.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-horizontal-zh.svg +51 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-memory-en.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-memory-en.svg +48 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-memory-zh.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-memory-zh.svg +48 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-migrate-en.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-migrate-en.svg +56 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-migrate-zh.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-migrate-zh.svg +56 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-switch-en.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-switch-en.svg +47 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-switch-zh.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-switch-zh.svg +47 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-unified-en.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-unified-en.svg +51 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-unified-zh.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-unified-zh.svg +51 -0
- package/docs/getting-started.md +496 -42
- package/docs/overview.md +134 -0
- package/docs/overview.zh-CN.md +102 -0
- package/docs/research.md +59 -0
- package/docs/roadmap.md +11 -6
- package/docs/video/README.md +76 -0
- package/docs/video/build/audio/01-opening.aiff +0 -0
- package/docs/video/build/audio/01-opening.mp3 +0 -0
- package/docs/video/build/audio/02-pain.aiff +0 -0
- package/docs/video/build/audio/02-pain.mp3 +0 -0
- package/docs/video/build/audio/03-solution.aiff +0 -0
- package/docs/video/build/audio/03-solution.mp3 +0 -0
- package/docs/video/build/audio/04-install.aiff +0 -0
- package/docs/video/build/audio/04-install.mp3 +0 -0
- package/docs/video/build/audio/04-setup.mp3 +0 -0
- package/docs/video/build/audio/05-dryrun.mp3 +0 -0
- package/docs/video/build/audio/05-init.aiff +0 -0
- package/docs/video/build/audio/05-init.mp3 +0 -0
- package/docs/video/build/audio/05-interactive.mp3 +0 -0
- package/docs/video/build/audio/06-dryrun.aiff +0 -0
- package/docs/video/build/audio/06-dryrun.mp3 +0 -0
- package/docs/video/build/audio/06-onboard.mp3 +0 -0
- package/docs/video/build/audio/06-run.mp3 +0 -0
- package/docs/video/build/audio/07-onboard.aiff +0 -0
- package/docs/video/build/audio/07-onboard.mp3 +0 -0
- package/docs/video/build/audio/07-verify.mp3 +0 -0
- package/docs/video/build/audio/08-closing.mp3 +0 -0
- package/docs/video/build/audio/08-doctor.aiff +0 -0
- package/docs/video/build/audio/08-doctor.mp3 +0 -0
- package/docs/video/build/audio/09-rollback.aiff +0 -0
- package/docs/video/build/audio/09-rollback.mp3 +0 -0
- package/docs/video/build/audio/10-principles.aiff +0 -0
- package/docs/video/build/audio/10-principles.mp3 +0 -0
- package/docs/video/build/audio/11-closing.aiff +0 -0
- package/docs/video/build/audio/11-closing.mp3 +0 -0
- package/docs/video/build/frames/01-opening-0.png +0 -0
- package/docs/video/build/frames/02-pain-1.png +0 -0
- package/docs/video/build/frames/02-pain-2.png +0 -0
- package/docs/video/build/frames/03-solution-3.png +0 -0
- package/docs/video/build/frames/04-install-4.png +0 -0
- package/docs/video/build/frames/04-setup-4.png +0 -0
- package/docs/video/build/frames/04-setup-5.png +0 -0
- package/docs/video/build/frames/05-dryrun-6.png +0 -0
- package/docs/video/build/frames/05-init-5.png +0 -0
- package/docs/video/build/frames/05-interactive-5.png +0 -0
- package/docs/video/build/frames/05-interactive-6.png +0 -0
- package/docs/video/build/frames/06-dryrun-6.png +0 -0
- package/docs/video/build/frames/06-dryrun-7.png +0 -0
- package/docs/video/build/frames/06-onboard-7.png +0 -0
- package/docs/video/build/frames/06-onboard-8.png +0 -0
- package/docs/video/build/frames/06-run-7.png +0 -0
- package/docs/video/build/frames/06-run-8.png +0 -0
- package/docs/video/build/frames/07-onboard-10.png +0 -0
- package/docs/video/build/frames/07-onboard-7.png +0 -0
- package/docs/video/build/frames/07-onboard-8.png +0 -0
- package/docs/video/build/frames/07-onboard-9.png +0 -0
- package/docs/video/build/frames/07-verify-10.png +0 -0
- package/docs/video/build/frames/07-verify-8.png +0 -0
- package/docs/video/build/frames/07-verify-9.png +0 -0
- package/docs/video/build/frames/08-closing-10.png +0 -0
- package/docs/video/build/frames/08-closing-11.png +0 -0
- package/docs/video/build/frames/08-doctor-11.png +0 -0
- package/docs/video/build/frames/08-doctor-9.png +0 -0
- package/docs/video/build/frames/09-rollback-10.png +0 -0
- package/docs/video/build/frames/09-rollback-12.png +0 -0
- package/docs/video/build/frames/10-principles-11.png +0 -0
- package/docs/video/build/frames/10-principles-13.png +0 -0
- package/docs/video/build/frames/11-closing-12.png +0 -0
- package/docs/video/build/frames/11-closing-14.png +0 -0
- package/docs/video/build/segments/01-opening.mp4 +0 -0
- package/docs/video/build/segments/01-opening.txt +3 -0
- package/docs/video/build/segments/02-pain.mp4 +0 -0
- package/docs/video/build/segments/02-pain.txt +5 -0
- package/docs/video/build/segments/03-solution.mp4 +0 -0
- package/docs/video/build/segments/03-solution.txt +3 -0
- package/docs/video/build/segments/04-install.mp4 +0 -0
- package/docs/video/build/segments/04-install.txt +3 -0
- package/docs/video/build/segments/04-setup.mp4 +0 -0
- package/docs/video/build/segments/04-setup.txt +3 -0
- package/docs/video/build/segments/05-dryrun.mp4 +0 -0
- package/docs/video/build/segments/05-dryrun.txt +3 -0
- package/docs/video/build/segments/05-init.mp4 +0 -0
- package/docs/video/build/segments/05-init.txt +3 -0
- package/docs/video/build/segments/05-interactive.mp4 +0 -0
- package/docs/video/build/segments/05-interactive.txt +5 -0
- package/docs/video/build/segments/06-dryrun.mp4 +0 -0
- package/docs/video/build/segments/06-dryrun.txt +3 -0
- package/docs/video/build/segments/06-onboard.mp4 +0 -0
- package/docs/video/build/segments/06-onboard.txt +5 -0
- package/docs/video/build/segments/06-run.mp4 +0 -0
- package/docs/video/build/segments/06-run.txt +3 -0
- package/docs/video/build/segments/07-onboard.mp4 +0 -0
- package/docs/video/build/segments/07-onboard.txt +5 -0
- package/docs/video/build/segments/07-verify.mp4 +0 -0
- package/docs/video/build/segments/07-verify.txt +5 -0
- package/docs/video/build/segments/08-closing.mp4 +0 -0
- package/docs/video/build/segments/08-closing.txt +3 -0
- package/docs/video/build/segments/08-doctor.mp4 +0 -0
- package/docs/video/build/segments/08-doctor.txt +3 -0
- package/docs/video/build/segments/09-rollback.mp4 +0 -0
- package/docs/video/build/segments/09-rollback.txt +3 -0
- package/docs/video/build/segments/10-principles.mp4 +0 -0
- package/docs/video/build/segments/10-principles.txt +3 -0
- package/docs/video/build/segments/11-closing.mp4 +0 -0
- package/docs/video/build/segments/11-closing.txt +3 -0
- package/docs/video/build/segments/final.txt +8 -0
- package/docs/video/build-ai/audio/01-hook.mp3 +0 -0
- package/docs/video/build-ai/audio/02-pain.mp3 +0 -0
- package/docs/video/build-ai/audio/03-solution.mp3 +0 -0
- package/docs/video/build-ai/audio/04-how.mp3 +0 -0
- package/docs/video/build-ai/audio/05-safe.mp3 +0 -0
- package/docs/video/build-ai/audio/06-closing.mp3 +0 -0
- package/docs/video/build-ai/clips/01-hook.mp4 +0 -0
- package/docs/video/build-ai/clips/02-pain.mp4 +0 -0
- package/docs/video/build-ai/clips/03-solution.mp4 +0 -0
- package/docs/video/build-ai/clips/04-how.mp4 +0 -0
- package/docs/video/build-ai/clips/05-safe.mp4 +0 -0
- package/docs/video/build-ai/clips/06-closing.mp4 +0 -0
- package/docs/video/build-ai/first-frame-02-pain.png +0 -0
- package/docs/video/build-ai/first-frame-03-solution.png +0 -0
- package/docs/video/build-ai/first-frame-04-how.png +0 -0
- package/docs/video/build-ai/first-frame-05-safe.png +0 -0
- package/docs/video/build-ai/segments/01-hook.caption.txt +2 -0
- package/docs/video/build-ai/segments/01-hook.mp4 +0 -0
- package/docs/video/build-ai/segments/02-pain.mp4 +0 -0
- package/docs/video/build-ai/segments/03-solution.mp4 +0 -0
- package/docs/video/build-ai/segments/04-how.mp4 +0 -0
- package/docs/video/build-ai/segments/05-safe.mp4 +0 -0
- package/docs/video/build-ai/segments/06-closing.mp4 +0 -0
- package/docs/video/build-ai/segments/cap-01-hook.png +0 -0
- package/docs/video/build-ai/segments/cap-02-pain.png +0 -0
- package/docs/video/build-ai/segments/cap-03-solution.png +0 -0
- package/docs/video/build-ai/segments/cap-04-how.png +0 -0
- package/docs/video/build-ai/segments/cap-05-safe.png +0 -0
- package/docs/video/build-ai/segments/cap-06-closing.png +0 -0
- package/docs/video/build-ai/segments/final.txt +6 -0
- package/docs/video/build-posters/audio/01-hook.mp3 +0 -0
- package/docs/video/build-posters/audio/02-pain.mp3 +0 -0
- package/docs/video/build-posters/audio/03-solution.mp3 +0 -0
- package/docs/video/build-posters/audio/04-how.mp3 +0 -0
- package/docs/video/build-posters/audio/05-safe.mp3 +0 -0
- package/docs/video/build-posters/audio/06-closing.mp3 +0 -0
- package/docs/video/build-posters/cap-01-hook.png +0 -0
- package/docs/video/build-posters/cap-02-pain.png +0 -0
- package/docs/video/build-posters/cap-03-solution.png +0 -0
- package/docs/video/build-posters/cap-04-how.png +0 -0
- package/docs/video/build-posters/cap-05-safe.png +0 -0
- package/docs/video/build-posters/cap-06-closing.png +0 -0
- package/docs/video/build-posters/card-01-hook.png +0 -0
- package/docs/video/build-posters/card-06-closing.png +0 -0
- package/docs/video/build-posters/segments/01-hook.mp4 +0 -0
- package/docs/video/build-posters/segments/02-pain.mp4 +0 -0
- package/docs/video/build-posters/segments/03-solution.mp4 +0 -0
- package/docs/video/build-posters/segments/04-how.mp4 +0 -0
- package/docs/video/build-posters/segments/05-safe.mp4 +0 -0
- package/docs/video/build-posters/segments/06-closing.mp4 +0 -0
- package/docs/video/build-posters/segments/final.txt +6 -0
- package/docs/video/generate-video-ai.mjs +334 -0
- package/docs/video/generate-video-posters.mjs +204 -0
- package/docs/video/generate-video.mjs +426 -0
- package/docs/video/outline.zh-CN.md +102 -0
- package/docs/video/trellis-demo-video-ai.mp4 +0 -0
- package/docs/video/trellis-demo-video.mp4 +0 -0
- package/docs/video/voiceover.zh-CN.md +49 -0
- package/package.json +6 -2
- package/schema/builtin-skills/trellis-runtime/SKILL.md +117 -0
- package/schema/capability-selection.example.yaml +23 -0
- package/schema/scope.example.yaml +1 -1
- package/schema/servers.example.yaml +15 -1
package/dist/cli.js
CHANGED
|
@@ -9,22 +9,33 @@ import { runInit } from "./commands/init.js";
|
|
|
9
9
|
import { runMigrate } from "./commands/migrate.js";
|
|
10
10
|
import { runOnboard } from "./commands/onboard.js";
|
|
11
11
|
import { runSync } from "./commands/sync.js";
|
|
12
|
-
import { runMcpSync, runMcpList, runMcpAdd, runMcpRemove, parseMcpAddArgs } from "./commands/mcp.js";
|
|
13
|
-
import {
|
|
12
|
+
import { runMcpSync, runMcpList, runMcpAdd, runMcpRemove, runMcpSetAuth, parseMcpAddArgs } from "./commands/mcp.js";
|
|
13
|
+
import { runMcpImport } from "./commands/mcpImport.js";
|
|
14
|
+
import { parseMcpGatewayArgs, runMcpGateway, runMcpRuntime } from "./commands/mcpGateway.js";
|
|
14
15
|
import { runMcpAuth } from "./commands/mcpAuth.js";
|
|
15
16
|
import { runSecretsAudit } from "./commands/secretsAudit.js";
|
|
16
17
|
import { runRollback } from "./commands/rollback.js";
|
|
17
|
-
import { runSkillList, runSkillAdd, runSkillRemove } from "./commands/skill.js";
|
|
18
|
-
import { runMemoryExtraction, runMemorySync } from "./commands/memory.js";
|
|
18
|
+
import { runSkillList, runSkillAdd, runSkillRemove, runSkillUpdateBuiltin } from "./commands/skill.js";
|
|
19
|
+
import { collectMemoryList, runMemoryExtraction, runMemorySync } from "./commands/memory.js";
|
|
20
|
+
import { parseManageArgs, runManage } from "./commands/manage.js";
|
|
21
|
+
import { runKimi } from "./commands/kimi.js";
|
|
22
|
+
import { TRELLIS_VERSION } from "./lib/cliMetadata.js";
|
|
19
23
|
import { parseSyncArgs } from "./lib/syncArgs.js";
|
|
20
|
-
const KNOWN_COMMANDS = ["onboard", "init", "migrate", "doctor", "sync", "mcp", "mcp-gateway", "skill", "memory", "secrets", "rollback"];
|
|
24
|
+
const KNOWN_COMMANDS = ["onboard", "init", "migrate", "doctor", "sync", "mcp", "mcp-gateway", "mcp-runtime", "skill", "memory", "manage", "kimi", "secrets", "rollback"];
|
|
21
25
|
function printUsage() {
|
|
22
26
|
console.log(`trellis - a single source of capability for every coding agent
|
|
23
27
|
|
|
24
28
|
Usage:
|
|
25
29
|
trellis <command>
|
|
30
|
+
trellis --version
|
|
31
|
+
trellis --help
|
|
32
|
+
|
|
33
|
+
Options:
|
|
34
|
+
-v, --version print the installed Trellis version
|
|
35
|
+
-h, --help show this help
|
|
26
36
|
|
|
27
37
|
Commands:
|
|
38
|
+
help Show this help
|
|
28
39
|
onboard Guided flow: init -> detect agents -> pick a migration source ->
|
|
29
40
|
pick which agents to manage -> migrate -> sync -> mcp sync ->
|
|
30
41
|
secrets audit, in one command. Source (read from) and managed
|
|
@@ -39,15 +50,21 @@ Commands:
|
|
|
39
50
|
(required with no terminal to prompt
|
|
40
51
|
in, e.g. --json)
|
|
41
52
|
--mcp-mode <direct|hub|gateway>
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
--hub-url <url> required with --mcp-mode hub
|
|
53
|
+
direct = Agent 分别直连;gateway =
|
|
54
|
+
Trellis 本机统一托管(推荐);hub =
|
|
55
|
+
连接已有的外部 MCP Hub
|
|
56
|
+
--hub-url <url> required with --mcp-mode hub; Trellis
|
|
57
|
+
does not deploy an external Hub
|
|
46
58
|
--gateway-agents <ids>
|
|
47
59
|
optional with --mcp-mode gateway;
|
|
48
60
|
omit for every managed agent
|
|
49
61
|
--memory <on|off> enable/disable the shared memory MCP
|
|
50
62
|
server; omit to leave it untouched
|
|
63
|
+
--memory-migrate <on|off>
|
|
64
|
+
import supported native Agent memory into
|
|
65
|
+
canonical; omit to leave it untouched
|
|
66
|
+
--selection <file> item-level YAML/JSON selection for skills,
|
|
67
|
+
MCP servers, memories, and per-agent routes
|
|
51
68
|
--dry-run preview the whole flow, write nothing
|
|
52
69
|
--json machine-readable output, no report text
|
|
53
70
|
init Create ~/.trellis/ with a minimal valid skeleton if missing
|
|
@@ -55,12 +72,13 @@ Commands:
|
|
|
55
72
|
missing) and prints which agents are present
|
|
56
73
|
--json machine-readable output, no report text
|
|
57
74
|
migrate --from <agent>
|
|
58
|
-
Import an existing agent's real skills/instructions/MCP
|
|
75
|
+
Import an existing agent's real skills/instructions/MCP/memory
|
|
59
76
|
servers into canonical source (claude-code | codex | kiro |
|
|
60
77
|
pi — pi has no static MCP config, mcp migrate-in is a no-op
|
|
61
78
|
for it). Never overwrites differing content — reports a
|
|
62
79
|
conflict instead.
|
|
63
|
-
|
|
80
|
+
--only skills|instructions|mcp|memory
|
|
81
|
+
restrict to one category
|
|
64
82
|
--dry-run preview the plan, write nothing
|
|
65
83
|
--json machine-readable output, no report text
|
|
66
84
|
doctor Scan Claude Code / Codex / Kiro / pi for drift
|
|
@@ -83,12 +101,22 @@ Commands:
|
|
|
83
101
|
--json machine-readable output, no report text
|
|
84
102
|
mcp add <name> --transport stdio|http|sse ...
|
|
85
103
|
Add a canonical MCP server (refuses on an existing name,
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
104
|
+
no overwrite): --command <cmd> [--args a,b] (stdio) or
|
|
105
|
+
--url <url> (http/sse); [--headers k=v,...]
|
|
106
|
+
[--auth oauth] [--env NAME,...] [--static-env k=v,...] [--agents id,...]
|
|
107
|
+
[--enabled true|false]
|
|
108
|
+
--dry-run preview the plan, write nothing
|
|
109
|
+
--json machine-readable output, no report text
|
|
110
|
+
mcp import <json-file>
|
|
111
|
+
Import a standard mcpServers JSON export without changing the
|
|
112
|
+
source; extracts credential env values into the ignored local
|
|
113
|
+
secret file, de-duplicates, and reports conflicts
|
|
114
|
+
--dry-run preview without writing
|
|
115
|
+
--json machine-readable output, no report text
|
|
116
|
+
mcp set <name> --auth oauth|none
|
|
117
|
+
Set or clear explicit OAuth classification; canonical only
|
|
118
|
+
--dry-run preview the plan, write nothing
|
|
119
|
+
--json machine-readable output, no report text
|
|
92
120
|
mcp auth <server-name>
|
|
93
121
|
Authorize a remote (http/sse) MCP server that uses OAuth —
|
|
94
122
|
opens a browser once, stores the result 0600 under
|
|
@@ -97,9 +125,14 @@ Commands:
|
|
|
97
125
|
refreshes silently on its own and never prompts.
|
|
98
126
|
--force re-authorize even if the stored token is valid
|
|
99
127
|
--json machine-readable output, no report text
|
|
128
|
+
mcp-runtime --agent <agent>
|
|
129
|
+
Internal MCP edge exposing Trellis providers and selected
|
|
130
|
+
upstream capabilities; existing mcp-gateway configs remain valid
|
|
131
|
+
as a compatibility alias
|
|
100
132
|
mcp remove <name>
|
|
101
|
-
Remove a canonical MCP server
|
|
102
|
-
|
|
133
|
+
Remove a canonical MCP server, then run the same sync as
|
|
134
|
+
mcp sync so every managed agent's Trellis-owned entry for
|
|
135
|
+
it is removed too
|
|
103
136
|
--dry-run preview the plan, write nothing
|
|
104
137
|
--json machine-readable output, no report text
|
|
105
138
|
skill list
|
|
@@ -111,6 +144,11 @@ Commands:
|
|
|
111
144
|
--dry-run preview the plan, write nothing
|
|
112
145
|
--json machine-readable output, no report text
|
|
113
146
|
skill remove <name>
|
|
147
|
+
skill update-builtin
|
|
148
|
+
Refresh the package-owned trellis-runtime Skill in canonical
|
|
149
|
+
source; existing native symlinks see the update
|
|
150
|
+
--dry-run preview without writing
|
|
151
|
+
--json machine-readable output, no report text
|
|
114
152
|
Remove a canonical skill (the next sync auto-removes the
|
|
115
153
|
now-stale symlink on every managed agent)
|
|
116
154
|
--dry-run preview the plan, write nothing
|
|
@@ -132,6 +170,20 @@ Commands:
|
|
|
132
170
|
round-trip byte-for-byte back through memory sync.
|
|
133
171
|
--dry-run preview the plan, write nothing
|
|
134
172
|
--json machine-readable output, no report text
|
|
173
|
+
manage list
|
|
174
|
+
Show the canonical managed-agent write boundary.
|
|
175
|
+
manage set <ids|none>
|
|
176
|
+
manage add <ids>
|
|
177
|
+
manage remove <ids>
|
|
178
|
+
Explicitly replace, extend, or narrow the managed set. Removing
|
|
179
|
+
an agent preserves its existing native state; future Trellis
|
|
180
|
+
writes stop reaching it. Mutations are backup/rollback-enabled.
|
|
181
|
+
--dry-run preview current -> desired, write nothing
|
|
182
|
+
--json machine-readable output
|
|
183
|
+
kimi [args...]
|
|
184
|
+
Launch Kimi Code. When kimi-code Runtime delivery is \`mcp\`,
|
|
185
|
+
starts Kimi with an empty --skills-dir so Skills come from
|
|
186
|
+
trellis-runtime instead of native discovery.
|
|
135
187
|
secrets audit
|
|
136
188
|
Scan each present agent's real MCP config for leaked
|
|
137
189
|
credentials and unexpected env var names
|
|
@@ -148,12 +200,23 @@ Commands:
|
|
|
148
200
|
|
|
149
201
|
See docs/roadmap.md for what's built vs. planned.`);
|
|
150
202
|
}
|
|
203
|
+
function printVersion() {
|
|
204
|
+
console.log(TRELLIS_VERSION);
|
|
205
|
+
}
|
|
151
206
|
async function main(argv) {
|
|
152
207
|
const [command, ...rest] = argv;
|
|
153
208
|
if (!command || command === "--help" || command === "-h") {
|
|
154
209
|
printUsage();
|
|
155
210
|
return;
|
|
156
211
|
}
|
|
212
|
+
if (command === "--version" || command === "-v") {
|
|
213
|
+
printVersion();
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
if (command === "help") {
|
|
217
|
+
printUsage();
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
157
220
|
if (!KNOWN_COMMANDS.includes(command)) {
|
|
158
221
|
console.error(`Unknown command: ${command}\n`);
|
|
159
222
|
printUsage();
|
|
@@ -165,7 +228,7 @@ async function main(argv) {
|
|
|
165
228
|
// sync --help`) must never fall through to actually running the command
|
|
166
229
|
// it was asking about (real incident: `--help` isn't a flag any branch
|
|
167
230
|
// recognizes, so it silently ran a real, non-dry-run `mcp sync`).
|
|
168
|
-
if (rest.includes("--help") || rest.includes("-h")) {
|
|
231
|
+
if (command !== "kimi" && (rest.includes("--help") || rest.includes("-h"))) {
|
|
169
232
|
printUsage();
|
|
170
233
|
return;
|
|
171
234
|
}
|
|
@@ -182,6 +245,10 @@ async function main(argv) {
|
|
|
182
245
|
const gatewayAgents = gatewayAgentsIndex >= 0 ? rest[gatewayAgentsIndex + 1] : undefined;
|
|
183
246
|
const memoryIndex = rest.indexOf("--memory");
|
|
184
247
|
const memory = memoryIndex >= 0 ? rest[memoryIndex + 1] : undefined;
|
|
248
|
+
const memoryMigrateIndex = rest.indexOf("--memory-migrate");
|
|
249
|
+
const memoryMigrate = memoryMigrateIndex >= 0 ? rest[memoryMigrateIndex + 1] : undefined;
|
|
250
|
+
const selectionIndex = rest.indexOf("--selection");
|
|
251
|
+
const selectionFile = selectionIndex >= 0 ? rest[selectionIndex + 1] : undefined;
|
|
185
252
|
const { exitCode } = await runOnboard({
|
|
186
253
|
agent,
|
|
187
254
|
manage,
|
|
@@ -189,6 +256,8 @@ async function main(argv) {
|
|
|
189
256
|
hubUrl,
|
|
190
257
|
gatewayAgents,
|
|
191
258
|
memory,
|
|
259
|
+
memoryMigrate,
|
|
260
|
+
selectionFile,
|
|
192
261
|
dryRun: rest.includes("--dry-run"),
|
|
193
262
|
json: rest.includes("--json"),
|
|
194
263
|
});
|
|
@@ -217,14 +286,16 @@ async function main(argv) {
|
|
|
217
286
|
// Spawned by an agent, never typed by a person: stdout is the MCP
|
|
218
287
|
// protocol stream for the rest of this process's life, so nothing here
|
|
219
288
|
// may print to it (trellis-mcp-gateway-hosting design.md D2).
|
|
220
|
-
if (command === "mcp-gateway") {
|
|
289
|
+
if (command === "mcp-gateway" || command === "mcp-runtime") {
|
|
221
290
|
const parsed = parseMcpGatewayArgs(rest);
|
|
222
291
|
if ("error" in parsed) {
|
|
223
292
|
console.error(parsed.error);
|
|
224
293
|
process.exitCode = 1;
|
|
225
294
|
return;
|
|
226
295
|
}
|
|
227
|
-
const { exitCode } =
|
|
296
|
+
const { exitCode } = command === "mcp-runtime"
|
|
297
|
+
? await runMcpRuntime({ agentId: parsed.agentId })
|
|
298
|
+
: await runMcpGateway({ agentId: parsed.agentId });
|
|
228
299
|
process.exitCode = exitCode;
|
|
229
300
|
return;
|
|
230
301
|
}
|
|
@@ -255,7 +326,19 @@ async function main(argv) {
|
|
|
255
326
|
}
|
|
256
327
|
if (subcommand === "add") {
|
|
257
328
|
const [name] = mcpRest;
|
|
258
|
-
process.exitCode = runMcpAdd(name, parseMcpAddArgs(mcpRest), { json, dryRun }).exitCode;
|
|
329
|
+
process.exitCode = (await runMcpAdd(name, parseMcpAddArgs(mcpRest), { json, dryRun })).exitCode;
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
if (subcommand === "import") {
|
|
333
|
+
const [file] = mcpRest;
|
|
334
|
+
process.exitCode = (await runMcpImport(file, { json, dryRun })).exitCode;
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
if (subcommand === "set") {
|
|
338
|
+
const [name] = mcpRest;
|
|
339
|
+
const authIndex = mcpRest.indexOf("--auth");
|
|
340
|
+
const auth = authIndex >= 0 ? mcpRest[authIndex + 1] : undefined;
|
|
341
|
+
process.exitCode = runMcpSetAuth(name, auth, { json, dryRun }).exitCode;
|
|
259
342
|
return;
|
|
260
343
|
}
|
|
261
344
|
if (subcommand === "remove") {
|
|
@@ -265,7 +348,7 @@ async function main(argv) {
|
|
|
265
348
|
process.exitCode = 1;
|
|
266
349
|
return;
|
|
267
350
|
}
|
|
268
|
-
process.exitCode = runMcpRemove(name, { json, dryRun }).exitCode;
|
|
351
|
+
process.exitCode = (await runMcpRemove(name, { json, dryRun })).exitCode;
|
|
269
352
|
return;
|
|
270
353
|
}
|
|
271
354
|
if (subcommand === "auth") {
|
|
@@ -279,7 +362,7 @@ async function main(argv) {
|
|
|
279
362
|
process.exitCode = exitCode;
|
|
280
363
|
return;
|
|
281
364
|
}
|
|
282
|
-
console.error(`Unknown mcp subcommand: ${subcommand ?? "(none)"}\nUsage: trellis mcp sync|list|add <name>|remove <name>|auth <name>\n`);
|
|
365
|
+
console.error(`Unknown mcp subcommand: ${subcommand ?? "(none)"}\nUsage: trellis mcp sync|list|add <name>|set <name>|remove <name>|auth <name>\n`);
|
|
283
366
|
process.exitCode = 1;
|
|
284
367
|
return;
|
|
285
368
|
}
|
|
@@ -300,7 +383,7 @@ async function main(argv) {
|
|
|
300
383
|
process.exitCode = 1;
|
|
301
384
|
return;
|
|
302
385
|
}
|
|
303
|
-
process.exitCode = runSkillAdd(name, from, { json, dryRun }).exitCode;
|
|
386
|
+
process.exitCode = (await runSkillAdd(name, from, { json, dryRun })).exitCode;
|
|
304
387
|
return;
|
|
305
388
|
}
|
|
306
389
|
if (subcommand === "remove") {
|
|
@@ -310,10 +393,14 @@ async function main(argv) {
|
|
|
310
393
|
process.exitCode = 1;
|
|
311
394
|
return;
|
|
312
395
|
}
|
|
313
|
-
process.exitCode = runSkillRemove(name, { json, dryRun }).exitCode;
|
|
396
|
+
process.exitCode = (await runSkillRemove(name, { json, dryRun })).exitCode;
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
if (subcommand === "update-builtin") {
|
|
400
|
+
process.exitCode = runSkillUpdateBuiltin({ json, dryRun }).exitCode;
|
|
314
401
|
return;
|
|
315
402
|
}
|
|
316
|
-
console.error(`Unknown skill subcommand: ${subcommand ?? "(none)"}\nUsage: trellis skill list|add <name> --from <path>|remove <name
|
|
403
|
+
console.error(`Unknown skill subcommand: ${subcommand ?? "(none)"}\nUsage: trellis skill list|add <name> --from <path>|remove <name>|update-builtin\n`);
|
|
317
404
|
process.exitCode = 1;
|
|
318
405
|
return;
|
|
319
406
|
}
|
|
@@ -321,6 +408,21 @@ async function main(argv) {
|
|
|
321
408
|
const [subcommand, ...memoryRest] = rest;
|
|
322
409
|
const json = memoryRest.includes("--json");
|
|
323
410
|
const dryRun = memoryRest.includes("--dry-run");
|
|
411
|
+
if (subcommand === "list") {
|
|
412
|
+
const entries = collectMemoryList();
|
|
413
|
+
if (json) {
|
|
414
|
+
console.log(JSON.stringify(entries, null, 2));
|
|
415
|
+
}
|
|
416
|
+
else if (entries.length === 0) {
|
|
417
|
+
console.log("No memories in canonical source yet.");
|
|
418
|
+
}
|
|
419
|
+
else {
|
|
420
|
+
for (const { name, scope } of entries) {
|
|
421
|
+
console.log(`${name} — ${scope.length > 0 ? scope.join(", ") : "(no managed agent reaches it)"}`);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
324
426
|
if (subcommand === "sync") {
|
|
325
427
|
process.exitCode = runMemorySync({ json, dryRun }).exitCode;
|
|
326
428
|
return;
|
|
@@ -329,10 +431,24 @@ async function main(argv) {
|
|
|
329
431
|
process.exitCode = runMemoryExtraction({ json, dryRun }).exitCode;
|
|
330
432
|
return;
|
|
331
433
|
}
|
|
332
|
-
console.error(`Unknown memory subcommand: ${subcommand ?? "(none)"}\nUsage: trellis memory sync|extract\n`);
|
|
434
|
+
console.error(`Unknown memory subcommand: ${subcommand ?? "(none)"}\nUsage: trellis memory list|sync|extract\n`);
|
|
333
435
|
process.exitCode = 1;
|
|
334
436
|
return;
|
|
335
437
|
}
|
|
438
|
+
if (command === "manage") {
|
|
439
|
+
const parsed = parseManageArgs(rest);
|
|
440
|
+
if ("error" in parsed) {
|
|
441
|
+
console.error(`${parsed.error}\nUsage: trellis manage list|set <ids|none>|add <ids>|remove <ids> [--dry-run] [--json]\n`);
|
|
442
|
+
process.exitCode = 1;
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
process.exitCode = runManage(parsed).exitCode;
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
if (command === "kimi") {
|
|
449
|
+
process.exitCode = (await runKimi(rest)).exitCode;
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
336
452
|
if (command === "secrets") {
|
|
337
453
|
const [subcommand] = rest;
|
|
338
454
|
if (subcommand !== "audit") {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `trellis doctor` — read-only cross-agent scan. No `.trellis/` canonical
|
|
3
|
-
* source required (docs/roadmap.md): this compares the
|
|
3
|
+
* source required (docs/roadmap.md): this compares the five agents' own
|
|
4
4
|
* current state against each other, the same manual process used
|
|
5
5
|
* throughout docs/research.md's investigation, now formalized.
|
|
6
6
|
*/
|
|
7
|
+
import { loadCanonicalSource } from "../core/canonical.js";
|
|
7
8
|
import type { AgentId, AgentSnapshot } from "../core/types.js";
|
|
8
9
|
/**
|
|
9
10
|
* Interim default until P1 wires this from `.trellis/mcp/servers.yaml`'s
|
|
@@ -13,7 +14,7 @@ import type { AgentId, AgentSnapshot } from "../core/types.js";
|
|
|
13
14
|
* machine.
|
|
14
15
|
*/
|
|
15
16
|
export declare const DEFAULT_KNOWN_HOST_INJECTED: readonly string[];
|
|
16
|
-
export type FindingKind = "probe-failed" | "duplication" | "collision" | "drift" | "case-mismatch" | "parse-diagnostic" | "mcp-unreachable";
|
|
17
|
+
export type FindingKind = "probe-failed" | "duplication" | "collision" | "drift" | "case-mismatch" | "parse-diagnostic" | "runtime-drift" | "mcp-unreachable";
|
|
17
18
|
export interface Finding {
|
|
18
19
|
kind: FindingKind;
|
|
19
20
|
/** Omitted for a finding that names more than one agent (drift). */
|
|
@@ -92,6 +93,10 @@ export declare function detectCrossAgentDrift(snapshots: AgentSnapshot[]): Findi
|
|
|
92
93
|
export declare function detectCaseMismatches(snapshots: AgentSnapshot[]): Finding[];
|
|
93
94
|
export declare function detectParseDiagnostics(snapshots: AgentSnapshot[]): Finding[];
|
|
94
95
|
export declare function detectMcpUnreachable(snapshots: AgentSnapshot[]): Finding[];
|
|
96
|
+
/** Compares runtime entries against the same canonical MCP plan that sync
|
|
97
|
+
* uses. Only missing Trellis-owned runtime edges are reported; extra
|
|
98
|
+
* user-authored MCP entries remain outside doctor ownership. */
|
|
99
|
+
export declare function detectRuntimeDrift(snapshots: AgentSnapshot[], canonical: Pick<ReturnType<typeof loadCanonicalSource>, "mcp" | "managedAgents" | "secretsPolicy">): Finding[];
|
|
95
100
|
/** Exported so `trellis onboard` can reuse it verbatim for its own final
|
|
96
101
|
* stage (trellis-onboard-closed-loop) rather than a second copy of this
|
|
97
102
|
* formatting. */
|
package/dist/commands/doctor.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `trellis doctor` — read-only cross-agent scan. No `.trellis/` canonical
|
|
3
|
-
* source required (docs/roadmap.md): this compares the
|
|
3
|
+
* source required (docs/roadmap.md): this compares the five agents' own
|
|
4
4
|
* current state against each other, the same manual process used
|
|
5
5
|
* throughout docs/research.md's investigation, now formalized.
|
|
6
6
|
*/
|
|
@@ -9,7 +9,10 @@ import * as claudeCodeProbe from "../probes/claude-code.js";
|
|
|
9
9
|
import * as codexProbe from "../probes/codex.js";
|
|
10
10
|
import * as kiroProbe from "../probes/kiro.js";
|
|
11
11
|
import * as piProbe from "../probes/pi.js";
|
|
12
|
+
import * as kimiCodeProbe from "../probes/kimi-code.js";
|
|
13
|
+
import * as zcodeProbe from "../probes/zcode.js";
|
|
12
14
|
import { loadCanonicalSource } from "../core/canonical.js";
|
|
15
|
+
import { GATEWAY_ENTRY_NAME, RUNTIME_ENTRY_NAME, resolveMcpPlan } from "../adapters/mcpPlan.js";
|
|
13
16
|
import { ALL_AGENTS } from "../core/types.js";
|
|
14
17
|
/**
|
|
15
18
|
* Interim default until P1 wires this from `.trellis/mcp/servers.yaml`'s
|
|
@@ -32,6 +35,7 @@ const EXIT_NONZERO_KINDS = new Set([
|
|
|
32
35
|
"drift",
|
|
33
36
|
"case-mismatch",
|
|
34
37
|
"parse-diagnostic",
|
|
38
|
+
"runtime-drift",
|
|
35
39
|
]);
|
|
36
40
|
/** Exported so tests can assert on this resolution directly, without
|
|
37
41
|
* routing through real per-agent probes `runDoctor` also runs. */
|
|
@@ -72,6 +76,8 @@ export async function collectDoctorReport(homeDir = homedir(), knownHostInjected
|
|
|
72
76
|
{ agent: "codex", run: () => codexProbe.probe(homeDir, { probeMcp }) },
|
|
73
77
|
{ agent: "kiro", run: () => kiroProbe.probe(homeDir, { probeMcp }) },
|
|
74
78
|
{ agent: "pi", run: () => piProbe.probe(homeDir) },
|
|
79
|
+
{ agent: "kimi-code", run: () => kimiCodeProbe.probe(homeDir, { probeMcp }) },
|
|
80
|
+
{ agent: "zcode", run: () => zcodeProbe.probe(homeDir, { probeMcp }) },
|
|
75
81
|
];
|
|
76
82
|
// One agent erroring must not blank the other three's results.
|
|
77
83
|
const settled = await Promise.allSettled(probeList.map((p) => p.run()));
|
|
@@ -89,7 +95,15 @@ export async function collectDoctorReport(homeDir = homedir(), knownHostInjected
|
|
|
89
95
|
});
|
|
90
96
|
}
|
|
91
97
|
});
|
|
92
|
-
|
|
98
|
+
let canonical;
|
|
99
|
+
try {
|
|
100
|
+
canonical = loadCanonicalSource(homeDir);
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
// Doctor remains useful as a standalone cross-agent scanner when
|
|
104
|
+
// canonical has not been initialized yet.
|
|
105
|
+
}
|
|
106
|
+
findings.push(...detectDuplication(snapshots), ...detectCollisions(snapshots, knownHostInjected), ...detectCrossAgentDrift(snapshots), ...detectCaseMismatches(snapshots), ...detectParseDiagnostics(snapshots), ...(canonical ? detectRuntimeDrift(snapshots, canonical) : []), ...detectMcpUnreachable(snapshots));
|
|
93
107
|
return { snapshots, findings };
|
|
94
108
|
}
|
|
95
109
|
/**
|
|
@@ -233,6 +247,30 @@ export function detectMcpUnreachable(snapshots) {
|
|
|
233
247
|
}
|
|
234
248
|
return findings;
|
|
235
249
|
}
|
|
250
|
+
/** Compares runtime entries against the same canonical MCP plan that sync
|
|
251
|
+
* uses. Only missing Trellis-owned runtime edges are reported; extra
|
|
252
|
+
* user-authored MCP entries remain outside doctor ownership. */
|
|
253
|
+
export function detectRuntimeDrift(snapshots, canonical) {
|
|
254
|
+
const findings = [];
|
|
255
|
+
for (const snap of snapshots) {
|
|
256
|
+
if (!snap.present || !canonical.managedAgents.includes(snap.agent) || snap.agent === "pi")
|
|
257
|
+
continue;
|
|
258
|
+
const expected = resolveMcpPlan(snap.agent, canonical.mcp, canonical.managedAgents, canonical.secretsPolicy).desired
|
|
259
|
+
.map((entry) => entry.name)
|
|
260
|
+
.filter((name) => name === RUNTIME_ENTRY_NAME || name === GATEWAY_ENTRY_NAME);
|
|
261
|
+
const actual = new Set(snap.mcpServers.map((server) => server.name));
|
|
262
|
+
for (const name of expected) {
|
|
263
|
+
if (!actual.has(name)) {
|
|
264
|
+
findings.push({
|
|
265
|
+
kind: "runtime-drift",
|
|
266
|
+
agent: snap.agent,
|
|
267
|
+
message: "canonical expects MCP runtime entry \"" + name + "\" for " + snap.agent + ", but it is missing from the agent static configuration",
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return findings;
|
|
273
|
+
}
|
|
236
274
|
/** Exported so `trellis onboard` can reuse it verbatim for its own final
|
|
237
275
|
* stage (trellis-onboard-closed-loop) rather than a second copy of this
|
|
238
276
|
* formatting. */
|
package/dist/commands/init.d.ts
CHANGED
|
@@ -29,7 +29,7 @@ export interface InitReport {
|
|
|
29
29
|
/** Exported so `migrate` can byte-compare canonical `agents.md` against
|
|
30
30
|
* this exact string (design.md D3, trellis-cli-migrate) rather than
|
|
31
31
|
* retyping an equivalent one that could silently drift from this. */
|
|
32
|
-
export declare const AGENTS_MD_TEMPLATE = "# Shared instructions\n\nWrite what every agent should know here \u2014 communication preferences,\nproject conventions, anything you'd otherwise repeat per agent.\n\nAlready using Claude Code, Codex, Kiro, or
|
|
32
|
+
export declare const AGENTS_MD_TEMPLATE = "# Shared instructions\n\nWrite what every agent should know here \u2014 communication preferences,\nproject conventions, anything you'd otherwise repeat per agent.\n\nAlready using Claude Code, Codex, Kiro, pi, Kimi Code, or ZCode? `trellis migrate --from\n<agent>` imports its real instructions and skills instead of starting\nfrom this placeholder.\n";
|
|
33
33
|
/**
|
|
34
34
|
* Trellis never spawns an installer itself (global package installs are
|
|
35
35
|
* exactly the kind of irreversible, system-wide action that needs the
|
|
@@ -38,7 +38,9 @@ export declare const AGENTS_MD_TEMPLATE = "# Shared instructions\n\nWrite what e
|
|
|
38
38
|
* own current install docs, same discipline as everything else here.
|
|
39
39
|
*/
|
|
40
40
|
export declare const INSTALL_HINTS: Record<AgentId, string>;
|
|
41
|
-
export declare function collectInitReport(homeDir?: string
|
|
41
|
+
export declare function collectInitReport(homeDir?: string, options?: {
|
|
42
|
+
write?: boolean;
|
|
43
|
+
}): Promise<InitReport>;
|
|
42
44
|
export declare function runInit(opts?: RunInitOptions): Promise<{
|
|
43
45
|
exitCode: number;
|
|
44
46
|
}>;
|
package/dist/commands/init.js
CHANGED
|
@@ -15,6 +15,8 @@ import * as claudeCodeProbe from "../probes/claude-code.js";
|
|
|
15
15
|
import * as codexProbe from "../probes/codex.js";
|
|
16
16
|
import * as kiroProbe from "../probes/kiro.js";
|
|
17
17
|
import * as piProbe from "../probes/pi.js";
|
|
18
|
+
import * as kimiCodeProbe from "../probes/kimi-code.js";
|
|
19
|
+
import * as zcodeProbe from "../probes/zcode.js";
|
|
18
20
|
import { ALL_AGENTS } from "../core/types.js";
|
|
19
21
|
/** Exported so `migrate` can byte-compare canonical `agents.md` against
|
|
20
22
|
* this exact string (design.md D3, trellis-cli-migrate) rather than
|
|
@@ -24,7 +26,7 @@ export const AGENTS_MD_TEMPLATE = `# Shared instructions
|
|
|
24
26
|
Write what every agent should know here — communication preferences,
|
|
25
27
|
project conventions, anything you'd otherwise repeat per agent.
|
|
26
28
|
|
|
27
|
-
Already using Claude Code, Codex, Kiro, or
|
|
29
|
+
Already using Claude Code, Codex, Kiro, pi, Kimi Code, or ZCode? \`trellis migrate --from
|
|
28
30
|
<agent>\` imports its real instructions and skills instead of starting
|
|
29
31
|
from this placeholder.
|
|
30
32
|
`;
|
|
@@ -93,32 +95,46 @@ export const INSTALL_HINTS = {
|
|
|
93
95
|
codex: "npm install -g @openai/codex",
|
|
94
96
|
kiro: "https://kiro.dev/downloads/",
|
|
95
97
|
pi: "npm install -g @earendil-works/pi-coding-agent",
|
|
98
|
+
"kimi-code": "curl -fsSL https://code.kimi.com/kimi-code/install.sh | bash",
|
|
99
|
+
zcode: "https://zcode.z.ai/en/docs/install",
|
|
96
100
|
};
|
|
97
|
-
function ensureFile(path, template) {
|
|
101
|
+
function ensureFile(path, template, write = true) {
|
|
98
102
|
if (existsSync(path)) {
|
|
99
103
|
return { path, action: "already-present" };
|
|
100
104
|
}
|
|
101
|
-
|
|
105
|
+
if (write)
|
|
106
|
+
writeFileSync(path, template);
|
|
102
107
|
return { path, action: "create" };
|
|
103
108
|
}
|
|
104
|
-
export async function collectInitReport(homeDir = homedir()) {
|
|
109
|
+
export async function collectInitReport(homeDir = homedir(), options = {}) {
|
|
110
|
+
const write = options.write !== false;
|
|
105
111
|
const root = join(homeDir, ".trellis");
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
112
|
+
if (write) {
|
|
113
|
+
mkdirSync(root, { recursive: true });
|
|
114
|
+
mkdirSync(join(root, "mcp"), { recursive: true });
|
|
115
|
+
mkdirSync(join(root, "skills"), { recursive: true });
|
|
116
|
+
mkdirSync(join(root, "agents"), { recursive: true });
|
|
117
|
+
mkdirSync(join(root, "memories"), { recursive: true });
|
|
118
|
+
}
|
|
111
119
|
const files = [
|
|
112
|
-
ensureFile(join(root, "agents.md"), AGENTS_MD_TEMPLATE),
|
|
113
|
-
ensureFile(join(root, "mcp", "servers.yaml"), serversYamlTemplate()),
|
|
114
|
-
ensureFile(join(root, "secrets.policy.yaml"), secretsPolicyYamlTemplate()),
|
|
115
|
-
ensureFile(join(root, "managed.yaml"), managedYamlTemplate()),
|
|
120
|
+
ensureFile(join(root, "agents.md"), AGENTS_MD_TEMPLATE, write),
|
|
121
|
+
ensureFile(join(root, "mcp", "servers.yaml"), serversYamlTemplate(), write),
|
|
122
|
+
ensureFile(join(root, "secrets.policy.yaml"), secretsPolicyYamlTemplate(), write),
|
|
123
|
+
ensureFile(join(root, "managed.yaml"), managedYamlTemplate(), write),
|
|
116
124
|
];
|
|
125
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
126
|
+
const builtinSkillPath = join(root, "skills", "trellis-runtime", "SKILL.md");
|
|
127
|
+
const builtinSkillTemplate = readFileSync(join(here, "..", "..", "schema", "builtin-skills", "trellis-runtime", "SKILL.md"), "utf8");
|
|
128
|
+
if (write)
|
|
129
|
+
mkdirSync(dirname(builtinSkillPath), { recursive: true });
|
|
130
|
+
files.push(ensureFile(builtinSkillPath, builtinSkillTemplate, write));
|
|
117
131
|
const probes = [
|
|
118
132
|
{ agent: "claude-code", run: () => claudeCodeProbe.probe(homeDir) },
|
|
119
133
|
{ agent: "codex", run: () => codexProbe.probe(homeDir) },
|
|
120
134
|
{ agent: "kiro", run: () => kiroProbe.probe(homeDir) },
|
|
121
135
|
{ agent: "pi", run: () => piProbe.probe(homeDir) },
|
|
136
|
+
{ agent: "kimi-code", run: () => kimiCodeProbe.probe(homeDir) },
|
|
137
|
+
{ agent: "zcode", run: () => zcodeProbe.probe(homeDir) },
|
|
122
138
|
];
|
|
123
139
|
const settled = await Promise.allSettled(probes.map((p) => p.run()));
|
|
124
140
|
const agents = settled.map((result, index) => {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Runtime-first Kimi Code launcher.
|
|
2
|
+
*
|
|
3
|
+
* Kimi automatically discovers ~/.agents/skills. When canonical delivery is
|
|
4
|
+
* `mcp`, passing one empty --skills-dir is the only documented way to replace
|
|
5
|
+
* both user/project Skill roots for this launch and prevent duplicate native
|
|
6
|
+
* Skill delivery. Native/both modes invoke Kimi normally.
|
|
7
|
+
*/
|
|
8
|
+
import { spawn as spawnProcess } from "node:child_process";
|
|
9
|
+
export interface RunKimiOptions {
|
|
10
|
+
homeDir?: string;
|
|
11
|
+
env?: NodeJS.ProcessEnv;
|
|
12
|
+
spawn?: typeof spawnProcess;
|
|
13
|
+
}
|
|
14
|
+
export declare function runKimi(args?: readonly string[], opts?: RunKimiOptions): Promise<{
|
|
15
|
+
exitCode: number;
|
|
16
|
+
}>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/** Runtime-first Kimi Code launcher.
|
|
2
|
+
*
|
|
3
|
+
* Kimi automatically discovers ~/.agents/skills. When canonical delivery is
|
|
4
|
+
* `mcp`, passing one empty --skills-dir is the only documented way to replace
|
|
5
|
+
* both user/project Skill roots for this launch and prevent duplicate native
|
|
6
|
+
* Skill delivery. Native/both modes invoke Kimi normally.
|
|
7
|
+
*/
|
|
8
|
+
import { execFileSync, spawn as spawnProcess } from "node:child_process";
|
|
9
|
+
import { existsSync, mkdtempSync, rmSync } from "node:fs";
|
|
10
|
+
import { homedir, tmpdir } from "node:os";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { capabilityDeliveryForAgent } from "../core/types.js";
|
|
13
|
+
import { loadCanonicalSource } from "../core/canonical.js";
|
|
14
|
+
function resolveKimiCommand(homeDir, env) {
|
|
15
|
+
const explicit = env.TRELLIS_KIMI_BIN;
|
|
16
|
+
if (explicit && existsSync(explicit))
|
|
17
|
+
return explicit;
|
|
18
|
+
const homeBinary = join(env.KIMI_CODE_HOME ?? join(homeDir, ".kimi-code"), "bin", "kimi");
|
|
19
|
+
if (existsSync(homeBinary))
|
|
20
|
+
return homeBinary;
|
|
21
|
+
try {
|
|
22
|
+
return execFileSync("which", ["kimi"], { encoding: "utf8", env }).trim() || "kimi";
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return "kimi";
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function hasSkillsDirArg(args) {
|
|
29
|
+
return args.some((arg) => arg === "--skills-dir" || arg.startsWith("--skills-dir="));
|
|
30
|
+
}
|
|
31
|
+
export async function runKimi(args = [], opts = {}) {
|
|
32
|
+
const homeDir = opts.homeDir ?? homedir();
|
|
33
|
+
const env = { ...process.env, ...(opts.env ?? {}) };
|
|
34
|
+
let canonical;
|
|
35
|
+
try {
|
|
36
|
+
canonical = loadCanonicalSource(homeDir);
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
40
|
+
return { exitCode: 1 };
|
|
41
|
+
}
|
|
42
|
+
const delivery = capabilityDeliveryForAgent("kimi-code", canonical.mcp);
|
|
43
|
+
const runtimeOnly = delivery === "mcp";
|
|
44
|
+
if (runtimeOnly && hasSkillsDirArg(args)) {
|
|
45
|
+
console.error("trellis kimi: --skills-dir cannot be combined with Runtime-only delivery; change mcp.runtime.delivery.kimi-code or use native Kimi directly");
|
|
46
|
+
return { exitCode: 1 };
|
|
47
|
+
}
|
|
48
|
+
let emptySkillsDir;
|
|
49
|
+
const launchArgs = [...args];
|
|
50
|
+
if (runtimeOnly) {
|
|
51
|
+
emptySkillsDir = mkdtempSync(join(tmpdir(), "trellis-kimi-empty-skills-"));
|
|
52
|
+
launchArgs.unshift("--skills-dir", emptySkillsDir);
|
|
53
|
+
}
|
|
54
|
+
const command = resolveKimiCommand(homeDir, env);
|
|
55
|
+
const spawn = opts.spawn ?? spawnProcess;
|
|
56
|
+
const child = spawn(command, launchArgs, { stdio: "inherit", env });
|
|
57
|
+
const exitCode = await new Promise((resolve) => {
|
|
58
|
+
child.once("error", () => resolve(1));
|
|
59
|
+
child.once("exit", (code, signal) => resolve(code ?? (signal ? 1 : 0)));
|
|
60
|
+
});
|
|
61
|
+
if (emptySkillsDir)
|
|
62
|
+
rmSync(emptySkillsDir, { recursive: true, force: true });
|
|
63
|
+
return { exitCode };
|
|
64
|
+
}
|