@mindfoldhq/trellis 0.6.2 → 0.6.4
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 +1 -1
- package/dist/cli/index.js +11 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/init.d.ts +5 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +49 -2
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/mem.d.ts.map +1 -1
- package/dist/commands/mem.js +4 -3
- package/dist/commands/mem.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +1 -2
- package/dist/commands/update.js.map +1 -1
- package/dist/configurators/antigravity.d.ts +1 -1
- package/dist/configurators/antigravity.js +1 -1
- package/dist/configurators/claude.d.ts +5 -2
- package/dist/configurators/claude.d.ts.map +1 -1
- package/dist/configurators/claude.js +37 -4
- package/dist/configurators/claude.js.map +1 -1
- package/dist/configurators/codebuddy.d.ts +1 -1
- package/dist/configurators/codebuddy.js +1 -1
- package/dist/configurators/codex.d.ts.map +1 -1
- package/dist/configurators/codex.js +3 -17
- package/dist/configurators/codex.js.map +1 -1
- package/dist/configurators/copilot.d.ts +1 -1
- package/dist/configurators/copilot.js +1 -1
- package/dist/configurators/cursor.d.ts +1 -1
- package/dist/configurators/cursor.js +1 -1
- package/dist/configurators/devin.d.ts +7 -0
- package/dist/configurators/devin.d.ts.map +1 -0
- package/dist/configurators/{windsurf.js → devin.js} +7 -7
- package/dist/configurators/devin.js.map +1 -0
- package/dist/configurators/droid.d.ts +1 -1
- package/dist/configurators/droid.js +1 -1
- package/dist/configurators/gemini.d.ts +1 -1
- package/dist/configurators/gemini.js +1 -1
- package/dist/configurators/index.d.ts +2 -1
- package/dist/configurators/index.d.ts.map +1 -1
- package/dist/configurators/index.js +22 -15
- package/dist/configurators/index.js.map +1 -1
- package/dist/configurators/kilo.d.ts +1 -1
- package/dist/configurators/kilo.js +1 -1
- package/dist/configurators/kiro.d.ts +4 -2
- package/dist/configurators/kiro.d.ts.map +1 -1
- package/dist/configurators/kiro.js +12 -3
- package/dist/configurators/kiro.js.map +1 -1
- package/dist/configurators/shared.d.ts +18 -24
- package/dist/configurators/shared.d.ts.map +1 -1
- package/dist/configurators/shared.js +19 -39
- package/dist/configurators/shared.js.map +1 -1
- package/dist/configurators/zcode.d.ts +19 -0
- package/dist/configurators/zcode.d.ts.map +1 -0
- package/dist/configurators/zcode.js +54 -0
- package/dist/configurators/zcode.js.map +1 -0
- package/dist/migrations/manifests/0.6.3.json +24 -0
- package/dist/migrations/manifests/0.6.4.json +9 -0
- package/dist/templates/claude/hooks/statusline.py +324 -0
- package/dist/templates/claude/index.d.ts +10 -1
- package/dist/templates/claude/index.d.ts.map +1 -1
- package/dist/templates/claude/index.js +12 -1
- package/dist/templates/claude/index.js.map +1 -1
- package/dist/templates/common/bundled-skills/trellis-meta/SKILL.md +4 -4
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-agents.md +2 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-skills-or-commands.md +2 -1
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/overview.md +2 -2
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/bundled-skills.md +3 -3
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/generated-files.md +2 -2
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/overview.md +1 -1
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/agents.md +3 -1
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/hooks-and-settings.md +2 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/overview.md +2 -2
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/platform-map.md +4 -2
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/skills-and-commands.md +3 -1
- package/dist/templates/common/bundled-skills/trellis-session-insight/SKILL.md +2 -2
- package/dist/templates/common/bundled-skills/trellis-session-insight/references/cli-quick-reference.md +23 -24
- package/dist/templates/common/skills/brainstorm.md +43 -0
- package/dist/templates/common/skills/break-loop.md +59 -0
- package/dist/templates/kiro/agents/trellis.json +34 -0
- package/dist/templates/kiro/hooks/trellis-workflow-state.kiro.hook +14 -0
- package/dist/templates/kiro/index.d.ts +16 -2
- package/dist/templates/kiro/index.d.ts.map +1 -1
- package/dist/templates/kiro/index.js +13 -3
- package/dist/templates/kiro/index.js.map +1 -1
- package/dist/templates/shared-hooks/index.d.ts +12 -4
- package/dist/templates/shared-hooks/index.d.ts.map +1 -1
- package/dist/templates/shared-hooks/index.js +17 -5
- package/dist/templates/shared-hooks/index.js.map +1 -1
- package/dist/templates/shared-hooks/inject-workflow-state.py +13 -3
- package/dist/templates/shared-hooks/session-start.py +8 -0
- package/dist/templates/trellis/scripts/add_session.py +26 -6
- package/dist/templates/trellis/scripts/common/cli_adapter.py +46 -32
- package/dist/templates/trellis/scripts/common/safe_commit.py +46 -16
- package/dist/templates/trellis/scripts/common/task_store.py +2 -2
- package/dist/templates/trellis/scripts/common/workflow_phase.py +1 -1
- package/dist/templates/trellis/workflow.md +23 -23
- package/dist/templates/zcode/agents/trellis-check.md +102 -0
- package/dist/templates/zcode/agents/trellis-implement.md +102 -0
- package/dist/templates/zcode/index.d.ts +15 -0
- package/dist/templates/zcode/index.d.ts.map +1 -0
- package/dist/templates/zcode/index.js +18 -0
- package/dist/templates/zcode/index.js.map +1 -0
- package/dist/types/ai-tools.d.ts +4 -4
- package/dist/types/ai-tools.d.ts.map +1 -1
- package/dist/types/ai-tools.js +25 -7
- package/dist/types/ai-tools.js.map +1 -1
- package/package.json +2 -2
- package/dist/configurators/windsurf.d.ts +0 -7
- package/dist/configurators/windsurf.d.ts.map +0 -1
- package/dist/configurators/windsurf.js.map +0 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ZCode configurator.
|
|
3
|
+
*
|
|
4
|
+
* ZCode (智谱) is a pull-based class-2 platform (agentCapable, no hooks).
|
|
5
|
+
* Three output paths:
|
|
6
|
+
* - `.agents/skills/` — shared skills, byte-identical with Codex/Gemini writes
|
|
7
|
+
* - `.zcode/commands/trellis/` — slash commands (invoked as /trellis:<name>)
|
|
8
|
+
* - `.zcode/cli/agents/` — sub-agent definitions with pull-based prelude
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Collect all ZCode template files for `trellis update` diff tracking.
|
|
12
|
+
* Must stay in sync with `configureZcode`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function collectZcodeTemplates(): Map<string, string>;
|
|
15
|
+
/**
|
|
16
|
+
* Configure ZCode at init time: write shared skills, commands, and sub-agents.
|
|
17
|
+
*/
|
|
18
|
+
export declare function configureZcode(cwd: string): Promise<void>;
|
|
19
|
+
//# sourceMappingURL=zcode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zcode.d.ts","sourceRoot":"","sources":["../../src/configurators/zcode.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAgBH;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAyB3D;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAuB/D"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ZCode configurator.
|
|
3
|
+
*
|
|
4
|
+
* ZCode (智谱) is a pull-based class-2 platform (agentCapable, no hooks).
|
|
5
|
+
* Three output paths:
|
|
6
|
+
* - `.agents/skills/` — shared skills, byte-identical with Codex/Gemini writes
|
|
7
|
+
* - `.zcode/commands/trellis/` — slash commands (invoked as /trellis:<name>)
|
|
8
|
+
* - `.zcode/cli/agents/` — sub-agent definitions with pull-based prelude
|
|
9
|
+
*/
|
|
10
|
+
import path from "node:path";
|
|
11
|
+
import { AI_TOOLS } from "../types/ai-tools.js";
|
|
12
|
+
import { ensureDir, writeFile } from "../utils/file-writer.js";
|
|
13
|
+
import { getAllAgents } from "../templates/zcode/index.js";
|
|
14
|
+
import { collectSkillTemplates, resolveAllAsSkillsNeutral, resolveBundledSkills, resolveCommands, writeSkills, writeAgents, applyPullBasedPreludeMarkdown, } from "./shared.js";
|
|
15
|
+
/**
|
|
16
|
+
* Collect all ZCode template files for `trellis update` diff tracking.
|
|
17
|
+
* Must stay in sync with `configureZcode`.
|
|
18
|
+
*/
|
|
19
|
+
export function collectZcodeTemplates() {
|
|
20
|
+
const config = AI_TOOLS.zcode;
|
|
21
|
+
const ctx = config.templateContext;
|
|
22
|
+
const files = new Map();
|
|
23
|
+
// 1. Shared skills → .agents/skills/ (byte-identical with Codex/Gemini)
|
|
24
|
+
for (const [filePath, content] of collectSkillTemplates(".agents/skills", resolveAllAsSkillsNeutral(ctx), resolveBundledSkills(ctx))) {
|
|
25
|
+
files.set(filePath, content);
|
|
26
|
+
}
|
|
27
|
+
// 2. Commands → .zcode/commands/trellis/
|
|
28
|
+
for (const cmd of resolveCommands(ctx)) {
|
|
29
|
+
files.set(`.zcode/commands/trellis/${cmd.name}.md`, cmd.content);
|
|
30
|
+
}
|
|
31
|
+
// 3. Sub-agents → .zcode/cli/agents/ (with pull-based prelude)
|
|
32
|
+
for (const agent of applyPullBasedPreludeMarkdown(getAllAgents())) {
|
|
33
|
+
files.set(`.zcode/cli/agents/${agent.name}.md`, agent.content);
|
|
34
|
+
}
|
|
35
|
+
return files;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Configure ZCode at init time: write shared skills, commands, and sub-agents.
|
|
39
|
+
*/
|
|
40
|
+
export async function configureZcode(cwd) {
|
|
41
|
+
const config = AI_TOOLS.zcode;
|
|
42
|
+
const ctx = config.templateContext;
|
|
43
|
+
// 1. Shared skills → .agents/skills/
|
|
44
|
+
await writeSkills(path.join(cwd, ".agents", "skills"), resolveAllAsSkillsNeutral(ctx), resolveBundledSkills(ctx));
|
|
45
|
+
// 2. Commands → .zcode/commands/trellis/
|
|
46
|
+
const commandsDir = path.join(cwd, ".zcode", "commands", "trellis");
|
|
47
|
+
ensureDir(commandsDir);
|
|
48
|
+
for (const cmd of resolveCommands(ctx)) {
|
|
49
|
+
await writeFile(path.join(commandsDir, `${cmd.name}.md`), cmd.content);
|
|
50
|
+
}
|
|
51
|
+
// 3. Sub-agents → .zcode/cli/agents/ (with pull-based prelude)
|
|
52
|
+
await writeAgents(path.join(cwd, ".zcode", "cli", "agents"), applyPullBasedPreludeMarkdown(getAllAgents()));
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=zcode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zcode.js","sourceRoot":"","sources":["../../src/configurators/zcode.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,oBAAoB,EACpB,eAAe,EACf,WAAW,EACX,WAAW,EACX,6BAA6B,GAC9B,MAAM,aAAa,CAAC;AAErB;;;GAGG;AACH,MAAM,UAAU,qBAAqB;IACnC,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC;IAC9B,MAAM,GAAG,GAAG,MAAM,CAAC,eAAe,CAAC;IACnC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IAExC,wEAAwE;IACxE,KAAK,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,qBAAqB,CACrD,gBAAgB,EAChB,yBAAyB,CAAC,GAAG,CAAC,EAC9B,oBAAoB,CAAC,GAAG,CAAC,CAC1B,EAAE,CAAC;QACF,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC/B,CAAC;IAED,yCAAyC;IACzC,KAAK,MAAM,GAAG,IAAI,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;QACvC,KAAK,CAAC,GAAG,CAAC,2BAA2B,GAAG,CAAC,IAAI,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACnE,CAAC;IAED,+DAA+D;IAC/D,KAAK,MAAM,KAAK,IAAI,6BAA6B,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC;QAClE,KAAK,CAAC,GAAG,CAAC,qBAAqB,KAAK,CAAC,IAAI,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IACjE,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,GAAW;IAC9C,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC;IAC9B,MAAM,GAAG,GAAG,MAAM,CAAC,eAAe,CAAC;IAEnC,qCAAqC;IACrC,MAAM,WAAW,CACf,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,QAAQ,CAAC,EACnC,yBAAyB,CAAC,GAAG,CAAC,EAC9B,oBAAoB,CAAC,GAAG,CAAC,CAC1B,CAAC;IAEF,yCAAyC;IACzC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IACpE,SAAS,CAAC,WAAW,CAAC,CAAC;IACvB,KAAK,MAAM,GAAG,IAAI,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;QACvC,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,GAAG,CAAC,IAAI,KAAK,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACzE,CAAC;IAED,+DAA+D;IAC/D,MAAM,WAAW,CACf,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,EACzC,6BAA6B,CAAC,YAAY,EAAE,CAAC,CAC9C,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.6.3",
|
|
3
|
+
"description": "Patch release: ZCode (智谱) platform, opt-in --with-statusline for Claude Code, Pi session mem adapter, first-principles + bayesian thinking frameworks in the brainstorm/break-loop skills, the Windsurf -> Devin platform rename (.windsurf/ -> .devin/, --windsurf kept as a deprecated alias), and fixes for #300 (Windows mem --cwd) and #303 (.trellis auto-commit staging scope).",
|
|
4
|
+
"breaking": false,
|
|
5
|
+
"recommendMigrate": true,
|
|
6
|
+
"changelog": "**Enhancements:**\n- feat(platform): **ZCode (`--zcode`).** Added ZCode (智谱 / Z.ai) as a pull-based, agent-capable platform (no hooks). `trellis init --zcode` writes `.agents/skills/`, `.zcode/commands/trellis/`, and `.zcode/cli/agents/` (`trellis-implement` / `trellis-check`). Registry `AI_TOOLS.zcode`, configurator `configureZcode` in `src/configurators/zcode.ts`.\n- feat(init): **`trellis init --with-statusline`.** Opt-in Claude Code status bar (off by default; interactive prompt when the flag is omitted, skipped under `-y`). Writes `.claude/hooks/statusline.py` and a `statusLine` entry in `.claude/settings.json`. Not part of `collectTemplates`/shared-hooks, so `trellis update` never force-installs or removes it.\n- feat(mem): **Pi session adapter.** `trellis mem --platform pi` (and `all`) now reads persisted Pi Agent sessions via `packages/core/src/mem/adapters/pi.ts`. Discovers `~/.pi/agent/sessions/`, honors `PI_CODING_AGENT_DIR` / `PI_CODING_AGENT_SESSION_DIR`, and slices phases in `sliceMemPhase` like Claude/Codex.\n- feat(platform): **Windsurf is now Devin.** Cognition renamed Windsurf to Devin Desktop (2026-06-02 OTA) and moved the config dir from `.windsurf/` to `.devin/`. `trellis init --devin` writes `.devin/workflows/` + `.devin/skills/` and passes `--platform devin` (#325). `--windsurf` remains a deprecated alias for one version.\n- feat(skills): **Thinking frameworks.** `brainstorm` gains a First Principles Analysis framework (decompose to fundamentals during requirement discovery) and `break-loop` gains a Bayesian Reasoning framework (weight hypotheses by evidence during debugging), both in `common/skills/` so all platforms get them on update. Hardcoded \"5 skills\" comments replaced with count-free wording (#335).\n\n**Bug Fixes:**\n- fix(mem): **`--cwd` Claude filter on Windows (#300).** `trellis mem --cwd` returned 0 Claude sessions on Windows because `claudeProjectDirFromCwd` only sanitized `/` and `_`. The regex now covers all separators (`/[/\\\\:_.]/g`) and `claudeListSessions` falls back to scanning every project dir when the derived dir is missing.\n- fix(commit): **`.trellis` auto-commit staging scope (#303).** Scoped `.trellis/` auto-commit so it no longer sweeps unrelated parallel-window task dirs into session commits. `safe_trellis_paths_to_add()` takes a `task_name`; `_auto_commit_workspace()` resolves the current task via `get_current_task()`; `release.js` `git add -A` now excludes `':!.trellis'`.\n\n**Migration:** Only the Windsurf → Devin rename needs `trellis update --migrate` — and only if you initialized with `--windsurf`. It ships idempotent `rename-dir` migrations (`.windsurf/workflows/` → `.devin/workflows/`, `.windsurf/skills/` → `.devin/skills/`); projects without a `.windsurf/` directory are silently skipped.",
|
|
7
|
+
"migrations": [
|
|
8
|
+
{
|
|
9
|
+
"type": "rename-dir",
|
|
10
|
+
"from": ".windsurf/workflows",
|
|
11
|
+
"to": ".devin/workflows",
|
|
12
|
+
"description": "Devin (formerly Windsurf): move installed workflows from the old .windsurf/ config dir to .devin/ (Windsurf was renamed to Devin Desktop).",
|
|
13
|
+
"reason": "Cognition renamed Windsurf to Devin Desktop and moved its config dir from .windsurf/ to .devin/. Trellis renamed the platform to match."
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"type": "rename-dir",
|
|
17
|
+
"from": ".windsurf/skills",
|
|
18
|
+
"to": ".devin/skills",
|
|
19
|
+
"description": "Devin (formerly Windsurf): move installed skills from the old .windsurf/ config dir to .devin/ (Windsurf was renamed to Devin Desktop).",
|
|
20
|
+
"reason": "Cognition renamed Windsurf to Devin Desktop and moved its config dir from .windsurf/ to .devin/. Trellis renamed the platform to match."
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"notes": "Windsurf → Devin rename (#325). If you initialized Trellis with `--windsurf`, run `trellis update --migrate` to move your installed `.windsurf/workflows/` and `.windsurf/skills/` directories to `.devin/`. Projects without a `.windsurf/` directory are unaffected (the migration silently skips). `--windsurf` still works as a deprecated alias for `--devin` this release.\n\nInstall: `npm install -g @mindfoldhq/trellis`"
|
|
24
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.6.4",
|
|
3
|
+
"description": "Patch release: fixes Kiro main-session workflow injection (deterministic activation via userPromptSubmit + agentSpawn) and emits `trellis-start` on agentCapable && !hasHooks platforms (Codex, ZCode, OpenCode, Reasonix) by narrowing the filterCommands condition. Also extends `workflow.md` platform-matrix blocks to cover ZCode and Reasonix.",
|
|
4
|
+
"breaking": false,
|
|
5
|
+
"recommendMigrate": false,
|
|
6
|
+
"changelog": "**Bug Fixes:**\n- fix(configurators): emit `trellis-start` on `agentCapable && !hasHooks` platforms (Codex, ZCode, OpenCode, Reasonix). `filterCommands(ctx)` in `packages/cli/src/configurators/shared.ts` now strips `start` only when both `agentCapable` and `hasHooks` are true. Prior condition removed `start` from every agent-capable platform, leaving the four no-hook platforms without a way to load workflow context. Codex's one-off `resolveCodexTrellisStartSkill` helper and its two call sites are deleted; the standard `resolveAllAsSkillsNeutral` / `resolveCommands` paths now emit the skill / command naturally. Triggered by external user report: `trellis init --zcode` produced neither `/trellis:start` nor a `trellis-start` skill.\n- fix(workflow.md): add ZCode and Reasonix to the platform-matrix blocks they were missing from. 13 edit points in `packages/cli/src/templates/trellis/workflow.md`: B1/B3/B5/B7/B12 sub-agent dispatch blocks (Active Task Routing, Phase 1.2 Research, Phase 1.3 Configure context, Phase 1.5 Completion criteria, Phase 2.2 Quality check), B9 class-2 pull-based block (`[codex-sub-agent]` → `[codex-sub-agent, ZCode, Reasonix]`), and the line 186 prose enumeration. B8 (`hook/plugin auto-handles`) deliberately left unchanged — that claim is false for pull-based platforms.\n- fix(kiro): wire per-turn workflow injection for the main session. Pre-0.6.4 Kiro projects had no deterministic Trellis activation — only the three sub-agent JSONs registered `agentSpawn` hooks, the main session had none. Adds main agent `.kiro/agents/trellis.json` (`userPromptSubmit` → `inject-workflow-state.py`, `agentSpawn` → `session-start.py`, `workflow.md` as always-loaded resource) and IDE `.kiro/hooks/trellis-workflow-state.kiro.hook` (promptSubmit → runCommand). `inject-workflow-state.py` + `session-start.py` add an isolated `platform == \"kiro\"` branch that prints plain stdout (Kiro injects it as context; no `hookSpecificOutput` envelope); other platforms byte-unchanged. `SHARED_HOOKS_BY_PLATFORM.kiro` gains both scripts.",
|
|
7
|
+
"migrations": [],
|
|
8
|
+
"notes": "Two bug fixes. No `--migrate` required.\n\nKiro users: existing projects must run `trellis update` to receive the new main-session agent and hook (`.kiro/agents/trellis.json`, `.kiro/hooks/trellis-workflow-state.kiro.hook`, updated shared hooks).\n\nZCode / OpenCode / Reasonix users: `trellis update` produces the previously missing `trellis-start` skill / `/trellis:start` slash command. Codex output is byte-identical (same template, same resolver, same wrapper — `update` will not flag user-modified).\n\nInstall: `npm install -g @mindfoldhq/trellis`"
|
|
9
|
+
}
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
Trellis StatusLine — project-level status display for Claude Code.
|
|
5
|
+
|
|
6
|
+
Reads Claude Code session JSON from stdin + Trellis task data from filesystem.
|
|
7
|
+
Outputs 1-2 lines:
|
|
8
|
+
With active task: [P1] Task title (status) + info line
|
|
9
|
+
Without task: info line only
|
|
10
|
+
Info line: model · ctx% · branch · duration · developer · tasks · rate limits
|
|
11
|
+
When COLUMNS (injected by Claude Code v2.1.153+) is too narrow for the info
|
|
12
|
+
line, the rate-limit segments move to their own line via an explicit "\n".
|
|
13
|
+
"""
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import json
|
|
17
|
+
import os
|
|
18
|
+
import re
|
|
19
|
+
import subprocess
|
|
20
|
+
import sys
|
|
21
|
+
import time
|
|
22
|
+
from datetime import datetime
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
|
|
25
|
+
# Fix: Windows Python defaults to GBK encoding, which corrupts UTF-8
|
|
26
|
+
# characters like the middle dot (·). Wrap stdout/stderr with UTF-8.
|
|
27
|
+
if sys.platform == "win32":
|
|
28
|
+
for stream in (sys.stdout, sys.stderr):
|
|
29
|
+
reconfigure = getattr(stream, "reconfigure", None)
|
|
30
|
+
if callable(reconfigure):
|
|
31
|
+
reconfigure(encoding="utf-8", errors="replace")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _read_text(path: Path) -> str:
|
|
35
|
+
try:
|
|
36
|
+
return path.read_text(encoding="utf-8").strip()
|
|
37
|
+
except (FileNotFoundError, PermissionError, OSError):
|
|
38
|
+
return ""
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _read_json(path: Path) -> dict:
|
|
42
|
+
text = _read_text(path)
|
|
43
|
+
if not text:
|
|
44
|
+
return {}
|
|
45
|
+
try:
|
|
46
|
+
return json.loads(text)
|
|
47
|
+
except (json.JSONDecodeError, ValueError):
|
|
48
|
+
return {}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _normalize_task_ref(task_ref: str) -> str:
|
|
52
|
+
normalized = task_ref.strip()
|
|
53
|
+
if not normalized:
|
|
54
|
+
return ""
|
|
55
|
+
|
|
56
|
+
path_obj = Path(normalized)
|
|
57
|
+
if path_obj.is_absolute():
|
|
58
|
+
return str(path_obj)
|
|
59
|
+
|
|
60
|
+
normalized = normalized.replace("\\", "/")
|
|
61
|
+
while normalized.startswith("./"):
|
|
62
|
+
normalized = normalized[2:]
|
|
63
|
+
|
|
64
|
+
if normalized.startswith("tasks/"):
|
|
65
|
+
return f".trellis/{normalized}"
|
|
66
|
+
|
|
67
|
+
return normalized
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _resolve_task_dir(trellis_dir: Path, task_ref: str) -> Path:
|
|
71
|
+
normalized = _normalize_task_ref(task_ref)
|
|
72
|
+
path_obj = Path(normalized)
|
|
73
|
+
if path_obj.is_absolute():
|
|
74
|
+
return path_obj
|
|
75
|
+
if normalized.startswith(".trellis/"):
|
|
76
|
+
return trellis_dir.parent / path_obj
|
|
77
|
+
return trellis_dir / "tasks" / path_obj
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _find_trellis_dir() -> Path | None:
|
|
81
|
+
"""Walk up from cwd to find .trellis/ directory."""
|
|
82
|
+
current = Path.cwd()
|
|
83
|
+
for parent in [current, *current.parents]:
|
|
84
|
+
candidate = parent / ".trellis"
|
|
85
|
+
if candidate.is_dir():
|
|
86
|
+
return candidate
|
|
87
|
+
return None
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def _get_current_task(trellis_dir: Path) -> dict | None:
|
|
91
|
+
"""Load current task info through Trellis' active task resolver."""
|
|
92
|
+
return _get_current_task_for_input(trellis_dir, {})
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _get_current_task_for_input(trellis_dir: Path, cc_data: dict) -> dict | None:
|
|
96
|
+
"""Load current task info for the Claude Code session JSON."""
|
|
97
|
+
scripts_dir = trellis_dir / "scripts"
|
|
98
|
+
if str(scripts_dir) not in sys.path:
|
|
99
|
+
sys.path.insert(0, str(scripts_dir))
|
|
100
|
+
try:
|
|
101
|
+
from common.active_task import resolve_active_task # type: ignore[import-not-found]
|
|
102
|
+
except Exception:
|
|
103
|
+
return None
|
|
104
|
+
|
|
105
|
+
active = resolve_active_task(trellis_dir.parent, cc_data, platform="claude")
|
|
106
|
+
if not active.task_path:
|
|
107
|
+
return None
|
|
108
|
+
|
|
109
|
+
task_path = _resolve_task_dir(trellis_dir, active.task_path)
|
|
110
|
+
if active.stale:
|
|
111
|
+
return {
|
|
112
|
+
"title": task_path.name,
|
|
113
|
+
"status": "stale",
|
|
114
|
+
"priority": "P?",
|
|
115
|
+
"source": active.source,
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
task_data = _read_json(task_path / "task.json")
|
|
119
|
+
if not task_data:
|
|
120
|
+
return None
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
"title": task_data.get("title") or task_data.get("name") or "unknown",
|
|
124
|
+
"status": task_data.get("status", "unknown"),
|
|
125
|
+
"priority": task_data.get("priority", "P2"),
|
|
126
|
+
"source": active.source,
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def _count_active_tasks(trellis_dir: Path) -> int:
|
|
131
|
+
"""Count non-archived task directories with valid task.json."""
|
|
132
|
+
tasks_dir = trellis_dir / "tasks"
|
|
133
|
+
if not tasks_dir.is_dir():
|
|
134
|
+
return 0
|
|
135
|
+
count = 0
|
|
136
|
+
for d in tasks_dir.iterdir():
|
|
137
|
+
if d.is_dir() and d.name != "archive" and (d / "task.json").is_file():
|
|
138
|
+
count += 1
|
|
139
|
+
return count
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def _get_developer(trellis_dir: Path) -> str:
|
|
143
|
+
content = _read_text(trellis_dir / ".developer")
|
|
144
|
+
if not content:
|
|
145
|
+
return "unknown"
|
|
146
|
+
for line in content.splitlines():
|
|
147
|
+
if line.startswith("name="):
|
|
148
|
+
return line[5:].strip()
|
|
149
|
+
return content.splitlines()[0].strip() or "unknown"
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def _get_git_branch() -> str:
|
|
153
|
+
try:
|
|
154
|
+
result = subprocess.run(
|
|
155
|
+
["git", "branch", "--show-current"],
|
|
156
|
+
capture_output=True, text=True, timeout=3,
|
|
157
|
+
)
|
|
158
|
+
return result.stdout.strip() if result.returncode == 0 else ""
|
|
159
|
+
except (FileNotFoundError, subprocess.TimeoutExpired):
|
|
160
|
+
return ""
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def _format_ctx_size(size: int) -> str:
|
|
164
|
+
if size >= 1_000_000:
|
|
165
|
+
return f"{size // 1_000_000}M"
|
|
166
|
+
if size >= 1_000:
|
|
167
|
+
return f"{size // 1_000}K"
|
|
168
|
+
return str(size)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def _format_duration(ms: int) -> str:
|
|
172
|
+
secs = ms // 1000
|
|
173
|
+
hours, remainder = divmod(secs, 3600)
|
|
174
|
+
mins = remainder // 60
|
|
175
|
+
if hours > 0:
|
|
176
|
+
return f"{hours}h{mins}m"
|
|
177
|
+
return f"{mins}m"
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def _format_remaining(secs: int) -> str:
|
|
181
|
+
if secs <= 0:
|
|
182
|
+
return ""
|
|
183
|
+
days, remainder = divmod(secs, 86400)
|
|
184
|
+
hours, remainder = divmod(remainder, 3600)
|
|
185
|
+
mins = remainder // 60
|
|
186
|
+
if days > 0:
|
|
187
|
+
return f"{days}d{hours}h"
|
|
188
|
+
if hours > 0:
|
|
189
|
+
return f"{hours}h{mins}m"
|
|
190
|
+
return f"{mins}m"
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def _parse_resets_at(value: object) -> int:
|
|
194
|
+
"""`resets_at` is epoch seconds (int/float, possibly stringified) or an
|
|
195
|
+
ISO-8601 timestamp depending on Claude Code version. Return epoch
|
|
196
|
+
seconds, or 0 when absent/unparseable (countdown is then omitted)."""
|
|
197
|
+
if isinstance(value, (int, float)):
|
|
198
|
+
return int(value)
|
|
199
|
+
if isinstance(value, str) and value:
|
|
200
|
+
try:
|
|
201
|
+
return int(float(value))
|
|
202
|
+
except ValueError:
|
|
203
|
+
pass
|
|
204
|
+
try:
|
|
205
|
+
parsed = datetime.fromisoformat(value.replace("Z", "+00:00"))
|
|
206
|
+
return int(parsed.timestamp())
|
|
207
|
+
except ValueError:
|
|
208
|
+
pass
|
|
209
|
+
return 0
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def _rate_limit_part(label: str, window: dict, now: int) -> str:
|
|
213
|
+
try:
|
|
214
|
+
pct = int(float(window.get("used_percentage"))) # pyright: ignore[reportArgumentType]
|
|
215
|
+
except (TypeError, ValueError):
|
|
216
|
+
return ""
|
|
217
|
+
part = f"{label} {pct}%"
|
|
218
|
+
remaining = _format_remaining(_parse_resets_at(window.get("resets_at")) - now)
|
|
219
|
+
if remaining:
|
|
220
|
+
part += f" \033[90m(reset {remaining})\033[0m"
|
|
221
|
+
return part
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
_ANSI_RE = re.compile(r"\x1b\[[0-9;]*m")
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def _visible_len(s: str) -> int:
|
|
228
|
+
"""Length of s with ANSI escape sequences stripped."""
|
|
229
|
+
return len(_ANSI_RE.sub("", s))
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def _terminal_width() -> int | None:
|
|
233
|
+
"""Terminal width from the COLUMNS env var, or None.
|
|
234
|
+
|
|
235
|
+
The statusline stdin JSON has no width field and stdout is a pipe, so
|
|
236
|
+
the COLUMNS env var (injected by Claude Code v2.1.153+) is the only
|
|
237
|
+
width signal. Absent or malformed values return None."""
|
|
238
|
+
try:
|
|
239
|
+
width = int(os.environ.get("COLUMNS", ""))
|
|
240
|
+
except ValueError:
|
|
241
|
+
return None
|
|
242
|
+
return width if width > 0 else None
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def main() -> None:
|
|
246
|
+
# Read Claude Code session JSON from stdin
|
|
247
|
+
try:
|
|
248
|
+
cc_data = json.loads(sys.stdin.read())
|
|
249
|
+
except (json.JSONDecodeError, ValueError):
|
|
250
|
+
cc_data = {}
|
|
251
|
+
|
|
252
|
+
trellis_dir = _find_trellis_dir()
|
|
253
|
+
SEP = " \033[90m·\033[0m "
|
|
254
|
+
|
|
255
|
+
# --- Trellis data ---
|
|
256
|
+
task = _get_current_task_for_input(trellis_dir, cc_data) if trellis_dir else None
|
|
257
|
+
dev = _get_developer(trellis_dir) if trellis_dir else ""
|
|
258
|
+
task_count = _count_active_tasks(trellis_dir) if trellis_dir else 0
|
|
259
|
+
|
|
260
|
+
# --- CC session data ---
|
|
261
|
+
model = cc_data.get("model", {}).get("display_name", "?")
|
|
262
|
+
ctx_pct = int(cc_data.get("context_window", {}).get("used_percentage") or 0)
|
|
263
|
+
ctx_size = _format_ctx_size(cc_data.get("context_window", {}).get("context_window_size") or 0)
|
|
264
|
+
duration = _format_duration(cc_data.get("cost", {}).get("total_duration_ms") or 0)
|
|
265
|
+
branch = _get_git_branch()
|
|
266
|
+
|
|
267
|
+
# Avoid "Opus 4.6 (1M context) (1M)"
|
|
268
|
+
if re.search(r"\d+[KMG]\b", model, re.IGNORECASE):
|
|
269
|
+
model_label = model
|
|
270
|
+
else:
|
|
271
|
+
model_label = f"{model} ({ctx_size})"
|
|
272
|
+
|
|
273
|
+
# Context % with color
|
|
274
|
+
if ctx_pct >= 90:
|
|
275
|
+
ctx_color = "\033[31m"
|
|
276
|
+
elif ctx_pct >= 70:
|
|
277
|
+
ctx_color = "\033[33m"
|
|
278
|
+
else:
|
|
279
|
+
ctx_color = "\033[32m"
|
|
280
|
+
|
|
281
|
+
# Build info line: model · ctx · branch · duration · dev · tasks [· rate limits]
|
|
282
|
+
parts = [
|
|
283
|
+
model_label,
|
|
284
|
+
f"ctx {ctx_color}{ctx_pct}%\033[0m",
|
|
285
|
+
]
|
|
286
|
+
if branch:
|
|
287
|
+
parts.append(f"\033[35m{branch}\033[0m")
|
|
288
|
+
parts.append(duration)
|
|
289
|
+
if dev:
|
|
290
|
+
parts.append(f"\033[32m{dev}\033[0m")
|
|
291
|
+
if task_count:
|
|
292
|
+
parts.append(f"{task_count} task(s)")
|
|
293
|
+
|
|
294
|
+
now = int(time.time())
|
|
295
|
+
rate_limits = cc_data.get("rate_limits", {})
|
|
296
|
+
rate_parts: list[str] = []
|
|
297
|
+
for label, key in (("5h", "five_hour"), ("7d", "seven_day")):
|
|
298
|
+
part = _rate_limit_part(label, rate_limits.get(key) or {}, now)
|
|
299
|
+
if part:
|
|
300
|
+
rate_parts.append(part)
|
|
301
|
+
|
|
302
|
+
info_line = SEP.join(parts + rate_parts)
|
|
303
|
+
|
|
304
|
+
# Output: task line (only if active) + info line
|
|
305
|
+
if task:
|
|
306
|
+
source = str(task.get("source") or "")
|
|
307
|
+
source_tag = "session" if source.startswith("session:") else source
|
|
308
|
+
source_suffix = f" \033[90m[{source_tag}]\033[0m" if source_tag else ""
|
|
309
|
+
print(f"\033[36m[{task['priority']}]\033[0m {task['title']} \033[33m({task['status']})\033[0m{source_suffix}")
|
|
310
|
+
|
|
311
|
+
# Claude Code's status-bar height counts only "\n" characters, so a
|
|
312
|
+
# visually wrapped long line misaligns rows. When the host provides a
|
|
313
|
+
# terminal width and the info line would overflow, split the rate-limit
|
|
314
|
+
# segments onto their own line with an explicit "\n" instead.
|
|
315
|
+
width = _terminal_width()
|
|
316
|
+
if width is not None and rate_parts and _visible_len(info_line) > width:
|
|
317
|
+
print(SEP.join(parts))
|
|
318
|
+
print(SEP.join(rate_parts))
|
|
319
|
+
else:
|
|
320
|
+
print(info_line)
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
if __name__ == "__main__":
|
|
324
|
+
main()
|
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
* Directory structure:
|
|
5
5
|
* claude/
|
|
6
6
|
* ├── agents/ # Sub-agent definitions
|
|
7
|
+
* ├── hooks/ # Claude-only opt-in hooks (statusline.py)
|
|
7
8
|
* └── settings.json # Settings configuration
|
|
8
9
|
*
|
|
9
|
-
*
|
|
10
|
+
* Default hooks come from shared-hooks/ (unified with other platforms).
|
|
10
11
|
*/
|
|
11
12
|
export declare const settingsTemplate: string;
|
|
12
13
|
export interface AgentTemplate {
|
|
@@ -19,4 +20,12 @@ export interface SettingsTemplate {
|
|
|
19
20
|
}
|
|
20
21
|
export declare function getAllAgents(): AgentTemplate[];
|
|
21
22
|
export declare function getSettingsTemplate(): SettingsTemplate;
|
|
23
|
+
/**
|
|
24
|
+
* Opt-in statusLine hook, installed only via `trellis init --with-statusline`.
|
|
25
|
+
*
|
|
26
|
+
* Lives under claude/hooks/ (not shared-hooks/) because `statusLine` is a
|
|
27
|
+
* Claude-only event, and is intentionally NOT part of `collectTemplates` —
|
|
28
|
+
* `trellis update` must never force-install it on opted-out projects.
|
|
29
|
+
*/
|
|
30
|
+
export declare function getStatuslineHook(): string;
|
|
22
31
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/claude/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/claude/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAqBH,eAAO,MAAM,gBAAgB,QAAgC,CAAC;AAE9D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,YAAY,IAAI,aAAa,EAAE,CAa9C;AAED,wBAAgB,mBAAmB,IAAI,gBAAgB,CAKtD;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C"}
|
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
* Directory structure:
|
|
5
5
|
* claude/
|
|
6
6
|
* ├── agents/ # Sub-agent definitions
|
|
7
|
+
* ├── hooks/ # Claude-only opt-in hooks (statusline.py)
|
|
7
8
|
* └── settings.json # Settings configuration
|
|
8
9
|
*
|
|
9
|
-
*
|
|
10
|
+
* Default hooks come from shared-hooks/ (unified with other platforms).
|
|
10
11
|
*/
|
|
11
12
|
import { readdirSync, readFileSync } from "node:fs";
|
|
12
13
|
import { dirname, join } from "node:path";
|
|
@@ -43,4 +44,14 @@ export function getSettingsTemplate() {
|
|
|
43
44
|
content: settingsTemplate,
|
|
44
45
|
};
|
|
45
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Opt-in statusLine hook, installed only via `trellis init --with-statusline`.
|
|
49
|
+
*
|
|
50
|
+
* Lives under claude/hooks/ (not shared-hooks/) because `statusLine` is a
|
|
51
|
+
* Claude-only event, and is intentionally NOT part of `collectTemplates` —
|
|
52
|
+
* `trellis update` must never force-install it on opted-out projects.
|
|
53
|
+
*/
|
|
54
|
+
export function getStatuslineHook() {
|
|
55
|
+
return readTemplate("hooks/statusline.py");
|
|
56
|
+
}
|
|
46
57
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/claude/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/claude/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;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;AAED,SAAS,SAAS,CAAC,GAAW;IAC5B,IAAI,CAAC;QACH,OAAO,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,YAAY,CAAC,eAAe,CAAC,CAAC;AAY9D,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAoB,EAAE,CAAC;IACnC,MAAM,KAAK,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;IAElC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACrC,MAAM,OAAO,GAAG,YAAY,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;YAC/C,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,OAAO;QACL,UAAU,EAAE,eAAe;QAC3B,OAAO,EAAE,gBAAgB;KAC1B,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO,YAAY,CAAC,qBAAqB,CAAC,CAAC;AAC7C,CAAC"}
|
|
@@ -7,15 +7,15 @@ description: "Understand and customize the local Trellis architecture inside a u
|
|
|
7
7
|
|
|
8
8
|
This skill is for local Trellis users who have already run `trellis init` in a project. After reading it, an AI should understand the Trellis architecture, operating model, and customization entry points inside that user project, then modify the generated `.trellis/` and platform directory files according to the user's request.
|
|
9
9
|
|
|
10
|
-
Trellis v0.6 adds three architectural surfaces on top of the pre-v0.6 workflow / persistence / platform model. First, a multi-agent collaboration runtime: `trellis channel` coordinates multiple AI worker processes through project-scoped JSONL event logs at `~/.trellis/channels/<project>/<channel>/events.jsonl`, with worker OOM guard, forum/thread channels, durable idempotency keys, and bundled `.trellis/agents/{check,implement}.md` runtime definitions. Second, cross-session memory: `trellis mem list | search | context | extract | projects` reads raw Claude Code and
|
|
10
|
+
Trellis v0.6 adds three architectural surfaces on top of the pre-v0.6 workflow / persistence / platform model. First, a multi-agent collaboration runtime: `trellis channel` coordinates multiple AI worker processes through project-scoped JSONL event logs at `~/.trellis/channels/<project>/<channel>/events.jsonl`, with worker OOM guard, forum/thread channels, durable idempotency keys, and bundled `.trellis/agents/{check,implement}.md` runtime definitions. Second, cross-session memory: `trellis mem list | search | context | extract | projects` reads raw Claude Code, Codex, and Pi Agent JSONL already on disk, slices by `--phase brainstorm|implement|all`, and never uploads anything. Third, a dual-package npm release: `@mindfoldhq/trellis` (CLI) and `@mindfoldhq/trellis-core` (SDK with `/channel`, `/task`, `/mem`, `/testing` subpaths) ship in lockstep on one version. Treat these as first-class customization surfaces alongside the per-platform integration files.
|
|
11
11
|
|
|
12
12
|
The default operating scope is local files in the user project:
|
|
13
13
|
|
|
14
14
|
- `.trellis/`: workflow, config, tasks, spec, workspace, scripts, bundled runtime agents, and runtime state.
|
|
15
|
-
- Platform directories: `.claude/`, `.codex/`, `.cursor/`, `.opencode/`, `.kiro/`, `.gemini/`, `.qoder/`, `.codebuddy/`, `.github/`, `.factory/`, `.pi/`, `.reasonix/`, `.kilocode/`, `.agent/`, `.
|
|
15
|
+
- Platform directories: `.claude/`, `.codex/`, `.cursor/`, `.opencode/`, `.kiro/`, `.gemini/`, `.qoder/`, `.codebuddy/`, `.github/`, `.factory/`, `.pi/`, `.reasonix/`, `.kilocode/`, `.agent/`, `.devin/`, and similar directories. Pi additionally exposes a native `trellis_subagent` tool with `single` / `parallel` / `chain` dispatch modes, throttled progress cards, and `isTrellisAgent()` validation on top of the file layout. Reasonix stores both workflow skills and subagent skills as `.reasonix/skills/<name>/SKILL.md`; subagent skills carry `runAs: subagent` frontmatter.
|
|
16
16
|
- Shared skill layer: `.agents/skills/`.
|
|
17
17
|
- User-owned channel store outside the project tree: `~/.trellis/channels/<project>/<channel>/events.jsonl`.
|
|
18
|
-
- Raw platform conversation logs queryable via `trellis mem`: `~/.claude/projects
|
|
18
|
+
- Raw platform conversation logs queryable via `trellis mem`: `~/.claude/projects/`, `~/.codex/sessions/`, and `~/.pi/agent/sessions/` (OpenCode adapter degraded for the v0.6 line).
|
|
19
19
|
|
|
20
20
|
Do not assume the user has the Trellis source repository. Do not default to modifying the global npm install directory or `node_modules` — both `@mindfoldhq/trellis` and `@mindfoldhq/trellis-core` ship as published packages sharing one version and one git tag per release.
|
|
21
21
|
|
|
@@ -67,7 +67,7 @@ Do not assume the user has the Trellis source repository. Do not default to modi
|
|
|
67
67
|
- `.trellis/config.yaml` is the project-level Trellis configuration entry point. It hosts task lifecycle hooks (`hooks.after_create` / `after_start` / `after_finish` / `after_archive`), journal shape (`session_commit_message` / `max_journal_lines` / `session_auto_commit`), channel worker guard (`channel.worker_guard.idle_timeout` / `max_live_workers`), Codex dispatch mode (`codex.dispatch_mode: inline | sub-agent`), and the spec registry block (`registry.spec.source` + `registry.spec.template`).
|
|
68
68
|
- `.trellis/spec/` stores the user's project-specific coding conventions and design constraints. When `registry.spec` is set, files are refreshed by `trellis update`; local edits surface as "modified by user" conflicts in `.trellis/.template-hashes.json`.
|
|
69
69
|
- `.trellis/tasks/` stores task PRDs, design notes, implement plans, research files, and JSONL context. Tasks form parent/child trees: `task.py create --parent <slug>`, `task.py add-subtask <parent> <child>`, `task.py remove-subtask <parent> <child>`, and `task.py list-context <task>`. `task.py create` rejects a slug already present in `.trellis/tasks/archive/**`.
|
|
70
|
-
- `.trellis/workspace/` stores **deliberately written** developer journals. Raw cross-session dialogue is **not** stored here — it lives on disk under `~/.claude/projects
|
|
70
|
+
- `.trellis/workspace/` stores **deliberately written** developer journals. Raw cross-session dialogue is **not** stored here — it lives on disk under `~/.claude/projects/`, `~/.codex/sessions/`, and `~/.pi/agent/sessions/` and is recovered via `trellis mem search|extract|context`. The bundled `trellis-session-insight` skill teaches when to reach for `mem`.
|
|
71
71
|
- `.trellis/agents/{check,implement}.md` are bundled, platform-agnostic channel runtime agent definitions loaded by `trellis channel spawn --agent <name>`. Editable; `trellis update` backfills missing ones. Editing the per-platform `trellis-implement.md` / `trellis-check.md` does **not** change channel-runtime worker behavior.
|
|
72
72
|
- `~/.trellis/channels/<project>/<channel>/events.jsonl` is the channel runtime event log per project per channel. User-owned, file-locked sequence numbering, durable `idempotencyKey` support; never under `.trellis/`.
|
|
73
73
|
- Bundled multi-file skills (`trellis-meta`, `trellis-spec-bootstrap`, `trellis-session-insight`, `trellis-channel`) are auto-dispatched to every platform skill root by `getBundledSkillTemplates()` in `packages/cli/src/templates/common/index.ts`. Dropping a new directory under `packages/cli/src/templates/common/bundled-skills/` (upstream) ships it to every platform on the next `trellis update`.
|
|
@@ -24,6 +24,8 @@ When the user wants to change `trellis-research`, `trellis-implement`, or `trell
|
|
|
24
24
|
| CodeBuddy | `.codebuddy/agents/trellis-*.md` |
|
|
25
25
|
| Factory Droid | `.factory/droids/trellis-*.md` |
|
|
26
26
|
| Pi Agent | `.pi/agents/trellis-*.md` |
|
|
27
|
+
| Reasonix | `.reasonix/skills/trellis-*/SKILL.md` (subagent frontmatter) |
|
|
28
|
+
| ZCode | `.zcode/cli/agents/trellis-*.md` |
|
|
27
29
|
|
|
28
30
|
Use the actual paths in the user project as authoritative.
|
|
29
31
|
|
|
@@ -89,7 +89,8 @@ If a command only repeats workflow rules, prefer making it reference/read `.trel
|
|
|
89
89
|
| Factory Droid | `.factory/skills/`, `.factory/commands/` |
|
|
90
90
|
| Pi Agent | `.pi/skills/` |
|
|
91
91
|
| Reasonix | `.reasonix/skills/` (no separate commands dir; slash commands built into the platform) |
|
|
92
|
-
|
|
|
92
|
+
| ZCode | `.agents/skills/`, `.zcode/commands/` |
|
|
93
|
+
| Kilo / Antigravity / Devin | workflows + skills |
|
|
93
94
|
|
|
94
95
|
Every directory above is a deploy target for the four bundled skills. Each platform receives a full copy on `trellis init` and refresh on `trellis update`; nothing has to be wired by hand.
|
|
95
96
|
|
package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/overview.md
CHANGED
|
@@ -17,7 +17,7 @@ This directory is for local AI working in a user project where Trellis was insta
|
|
|
17
17
|
|
|
18
18
|
## General Operation Order
|
|
19
19
|
|
|
20
|
-
1. **Confirm platform and directories**: inspect which directories exist, such as `.claude/`, `.codex/`, `.cursor/`.
|
|
20
|
+
1. **Confirm platform and directories**: inspect which directories exist, such as `.claude/`, `.codex/`, `.cursor/`, `.zcode/`.
|
|
21
21
|
2. **Confirm the current active task**: run `python3 ./.trellis/scripts/task.py current --source`.
|
|
22
22
|
3. **Read the local source of truth**: prefer `.trellis/workflow.md`, `.trellis/config.yaml`, and relevant platform files.
|
|
23
23
|
4. **Modify narrowly**: edit only files related to the user's request.
|
|
@@ -32,7 +32,7 @@ This directory is for local AI working in a user project where Trellis was insta
|
|
|
32
32
|
| Task material | `.trellis/tasks/<task>/` |
|
|
33
33
|
| Project specs | `.trellis/spec/` |
|
|
34
34
|
| Runtime scripts | `.trellis/scripts/` |
|
|
35
|
-
| Platform integration | `.claude/`, `.codex/`, `.cursor/`, `.opencode/`, and similar directories |
|
|
35
|
+
| Platform integration | `.claude/`, `.codex/`, `.cursor/`, `.opencode/`, `.zcode/`, and similar directories |
|
|
36
36
|
| Shared skill | `.agents/skills/` |
|
|
37
37
|
|
|
38
38
|
## Things Not To Do By Default
|
|
@@ -23,7 +23,7 @@ The set is discovered at runtime by listing directories under `templates/common/
|
|
|
23
23
|
| Skill | Purpose |
|
|
24
24
|
| --- | --- |
|
|
25
25
|
| `trellis-meta` | This skill. Explains the local Trellis architecture and customization entry points to an AI working inside a user project. |
|
|
26
|
-
| `trellis-session-insight` | Wraps the `trellis mem` CLI so an AI knows when and how to reach into past Claude Code / Codex conversation logs. |
|
|
26
|
+
| `trellis-session-insight` | Wraps the `trellis mem` CLI so an AI knows when and how to reach into past Claude Code / Codex / Pi Agent conversation logs. |
|
|
27
27
|
| `trellis-spec-bootstrap` | Platform-neutral workflow for creating or refreshing `.trellis/spec/` from the real codebase (with optional GitNexus / ABCoder integration). |
|
|
28
28
|
| `trellis-channel` | Capability skill teaching an AI when to reach for `trellis channel` for multi-agent collaboration, forum/thread persistent boards, and dispatcher-wait patterns. |
|
|
29
29
|
|
|
@@ -45,7 +45,7 @@ Each platform configurator calls `writeSkills(<root>, <workflowSkills>, resolveB
|
|
|
45
45
|
| Copilot | `.github/skills/<skill>/` | `configureCopilot` |
|
|
46
46
|
| Droid | `.factory/skills/<skill>/` | `configureDroid` |
|
|
47
47
|
| Antigravity | `.agent/skills/<skill>/` | `configureAntigravity` |
|
|
48
|
-
|
|
|
48
|
+
| Devin | `.devin/skills/<skill>/` | `configureDevin` |
|
|
49
49
|
| Kilo | `.kilocode/skills/<skill>/` | `configureKilo` |
|
|
50
50
|
| OpenCode | (handled by `collectOpenCodeTemplates`) | Uses the same `resolveBundledSkills(ctx)` output |
|
|
51
51
|
| Pi, Reasonix | (their own collectors) | Same `resolveBundledSkills(ctx)` output |
|
|
@@ -69,7 +69,7 @@ The mechanism that auto-dispatches bundled skills to platform skill roots lives
|
|
|
69
69
|
- `writeSkills(skillsRoot, workflowSkills, bundledSkills)` writes both workflow skills and bundled skill files under `skillsRoot`.
|
|
70
70
|
- `collectSkillTemplates(skillsRoot, workflowSkills, bundledSkills)` returns the same shape as a `Map<filePath, content>` for the update / hash pipeline.
|
|
71
71
|
|
|
72
|
-
Every platform configurator that supports skills imports both helpers (see `claude.ts`, `cursor.ts`, `codex.ts`, `gemini.ts`, `kiro.ts`, `qoder.ts`, `codebuddy.ts`, `copilot.ts`, `droid.ts`, `antigravity.ts`, `
|
|
72
|
+
Every platform configurator that supports skills imports both helpers (see `claude.ts`, `cursor.ts`, `codex.ts`, `gemini.ts`, `kiro.ts`, `qoder.ts`, `codebuddy.ts`, `copilot.ts`, `droid.ts`, `antigravity.ts`, `devin.ts`, `kilo.ts`). The `index.ts` `PLATFORM_FUNCTIONS` registry also calls `resolveBundledSkills(ctx)` inside each `collectTemplates` closure so `trellis update` tracking stays consistent.
|
|
73
73
|
|
|
74
74
|
## Adding a New Bundled Skill
|
|
75
75
|
|
|
@@ -41,9 +41,9 @@ Different platforms generate different directories. Common categories:
|
|
|
41
41
|
| --- | --- | --- |
|
|
42
42
|
| hooks | `.claude/hooks/`, `.codex/hooks/`, `.cursor/hooks/` | Inject session context, workflow-state, and sub-agent context. |
|
|
43
43
|
| settings | `.claude/settings.json`, `.codex/hooks.json`, `.qoder/settings.json` | Tell the platform when to run hooks or plugins. |
|
|
44
|
-
| agents | `.claude/agents/`, `.codex/agents/`, `.kiro/agents/` | Define agents such as `trellis-research`, `trellis-implement`, and `trellis-check`. |
|
|
44
|
+
| agents | `.claude/agents/`, `.codex/agents/`, `.kiro/agents/`, `.zcode/cli/agents/` | Define agents such as `trellis-research`, `trellis-implement`, and `trellis-check`. |
|
|
45
45
|
| skills | `.claude/skills/`, `.agents/skills/`, `.qoder/skills/` | Skills that auto-trigger or can be read by AI. |
|
|
46
|
-
| commands/prompts/workflows | `.cursor/commands/`, `.github/prompts/`, `.
|
|
46
|
+
| commands/prompts/workflows | `.cursor/commands/`, `.github/prompts/`, `.devin/workflows/`, `.zcode/commands/` | Explicit user-invoked command or workflow entry points. |
|
|
47
47
|
|
|
48
48
|
When modifying a platform directory, also confirm whether `.trellis/workflow.md` still describes the same flow.
|
|
49
49
|
|