@mindfoldhq/trellis 0.6.3 → 0.6.5

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.
Files changed (81) hide show
  1. package/dist/cli/index.js +1 -0
  2. package/dist/cli/index.js.map +1 -1
  3. package/dist/commands/channel/messages.js +1 -1
  4. package/dist/commands/channel/supervisor.d.ts.map +1 -1
  5. package/dist/commands/channel/supervisor.js +34 -2
  6. package/dist/commands/channel/supervisor.js.map +1 -1
  7. package/dist/commands/init.d.ts +1 -0
  8. package/dist/commands/init.d.ts.map +1 -1
  9. package/dist/commands/init.js.map +1 -1
  10. package/dist/commands/uninstall.d.ts.map +1 -1
  11. package/dist/commands/uninstall.js +1 -0
  12. package/dist/commands/uninstall.js.map +1 -1
  13. package/dist/commands/update.d.ts.map +1 -1
  14. package/dist/commands/update.js +23 -11
  15. package/dist/commands/update.js.map +1 -1
  16. package/dist/configurators/codex.d.ts.map +1 -1
  17. package/dist/configurators/codex.js +1 -15
  18. package/dist/configurators/codex.js.map +1 -1
  19. package/dist/configurators/index.d.ts.map +1 -1
  20. package/dist/configurators/index.js +25 -9
  21. package/dist/configurators/index.js.map +1 -1
  22. package/dist/configurators/kiro.d.ts +4 -2
  23. package/dist/configurators/kiro.d.ts.map +1 -1
  24. package/dist/configurators/kiro.js +12 -3
  25. package/dist/configurators/kiro.js.map +1 -1
  26. package/dist/configurators/pi.d.ts.map +1 -1
  27. package/dist/configurators/pi.js +14 -4
  28. package/dist/configurators/pi.js.map +1 -1
  29. package/dist/configurators/shared.d.ts +0 -19
  30. package/dist/configurators/shared.d.ts.map +1 -1
  31. package/dist/configurators/shared.js +12 -32
  32. package/dist/configurators/shared.js.map +1 -1
  33. package/dist/configurators/trae.d.ts +17 -0
  34. package/dist/configurators/trae.d.ts.map +1 -0
  35. package/dist/configurators/trae.js +42 -0
  36. package/dist/configurators/trae.js.map +1 -0
  37. package/dist/configurators/zcode.js +3 -3
  38. package/dist/configurators/zcode.js.map +1 -1
  39. package/dist/migrations/manifests/0.6.4.json +9 -0
  40. package/dist/migrations/manifests/0.6.5.json +9 -0
  41. package/dist/templates/codex/skills/brainstorm/SKILL.md +19 -1
  42. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-hooks.md +1 -1
  43. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/generated-files.md +1 -1
  44. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/hooks-and-settings.md +1 -0
  45. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/overview.md +2 -2
  46. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/platform-map.md +2 -0
  47. package/dist/templates/common/skills/brainstorm.md +19 -1
  48. package/dist/templates/copilot/prompts/brainstorm.prompt.md +19 -1
  49. package/dist/templates/kiro/agents/trellis.json +34 -0
  50. package/dist/templates/kiro/hooks/trellis-workflow-state.kiro.hook +14 -0
  51. package/dist/templates/kiro/index.d.ts +16 -2
  52. package/dist/templates/kiro/index.d.ts.map +1 -1
  53. package/dist/templates/kiro/index.js +13 -3
  54. package/dist/templates/kiro/index.js.map +1 -1
  55. package/dist/templates/pi/agents/trellis-check.md +1 -1
  56. package/dist/templates/pi/agents/trellis-implement.md +1 -1
  57. package/dist/templates/pi/agents/trellis-research.md +1 -1
  58. package/dist/templates/pi/extensions/trellis/index.ts.txt +84 -8
  59. package/dist/templates/shared-hooks/index.d.ts +9 -3
  60. package/dist/templates/shared-hooks/index.d.ts.map +1 -1
  61. package/dist/templates/shared-hooks/index.js +14 -3
  62. package/dist/templates/shared-hooks/index.js.map +1 -1
  63. package/dist/templates/shared-hooks/inject-workflow-state.py +52 -7
  64. package/dist/templates/shared-hooks/session-start.py +13 -0
  65. package/dist/templates/trae/agents/trellis-check.md +108 -0
  66. package/dist/templates/trae/agents/trellis-implement.md +103 -0
  67. package/dist/templates/trae/agents/trellis-research.md +137 -0
  68. package/dist/templates/trae/hooks.json +27 -0
  69. package/dist/templates/trae/index.d.ts +15 -0
  70. package/dist/templates/trae/index.d.ts.map +1 -0
  71. package/dist/templates/trae/index.js +15 -0
  72. package/dist/templates/trae/index.js.map +1 -0
  73. package/dist/templates/trellis/scripts/common/active_task.py +2 -0
  74. package/dist/templates/trellis/scripts/common/cli_adapter.py +37 -11
  75. package/dist/templates/trellis/scripts/common/task_store.py +1 -0
  76. package/dist/templates/trellis/workflow.md +22 -20
  77. package/dist/types/ai-tools.d.ts +4 -4
  78. package/dist/types/ai-tools.d.ts.map +1 -1
  79. package/dist/types/ai-tools.js +16 -0
  80. package/dist/types/ai-tools.js.map +1 -1
  81. package/package.json +2 -2
@@ -0,0 +1,14 @@
1
+ {
2
+ "version": "1.0.0",
3
+ "enabled": true,
4
+ "name": "trellis-workflow-state",
5
+ "description": "Inject Trellis workflow state on each prompt",
6
+ "when": {
7
+ "type": "promptSubmit"
8
+ },
9
+ "then": {
10
+ "type": "runCommand",
11
+ "command": "{{PYTHON_CMD}} .kiro/hooks/inject-workflow-state.py",
12
+ "timeout": 30
13
+ }
14
+ }
@@ -2,11 +2,14 @@
2
2
  * Kiro templates
3
3
  *
4
4
  * Kiro uses pure JSON agent definitions, not Markdown.
5
- * Hooks are embedded in agent JSON, not in a separate config file.
5
+ * CLI agents embed hooks in their JSON (`hooks.agentSpawn`,
6
+ * `hooks.userPromptSubmit`); the IDE surface reads standalone `.kiro.hook`
7
+ * JSON files (`when`/`then` schema).
6
8
  *
7
9
  * Directory structure:
8
10
  * kiro/
9
- * └── agents/ # Agent definitions (JSON)
11
+ * ├── agents/ # Agent definitions (JSON) — main `trellis` + 3 sub-agents
12
+ * └── hooks/ # IDE `.kiro.hook` definitions (JSON)
10
13
  */
11
14
  import { type AgentTemplate } from "../template-utils.js";
12
15
  export type { AgentTemplate };
@@ -15,4 +18,15 @@ export type { AgentTemplate };
15
18
  * Content contains {{PYTHON_CMD}} placeholder that must be resolved before writing.
16
19
  */
17
20
  export declare const getAllAgents: () => AgentTemplate[];
21
+ export interface IdeHookTemplate {
22
+ /** Filename (e.g. "trellis-workflow-state.kiro.hook") */
23
+ name: string;
24
+ /** Raw JSON content; contains {{PYTHON_CMD}} placeholder. */
25
+ content: string;
26
+ }
27
+ /**
28
+ * Get all Kiro IDE hook templates (`*.kiro.hook` JSON files).
29
+ * Content contains {{PYTHON_CMD}} placeholder that must be resolved before writing.
30
+ */
31
+ export declare const getIdeHooks: () => IdeHookTemplate[];
18
32
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/kiro/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAChF,YAAY,EAAE,aAAa,EAAE,CAAC;AAI9B;;;GAGG;AACH,eAAO,MAAM,YAAY,QAAO,aAAa,EAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/kiro/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAChF,YAAY,EAAE,aAAa,EAAE,CAAC;AAM9B;;;GAGG;AACH,eAAO,MAAM,YAAY,QAAO,aAAa,EAAsB,CAAC;AAEpE,MAAM,WAAW,eAAe;IAC9B,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW,QAAO,eAAe,EAGqB,CAAC"}
@@ -2,17 +2,27 @@
2
2
  * Kiro templates
3
3
  *
4
4
  * Kiro uses pure JSON agent definitions, not Markdown.
5
- * Hooks are embedded in agent JSON, not in a separate config file.
5
+ * CLI agents embed hooks in their JSON (`hooks.agentSpawn`,
6
+ * `hooks.userPromptSubmit`); the IDE surface reads standalone `.kiro.hook`
7
+ * JSON files (`when`/`then` schema).
6
8
  *
7
9
  * Directory structure:
8
10
  * kiro/
9
- * └── agents/ # Agent definitions (JSON)
11
+ * ├── agents/ # Agent definitions (JSON) — main `trellis` + 3 sub-agents
12
+ * └── hooks/ # IDE `.kiro.hook` definitions (JSON)
10
13
  */
11
14
  import { createTemplateReader } from "../template-utils.js";
12
- const { listJsonAgents } = createTemplateReader(import.meta.url);
15
+ const { listFiles, readTemplate, listJsonAgents } = createTemplateReader(import.meta.url);
13
16
  /**
14
17
  * Get all Kiro agent templates (JSON format).
15
18
  * Content contains {{PYTHON_CMD}} placeholder that must be resolved before writing.
16
19
  */
17
20
  export const getAllAgents = () => listJsonAgents();
21
+ /**
22
+ * Get all Kiro IDE hook templates (`*.kiro.hook` JSON files).
23
+ * Content contains {{PYTHON_CMD}} placeholder that must be resolved before writing.
24
+ */
25
+ export const getIdeHooks = () => listFiles("hooks")
26
+ .filter((f) => f.endsWith(".kiro.hook"))
27
+ .map((f) => ({ name: f, content: readTemplate(`hooks/${f}`) }));
18
28
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/kiro/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,oBAAoB,EAAsB,MAAM,sBAAsB,CAAC;AAGhF,MAAM,EAAE,cAAc,EAAE,GAAG,oBAAoB,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEjE;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,GAAoB,EAAE,CAAC,cAAc,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/kiro/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,oBAAoB,EAAsB,MAAM,sBAAsB,CAAC;AAGhF,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,cAAc,EAAE,GAAG,oBAAoB,CACtE,MAAM,CAAC,IAAI,CAAC,GAAG,CAChB,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,GAAoB,EAAE,CAAC,cAAc,EAAE,CAAC;AASpE;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,GAAsB,EAAE,CACjD,SAAS,CAAC,OAAO,CAAC;KACf,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;KACvC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC"}
@@ -2,7 +2,7 @@
2
2
  name: trellis-check
3
3
  description: |
4
4
  Code quality check expert. Reviews changes against Trellis specs, fixes issues directly, and verifies quality gates.
5
- tools: Read, Write, Edit, Bash, Glob, Grep
5
+ tools: read, write, edit, bash, find, grep
6
6
  ---
7
7
  # Check Agent
8
8
 
@@ -2,7 +2,7 @@
2
2
  name: trellis-implement
3
3
  description: |
4
4
  Code implementation expert. Understands Trellis specs and requirements, then implements features. No git commit allowed.
5
- tools: Read, Write, Edit, Bash, Glob, Grep
5
+ tools: read, write, edit, bash, find, grep
6
6
  ---
7
7
  # Implement Agent
8
8
 
@@ -2,7 +2,7 @@
2
2
  name: trellis-research
3
3
  description: |
4
4
  Code and technical research expert. Finds relevant files, patterns, docs, and persists findings to the current task's research/ directory.
5
- tools: Read, Write, Bash, Glob, Grep
5
+ tools: read, write, bash, find, grep
6
6
  ---
7
7
  # Research Agent
8
8
 
@@ -31,11 +31,13 @@ interface SubagentInput {
31
31
  interface AgentConfig {
32
32
  model?: string;
33
33
  thinking?: string;
34
+ tools?: string[];
34
35
  fallbackModels: string[];
35
36
  }
36
37
  interface PiRunConfig {
37
38
  model?: string;
38
39
  thinking?: string;
40
+ tools?: string[];
39
41
  }
40
42
 
41
43
  // ── Lazy-load pi-tui (avoid failing top-level imports) ─────────────────
@@ -81,6 +83,10 @@ const MAX_PARALLEL_PROMPTS = 6;
81
83
  const ABORT_KILL_GRACE_MS = 1500;
82
84
  const SESSION_OVERVIEW_TIMEOUT_MS = 1500;
83
85
  const THROTTLE_MS = 500;
86
+ const FIRST_REPLY_NOTICE = `<first-reply-notice>
87
+ First visible reply: say once in Chinese that Trellis SessionStart context is loaded, then answer directly.
88
+ This notice is one-shot: do not repeat it after the first assistant reply in the same session.
89
+ </first-reply-notice>`;
84
90
 
85
91
  // ── State types ───────────────────────────────────────────────────────
86
92
  type RunStatus = "pending" | "running" | "succeeded" | "failed" | "cancelled";
@@ -654,8 +660,8 @@ function resolveRunCfg(
654
660
  agentSuffixThinking ??
655
661
  normalize(inheritedThinking);
656
662
  if (baseModel && thinking && thinking !== "off")
657
- return { model: `${baseModel}:${thinking}`, thinking };
658
- return { model: baseModel || rawModel, thinking };
663
+ return { model: `${baseModel}:${thinking}`, thinking, tools: agentCfg.tools };
664
+ return { model: baseModel || rawModel, thinking, tools: agentCfg.tools };
659
665
  }
660
666
 
661
667
  function buildPiArgs(cfg: PiRunConfig): string[] {
@@ -669,6 +675,8 @@ function buildPiArgs(cfg: PiRunConfig): string[] {
669
675
  );
670
676
  else if (cfg.thinking && cfg.thinking !== "off")
671
677
  args.push("--thinking", cfg.thinking);
678
+ if (cfg.tools && cfg.tools.length > 0)
679
+ args.push("--tools", cfg.tools.join(","));
672
680
  return args;
673
681
  }
674
682
 
@@ -762,6 +770,16 @@ function parseAgentFM(c: string): AgentConfig {
762
770
  }
763
771
  i--;
764
772
  }
773
+ } else if (k === "tools") {
774
+ // Pi tool names are lowercase (read, bash, edit, write, grep, find, ls).
775
+ // Normalize to lowercase so mixed-case frontmatter still matches.
776
+ if (v.trim()) {
777
+ cfg.tools = v
778
+ .trim()
779
+ .split(",")
780
+ .map((s) => s.trim().replace(/^["']|["']$/g, "").toLowerCase())
781
+ .filter(Boolean);
782
+ }
765
783
  }
766
784
  }
767
785
  return cfg;
@@ -862,12 +880,12 @@ function workflowBreadcrumb(root: string, key: string | null): string {
862
880
  }
863
881
 
864
882
  // ── Session Overview ───────────────────────────────────────────────────
865
- function sessionOverview(root: string, key: string | null): string {
883
+ function runContextScript(root: string, key: string | null, args: string[]): string {
866
884
  const script = join(root, ".trellis", "scripts", "get_context.py");
867
885
  if (!exists(script)) return "";
868
886
  try {
869
887
  const py = process.platform === "win32" ? "python" : "python3";
870
- const result = spawnSync(py, [script], {
888
+ const result = spawnSync(py, [script, ...args], {
871
889
  cwd: root,
872
890
  env: key ? { ...process.env, TRELLIS_CONTEXT_ID: key } : process.env,
873
891
  encoding: "utf-8",
@@ -876,12 +894,44 @@ function sessionOverview(root: string, key: string | null): string {
876
894
  });
877
895
  if (result.status !== 0) return "";
878
896
  const stdout = (result.stdout ?? "").trim();
879
- return stdout ? `<session-overview>\n${stdout}\n</session-overview>` : "";
897
+ return stdout;
880
898
  } catch {
881
899
  return "";
882
900
  }
883
901
  }
884
902
 
903
+ function sessionOverview(root: string, key: string | null): string {
904
+ const stdout = runContextScript(root, key, []);
905
+ return stdout ? `<session-overview>\n${stdout}\n</session-overview>` : "";
906
+ }
907
+
908
+ function workflowOverview(root: string, key: string | null): string {
909
+ const stdout = runContextScript(root, key, [
910
+ "--mode",
911
+ "phase",
912
+ "--platform",
913
+ "pi",
914
+ ]);
915
+ return stdout ? `<trellis-workflow>\n${stdout}\n</trellis-workflow>` : "";
916
+ }
917
+
918
+ function buildStartupContext(
919
+ root: string,
920
+ key: string | null,
921
+ overview: string,
922
+ ): string {
923
+ const workflow = workflowOverview(root, key);
924
+ return [
925
+ "<session-context>\nTrellis compact SessionStart context. Use it to orient the session; load details on demand.\n</session-context>",
926
+ FIRST_REPLY_NOTICE,
927
+ overview,
928
+ workflow,
929
+ "<ready>\nUse the current workflow state to decide whether to create, continue, or skip a Trellis task.\n</ready>",
930
+ ]
931
+ .filter(Boolean)
932
+ .join("\n\n");
933
+ }
934
+
885
935
  function buildContext(root: string, agent: string, key: string | null): string {
886
936
  const dir = readTaskDir(root, key);
887
937
  if (!dir)
@@ -1372,6 +1422,16 @@ export default function trellisExtension(pi: {
1372
1422
  };
1373
1423
  return turnCache;
1374
1424
  };
1425
+ const startupKeys = new Set<string>();
1426
+ const getStartupCtx = (
1427
+ k: string | null,
1428
+ turn: { ov: string },
1429
+ ): string => {
1430
+ const key = k ?? "default";
1431
+ if (startupKeys.has(key)) return "";
1432
+ startupKeys.add(key);
1433
+ return buildStartupContext(root, k, turn.ov);
1434
+ };
1375
1435
 
1376
1436
  // Toggle only the latest subagent native card; do not use Pi global tool expansion.
1377
1437
  const toggleDetail = (ctx: PiExtensionContext) => {
@@ -1550,7 +1610,7 @@ export default function trellisExtension(pi: {
1550
1610
  pi.on?.("session_start", (event, ctx) => {
1551
1611
  getKey(event, ctx);
1552
1612
  ctx?.ui?.notify?.(
1553
- "Trellis project context is available. Use /trellis-continue to resume the current task.",
1613
+ "Trellis project context is available. Use /trellis-start to bootstrap or /trellis-continue to resume.",
1554
1614
  "info",
1555
1615
  );
1556
1616
  });
@@ -1585,13 +1645,29 @@ export default function trellisExtension(pi: {
1585
1645
  return { isError: true };
1586
1646
  return undefined;
1587
1647
  });
1648
+ pi.on?.("input", (event, ctx) => {
1649
+ const k = getKey(event, ctx);
1650
+ const ev = event as { text?: string };
1651
+ if (typeof ev.text !== "string" || !ev.text.trim())
1652
+ return { action: "continue" };
1653
+ const { wf, ov } = getTurnCtx(k);
1654
+ const injection = [wf, ov].filter(Boolean).join("\n\n");
1655
+ if (!injection) return { action: "continue" };
1656
+ return {
1657
+ action: "transform",
1658
+ text: [ev.text, injection].join("\n\n"),
1659
+ };
1660
+ });
1588
1661
  pi.on?.("before_agent_start", (event, ctx) => {
1589
1662
  const k = getKey(event, ctx);
1590
1663
  const cur = (event as { systemPrompt?: string }).systemPrompt ?? "";
1591
1664
  const ctxText = buildContext(root, "trellis-implement", k);
1592
- const { wf, ov } = getTurnCtx(k);
1665
+ const turn = getTurnCtx(k);
1666
+ const startup = getStartupCtx(k, turn);
1593
1667
  return {
1594
- systemPrompt: [cur, ctxText, wf, ov].filter(Boolean).join("\n\n"),
1668
+ systemPrompt: [cur, startup, ctxText, turn.wf, turn.ov]
1669
+ .filter(Boolean)
1670
+ .join("\n\n"),
1595
1671
  };
1596
1672
  });
1597
1673
  pi.on?.("context", (event, ctx) => {
@@ -12,7 +12,7 @@ export interface HookScript {
12
12
  content: string;
13
13
  }
14
14
  export type SharedHookName = "session-start.py" | "inject-shell-session-context.py" | "inject-workflow-state.py" | "inject-subagent-context.py";
15
- export type SharedHookPlatform = "claude" | "cursor" | "codex" | "gemini" | "qoder" | "copilot" | "codebuddy" | "droid" | "kiro";
15
+ export type SharedHookPlatform = "claude" | "cursor" | "codex" | "gemini" | "qoder" | "copilot" | "codebuddy" | "droid" | "kiro" | "trae";
16
16
  /**
17
17
  * Which shared hooks each platform actually invokes. Single source of truth
18
18
  * for shared-hook distribution — both `writeSharedHooks` (runtime install)
@@ -29,8 +29,14 @@ export type SharedHookPlatform = "claude" | "cursor" | "codex" | "gemini" | "qod
29
29
  * Class-2 (pull-based) platforms (codex, copilot, gemini, qoder) can't
30
30
  * have hooks mutate sub-agent prompts — their sub-agents load context
31
31
  * via a prelude instead.
32
- * - Kiro supports only `agentSpawn` (no SessionStart / UserPromptSubmit
33
- * event), so it takes just `inject-subagent-context.py`.
32
+ * - Kiro supports per-turn + spawn hooks on both surfaces (per the official
33
+ * docs https://kiro.dev/docs/cli/hooks/): the CLI custom agent declares
34
+ * `hooks.userPromptSubmit` + `hooks.agentSpawn`, and the IDE declares a
35
+ * `.kiro.hook` with `when.type=promptSubmit`. So Kiro ships
36
+ * `session-start.py` (agentSpawn overview), `inject-workflow-state.py`
37
+ * (per-turn breadcrumb), and `inject-subagent-context.py` (sub-agent
38
+ * spawn). The scripts emit a plain-text Kiro branch — Kiro adds a hook's
39
+ * stdout directly to the conversation context (no JSON envelope).
34
40
  * - Claude Code `statusLine` is intentionally not installed by default.
35
41
  * Users can add their own statusLine command in `.claude/settings.json`,
36
42
  * or opt in to the Trellis one via `trellis init --with-statusline`
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/shared-hooks/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAaH,MAAM,WAAW,UAAU;IACzB,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,cAAc,GACtB,kBAAkB,GAClB,iCAAiC,GACjC,0BAA0B,GAC1B,4BAA4B,CAAC;AAEjC,MAAM,MAAM,kBAAkB,GAC1B,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,OAAO,GACP,SAAS,GACT,WAAW,GACX,OAAO,GACP,MAAM,CAAC;AAEX;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAC3C,kBAAkB,EAClB,SAAS,cAAc,EAAE,CA2B1B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,UAAU,EAAE,CAWnD;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,kBAAkB,GAC3B,UAAU,EAAE,CAGd"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/shared-hooks/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAaH,MAAM,WAAW,UAAU;IACzB,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,cAAc,GACtB,kBAAkB,GAClB,iCAAiC,GACjC,0BAA0B,GAC1B,4BAA4B,CAAC;AAEjC,MAAM,MAAM,kBAAkB,GAC1B,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,OAAO,GACP,SAAS,GACT,WAAW,GACX,OAAO,GACP,MAAM,GACN,MAAM,CAAC;AAEX;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAC3C,kBAAkB,EAClB,SAAS,cAAc,EAAE,CAgC1B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,UAAU,EAAE,CAWnD;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,kBAAkB,GAC3B,UAAU,EAAE,CAGd"}
@@ -29,8 +29,14 @@ function readTemplate(relativePath) {
29
29
  * Class-2 (pull-based) platforms (codex, copilot, gemini, qoder) can't
30
30
  * have hooks mutate sub-agent prompts — their sub-agents load context
31
31
  * via a prelude instead.
32
- * - Kiro supports only `agentSpawn` (no SessionStart / UserPromptSubmit
33
- * event), so it takes just `inject-subagent-context.py`.
32
+ * - Kiro supports per-turn + spawn hooks on both surfaces (per the official
33
+ * docs https://kiro.dev/docs/cli/hooks/): the CLI custom agent declares
34
+ * `hooks.userPromptSubmit` + `hooks.agentSpawn`, and the IDE declares a
35
+ * `.kiro.hook` with `when.type=promptSubmit`. So Kiro ships
36
+ * `session-start.py` (agentSpawn overview), `inject-workflow-state.py`
37
+ * (per-turn breadcrumb), and `inject-subagent-context.py` (sub-agent
38
+ * spawn). The scripts emit a plain-text Kiro branch — Kiro adds a hook's
39
+ * stdout directly to the conversation context (no JSON envelope).
34
40
  * - Claude Code `statusLine` is intentionally not installed by default.
35
41
  * Users can add their own statusLine command in `.claude/settings.json`,
36
42
  * or opt in to the Trellis one via `trellis init --with-statusline`
@@ -62,7 +68,12 @@ export const SHARED_HOOKS_BY_PLATFORM = {
62
68
  "inject-workflow-state.py",
63
69
  "inject-subagent-context.py",
64
70
  ],
65
- kiro: ["inject-subagent-context.py"],
71
+ kiro: [
72
+ "session-start.py",
73
+ "inject-workflow-state.py",
74
+ "inject-subagent-context.py",
75
+ ],
76
+ trae: ["session-start.py", "inject-workflow-state.py"],
66
77
  };
67
78
  /**
68
79
  * Get all shared hook scripts. Content is platform-independent and can be
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/shared-hooks/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,SAAS,YAAY,CAAC,YAAoB;IACxC,OAAO,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC;AAC9D,CAAC;AA0BD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAGjC;IACF,MAAM,EAAE;QACN,kBAAkB;QAClB,0BAA0B;QAC1B,4BAA4B;KAC7B;IACD,MAAM,EAAE;QACN,kBAAkB;QAClB,iCAAiC;QACjC,4BAA4B;KAC7B;IACD,KAAK,EAAE,CAAC,0BAA0B,CAAC;IACnC,MAAM,EAAE,CAAC,kBAAkB,EAAE,0BAA0B,CAAC;IACxD,KAAK,EAAE,CAAC,kBAAkB,EAAE,0BAA0B,CAAC;IACvD,OAAO,EAAE,CAAC,0BAA0B,CAAC;IACrC,SAAS,EAAE;QACT,kBAAkB;QAClB,0BAA0B;QAC1B,4BAA4B;KAC7B;IACD,KAAK,EAAE;QACL,kBAAkB;QAClB,0BAA0B;QAC1B,4BAA4B;KAC7B;IACD,IAAI,EAAE,CAAC,4BAA4B,CAAC;CACrC,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,oBAAoB;IAClC,MAAM,OAAO,GAAiB,EAAE,CAAC;IACjC,MAAM,KAAK,GAAG,WAAW,CAAC,SAAS,CAAC;SACjC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;SAChC,IAAI,EAAE,CAAC;IAEV,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,+BAA+B,CAC7C,QAA4B;IAE5B,MAAM,OAAO,GAAG,IAAI,GAAG,CAAS,wBAAwB,CAAC,QAAQ,CAAC,CAAC,CAAC;IACpE,OAAO,oBAAoB,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AACnE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/shared-hooks/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,SAAS,YAAY,CAAC,YAAoB;IACxC,OAAO,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC;AAC9D,CAAC;AA2BD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAGjC;IACF,MAAM,EAAE;QACN,kBAAkB;QAClB,0BAA0B;QAC1B,4BAA4B;KAC7B;IACD,MAAM,EAAE;QACN,kBAAkB;QAClB,iCAAiC;QACjC,4BAA4B;KAC7B;IACD,KAAK,EAAE,CAAC,0BAA0B,CAAC;IACnC,MAAM,EAAE,CAAC,kBAAkB,EAAE,0BAA0B,CAAC;IACxD,KAAK,EAAE,CAAC,kBAAkB,EAAE,0BAA0B,CAAC;IACvD,OAAO,EAAE,CAAC,0BAA0B,CAAC;IACrC,SAAS,EAAE;QACT,kBAAkB;QAClB,0BAA0B;QAC1B,4BAA4B;KAC7B;IACD,KAAK,EAAE;QACL,kBAAkB;QAClB,0BAA0B;QAC1B,4BAA4B;KAC7B;IACD,IAAI,EAAE;QACJ,kBAAkB;QAClB,0BAA0B;QAC1B,4BAA4B;KAC7B;IACD,IAAI,EAAE,CAAC,kBAAkB,EAAE,0BAA0B,CAAC;CACvD,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,oBAAoB;IAClC,MAAM,OAAO,GAAiB,EAAE,CAAC;IACjC,MAAM,KAAK,GAAG,WAAW,CAAC,SAAS,CAAC;SACjC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;SAChC,IAAI,EAAE,CAAC;IAEV,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,+BAA+B,CAC7C,QAA4B;IAE5B,MAAM,OAAO,GAAG,IAAI,GAAG,CAAS,wBAAwB,CAAC,QAAQ,CAAC,CAAC,CAAC;IACpE,OAAO,oBAAoB,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AACnE,CAAC"}
@@ -18,9 +18,11 @@ missing or a tag is absent, the breadcrumb degrades to a generic
18
18
  the broken state instead of the hook silently masking it.
19
19
 
20
20
  Shared across all hook-capable platforms (Claude, Cursor, Codex, Qoder,
21
- CodeBuddy, Droid, Gemini, Copilot). Kiro is not wired (no per-turn
22
- hook entry point). Written to each platform's hooks directory via
23
- writeSharedHooks() at init time.
21
+ CodeBuddy, Droid, Gemini, Copilot, Kiro). Kiro wires this via the CLI
22
+ custom agent's ``hooks.userPromptSubmit`` and the IDE ``.kiro.hook``
23
+ ``promptSubmit`` event; its output branch emits a plain-text breadcrumb
24
+ (Kiro adds hook stdout directly to the conversation context). Written to
25
+ each platform's hooks directory via writeSharedHooks() at init time.
24
26
 
25
27
  Silent exit 0 cases (no output):
26
28
  - No .trellis/ directory found (not a Trellis project)
@@ -32,6 +34,8 @@ import json
32
34
  import os
33
35
  import re
34
36
  import sys
37
+ import queue
38
+ import threading
35
39
  from pathlib import Path
36
40
 
37
41
  # Force UTF-8 on stdin/stdout/stderr on Windows. Default codepage there is
@@ -100,6 +104,7 @@ def _detect_platform(input_data: dict) -> str | None:
100
104
  "QODER_PROJECT_DIR": "qoder",
101
105
  "KIRO_PROJECT_DIR": "kiro",
102
106
  "COPILOT_PROJECT_DIR": "copilot",
107
+ "TRAE_PROJECT_DIR": "trae",
103
108
  }
104
109
  for env_name, platform in env_map.items():
105
110
  if os.environ.get(env_name):
@@ -121,6 +126,8 @@ def _detect_platform(input_data: dict) -> str | None:
121
126
  return "droid"
122
127
  if ".kiro" in script_parts:
123
128
  return "kiro"
129
+ if ".trae" in script_parts:
130
+ return "trae"
124
131
  return None
125
132
 
126
133
 
@@ -300,14 +307,44 @@ def build_breadcrumb(
300
307
  # Entry
301
308
  # ---------------------------------------------------------------------------
302
309
 
310
+ def _load_hook_input() -> dict:
311
+ """Read hook JSON without trusting host runners to close stdin.
312
+
313
+ Kiro IDE `runCommand` and similar hook runners can leave stdin open while
314
+ sending no payload. A plain `json.load(sys.stdin)` then blocks forever.
315
+ Normal hook runners write the complete JSON payload and close stdin, so the
316
+ short daemon read preserves that path while failing closed to `{}` for
317
+ non-piping hosts.
318
+ """
319
+ result_queue: "queue.Queue[str | BaseException]" = queue.Queue(maxsize=1)
320
+
321
+ def _read() -> None:
322
+ try:
323
+ result_queue.put(sys.stdin.read())
324
+ except BaseException as exc:
325
+ result_queue.put(exc)
326
+
327
+ reader = threading.Thread(target=_read, daemon=True)
328
+ reader.start()
329
+ try:
330
+ raw = result_queue.get(timeout=0.2)
331
+ except queue.Empty:
332
+ return {}
333
+
334
+ if isinstance(raw, BaseException):
335
+ return {}
336
+ try:
337
+ data = json.loads(raw) if raw.strip() else {}
338
+ except (json.JSONDecodeError, ValueError):
339
+ return {}
340
+ return data if isinstance(data, dict) else {}
341
+
342
+
303
343
  def main() -> int:
304
344
  if os.environ.get("TRELLIS_HOOKS") == "0" or os.environ.get("TRELLIS_DISABLE_HOOKS") == "1":
305
345
  return 0
306
346
 
307
- try:
308
- data = json.load(sys.stdin)
309
- except (json.JSONDecodeError, ValueError):
310
- data = {}
347
+ data = _load_hook_input()
311
348
 
312
349
  cwd_str = data.get("cwd") or os.getcwd()
313
350
  cwd = Path(cwd_str)
@@ -342,6 +379,14 @@ def main() -> int:
342
379
  parts.append(breadcrumb)
343
380
  breadcrumb = "\n\n".join(parts)
344
381
 
382
+ # Kiro (CLI userPromptSubmit / IDE promptSubmit) adds a hook's stdout
383
+ # directly to the conversation context — no JSON envelope. Emit the bare
384
+ # breadcrumb text. Conditionally isolated: all other platforms keep the
385
+ # hookSpecificOutput JSON path below unchanged.
386
+ if platform == "kiro":
387
+ print(breadcrumb)
388
+ return 0
389
+
345
390
  # Gemini CLI 0.40.x rejects "UserPromptSubmit" — its per-turn event is
346
391
  # named "BeforeAgent". Other platforms (Claude/Cursor/Qoder/CodeBuddy/
347
392
  # Droid/Codex/Copilot) accept the original Claude-style name.
@@ -137,6 +137,7 @@ def should_skip_injection() -> bool:
137
137
  "GEMINI_NON_INTERACTIVE",
138
138
  "KIRO_NON_INTERACTIVE",
139
139
  "COPILOT_NON_INTERACTIVE",
140
+ "TRAE_NON_INTERACTIVE",
140
141
  ]
141
142
  return any(os.environ.get(var) == "1" for var in non_interactive_vars)
142
143
 
@@ -195,6 +196,7 @@ def _detect_platform(input_data: dict) -> str | None:
195
196
  "QODER_PROJECT_DIR": "qoder",
196
197
  "KIRO_PROJECT_DIR": "kiro",
197
198
  "COPILOT_PROJECT_DIR": "copilot",
199
+ "TRAE_PROJECT_DIR": "trae",
198
200
  }
199
201
  for env_name, platform in env_map.items():
200
202
  if os.environ.get(env_name):
@@ -216,6 +218,8 @@ def _detect_platform(input_data: dict) -> str | None:
216
218
  return "droid"
217
219
  if ".kiro" in script_parts:
218
220
  return "kiro"
221
+ if ".trae" in script_parts:
222
+ return "trae"
219
223
  return None
220
224
 
221
225
 
@@ -739,6 +743,7 @@ def main():
739
743
  "GEMINI_PROJECT_DIR",
740
744
  "KIRO_PROJECT_DIR",
741
745
  "COPILOT_PROJECT_DIR",
746
+ "TRAE_PROJECT_DIR",
742
747
  ]
743
748
  project_dir = None
744
749
  for var in project_dir_env_vars:
@@ -813,6 +818,14 @@ Context loaded. Follow <task-status>. Load workflow/spec/task details only when
813
818
  </ready>""")
814
819
 
815
820
  context_text = output.getvalue()
821
+
822
+ # Kiro (CLI trellis agent agentSpawn) adds a hook's stdout directly to the
823
+ # conversation context — no JSON envelope. Emit the bare overview text.
824
+ # Conditionally isolated: all other platforms keep the JSON path below.
825
+ if _detect_platform(hook_input) == "kiro":
826
+ print(context_text, flush=True)
827
+ return
828
+
816
829
  result = {
817
830
  # Claude Code / Qoder / CodeBuddy / Droid / Gemini / Copilot format
818
831
  "hookSpecificOutput": {
@@ -0,0 +1,108 @@
1
+ ---
2
+ name: trellis-check
3
+ description: |
4
+ Code quality check expert. Reviews code changes against specs and self-fixes issues.
5
+ tools: Read, Write, Edit, Bash, Glob, Grep
6
+ ---
7
+ # Check Agent
8
+
9
+ You are the Check Agent in the Trellis workflow.
10
+
11
+ ## Recursion Guard
12
+
13
+ You are already the `trellis-check` sub-agent that the main session dispatched. Do the review and fixes directly.
14
+
15
+ - Do NOT spawn another `trellis-check` or `trellis-implement` sub-agent.
16
+ - If SessionStart context, workflow-state breadcrumbs, or workflow.md say to dispatch `trellis-implement` / `trellis-check`, treat that as a main-session instruction that is already satisfied by your current role.
17
+ - Only the main session may dispatch Trellis implement/check agents. If more implementation work is needed, report that recommendation instead of spawning.
18
+
19
+ ## Context
20
+
21
+ Before checking, read:
22
+ - `.trellis/spec/` - Development guidelines
23
+ - Task `prd.md` - Requirements document
24
+ - Task `design.md` - Technical design (if exists)
25
+ - Task `implement.md` - Execution plan (if exists)
26
+ - Pre-commit checklist for quality standards
27
+
28
+ ## Core Responsibilities
29
+
30
+ 1. **Get code changes** - Use git diff to get uncommitted code
31
+ 2. **Review task artifacts** - Check changes against prd.md, design.md if present, and implement.md if present
32
+ 3. **Check against specs** - Verify code follows guidelines
33
+ 4. **Self-fix** - Fix issues yourself, not just report them
34
+ 5. **Run verification** - typecheck and lint
35
+
36
+ ## Important
37
+
38
+ **Fix issues yourself**, don't just report them.
39
+
40
+ You have write and edit tools, you can modify code directly.
41
+
42
+ ---
43
+
44
+ ## Workflow
45
+
46
+ ### Step 1: Get Changes
47
+
48
+ ```bash
49
+ git diff --name-only # List changed files
50
+ git diff # View specific changes
51
+ ```
52
+
53
+ ### Step 2: Check Against Specs and Task Artifacts
54
+
55
+ Read the task's prd.md, design.md if present, and implement.md if present, then read relevant specs in `.trellis/spec/` to check code:
56
+
57
+ - Does it satisfy the task requirements
58
+ - Does it follow the technical design and implementation plan when present
59
+ - Does it follow directory structure conventions
60
+ - Does it follow naming conventions
61
+ - Does it follow code patterns
62
+ - Are there missing types
63
+ - Are there potential bugs
64
+
65
+ ### Step 3: Self-Fix
66
+
67
+ After finding issues:
68
+
69
+ 1. Fix the issue directly (use edit tool)
70
+ 2. Record what was fixed
71
+ 3. Continue checking other issues
72
+
73
+ ### Step 4: Run Verification
74
+
75
+ Run project's lint and typecheck commands to verify changes.
76
+
77
+ If failed, fix issues and re-run.
78
+
79
+ ---
80
+
81
+ ## Report Format
82
+
83
+ ```markdown
84
+ ## Self-Check Complete
85
+
86
+ ### Files Checked
87
+
88
+ - src/components/Feature.tsx
89
+ - src/hooks/useFeature.ts
90
+
91
+ ### Issues Found and Fixed
92
+
93
+ 1. `<file>:<line>` - <what was fixed>
94
+ 2. `<file>:<line>` - <what was fixed>
95
+
96
+ ### Issues Not Fixed
97
+
98
+ (If there are issues that cannot be self-fixed, list them here with reasons)
99
+
100
+ ### Verification Results
101
+
102
+ - TypeCheck: Passed
103
+ - Lint: Passed
104
+
105
+ ### Summary
106
+
107
+ Checked X files, found Y issues, all fixed.
108
+ ```