Skill-first template architecture
Commands and skills now live underpackages/cli/src/templates/common/ as a single source of truth (3 commands + 5 skills). All 13 platforms resolve from common/ through per-platform adapters. Eliminates the prior N-copies-of-same-content drift that caused stale commands to linger on some platforms but not others.
Two reusable helpers landed alongside:
createTemplateReader()(intemplate-utils.ts) — factory used by 6 platform template modules, replacing boilerplateimport { readFileSync } from "fs"scaffolding. UsesfileURLToPathcorrectly so paths with spaces / on Windows resolve.writeSharedHooks()+writeAgents()+writeSkills()(inconfigurators/shared.ts) — three-line calls that configurators use to emit their hook / agent / skill set, instead of bespoke file-copy loops.
Hooks + agents for 7 new platforms
Qoder, CodeBuddy, Factory Droid, Cursor, Gemini CLI, Kiro, and GitHub Copilot go from commands-only to fully agent-capable. Each ships:- Sub-agent definitions (implement / check / research) in the platform’s native format
- Hook configuration wired via
shared-hooks/Python scripts (session-start, inject-subagent-context, statusline) — single implementation, cross-platform output adapters
AGENT_DEBUG, spec.jsonl/research.jsonl reads, hardcoded check-cross-layer.md references) had accumulated across releases.
Sub-agent context injection: class-1 hook vs class-2 pull-based
Codex, Copilot, Gemini, and Qoder (class-2) can’t reliably receive hook-modified sub-agent prompts:- Codex
PreToolUseonly fires for Bash;CollabAgentSpawnhook unimplemented (#15486) - Copilot
preToolUsesilently ignored on sub-agents (#2392 / #2540) - Gemini’s
BeforeToolcan’t see the caller’s context (#18128) - Qoder has no Task tool + context isolation
.current-task + prd.md + implement.jsonl/check.jsonl itself on first turn. Class-1 platforms (Claude / Cursor / OpenCode / Kiro / CodeBuddy / Droid) continue with hook-based push injection. Both paths live in shared infrastructure (applyPullBasedPreludeMarkdown / applyPullBasedPreludeToml) so future platforms pick one and it works.
Workflow enforcement v2: per-turn breadcrumb hook
Newinject-workflow-state.py shared hook fires on every user prompt (UserPromptSubmit equivalent on 8 platforms; chat.message on OpenCode Bun plugin). It injects a ~200-byte <workflow-state> block nudging AI toward the next workflow step based on the active task’s status.
Breadcrumb content is pulled from workflow.md [workflow-state:STATUS]...[/workflow-state:STATUS] blocks — users who fork the workflow edit one markdown file, not the hook Python. Covers four states: no_task / planning / in_progress / completed. Custom hyphenated statuses (in-review, blocked-by-team) are recognized via the STATUS regex [A-Za-z0-9_-]+. Unknown statuses emit a generic fallback instead of silent-exiting — the hook never leaves a conversation without guidance.
Three-tier fallback (workflow.md missing → partial tag → unknown status) so the hook never breaks.
Kiro is the one platform downgraded: its agentSpawn hook is per-sub-agent only, and there’s no upstream equivalent for main-session per-turn injection. Sub-agent context injection still works; per-turn breadcrumb is awaiting upstream support.
SessionStart payload restructure
The SessionStart<workflow> block grew from 2.7 KB to 9.5 KB by inlining Phase 1/2/3 step bodies — AI now has step-level how-to up front instead of lazy-loading via get_context.py --mode phase --step X.Y. Funded by shrinking <guidelines> from 10.9 KB to 4.6 KB: the cross-package guides/index.md stays inlined, but other spec/<pkg>/<layer>/index.md files are listed as paths only. Rationale: sub-agents get their specific specs via jsonl injection, and when the main agent needs details it reads on demand.
Total session-start payload: 16.7 KB — under Claude Code’s ~20 KB additionalContext truncation threshold.
workflow.md itself slimmed 17 KB → 14 KB: English-only (was bilingual), removed What is Trellis intro + File Structure tree + redundant Best Practices section, task.py command table expanded from 5 → 16 subcommands per PR #169’s grouping (lifecycle / context / metadata / hierarchy / PR) with a --help pointer for future-proofing.
Legacy cleanup (126-entry safe-file-delete migration)
This release removes four categories of primitives whose replacement is now the default:- iFlow platform — CLI unmaintained; entire
.iflow/tree + template source removed - Multi-agent pipeline (
.trellis/scripts/multi_agent/+worktree.yaml) — all major CLIs now ship their own worktree support; Trellis doesn’t need to reimplement - Ralph Loop hook (
ralph-loop.py) — SubagentStop + exit-code-2 enforcement not portable across platforms; check agent’s self-fix loop is sufficient - Six commands + three sub-agents —
parallel(superseded by native worktrees),onboard/create-command/integrate-skill(low usage),check-cross-layer(merged intocheck),record-session(subsumed by/finish-work);dispatch/debug/planagents (replaced by skill routing)
allowed_hashes pulled from historical git versions, so users on any past 0.3.x / 0.4.x version get a clean migration).
Command → skill migration (80 new manifest entries)
The 5 skills that users no longer invoke by hand (before-dev / brainstorm / break-loop / check / update-spec) now live under <platform>/skills/trellis-<name>/SKILL.md on every platform. Without migration, a user upgrading from 0.4.x would end up with both the old command file and the new skill file side-by-side. The manifest closes this cleanly:
- 65 rename entries (13 platforms × 5 commands) — preserves user customizations via move + subsequent template-write prompt (not plain delete)
- 3 rename entries for
finish-workon skill-only platforms (.kiro/.qoder/.agentsshared layer) — gains thetrellis-prefix too - 10 safe-file-delete for the old
startcommand across agent-capable and skill-only platforms — session-start hook replaces the command’s role - 2 safe-file-delete for the legacy
improve-utskill (.agent/workflows/+.agents/skills/)
MigrationItem gained a new reason? field — version-specific context (e.g. “Trellis 0.4.0 skipped hashing this path, so pristine copies show as modified”) is authored inline in the manifest and rendered in the confirm prompt. No more hardcoded version-hints rotting in update.ts.
--migrate is now required for breaking releases
Running trellis update against a project whose installed version spans a manifest flagged breaking: true + recommendMigrate: true exits 1 with a clear error telling the user to add --migrate. Previously update would silently skip the rename/delete entries and still bump the .version stamp, leaving the project half-migrated (stale old paths next to new templates). --dry-run bypasses the gate so users can still preview.
Confirm-prompt redesign
When a migration file trips the modified-hash check, the interactive prompt now shows:- What the migration does (from the manifest
description) - Why prompted — per-entry
reasonfrom the manifest, or a generic fallback - Recommendation on each option (Backup / Rename / Skip) including the consequence of skipping (stale path persists to future updates)
backup-rename instead of skip — pressing Enter never destroys user edits or leaves orphan files.
Bug fixes
- Backup no longer snapshots platform worktrees.
createFullBackupexcludes any/worktrees/or/worktree/path, so Claude Code’s.claude/worktrees/, Cursor’s.cursor/worktrees/, and Gemini CLI’s.gemini/worktrees/don’t get duplicated on everytrellis update(one backup could otherwise bloat to 100s of MB once worktrees are in use). copy-templatesbuild step leaks stale files. Addedcleanto the build chain (clean && tsc && copy-templates) so templates deleted fromsrc/stop lingering indist/and shipping to npm. Without this fix, safe-file-deletes fought re-writes from the stale dist templates in a loop.
Other notable changes
task.py createstops writing legacycurrent_phase/next_actionfields. FP-analysis outcome: workflow.md’s Phase N.M is documentation layering, not runtime state —task.json.statusis the single source of task-level state.inject-subagent-context.py’supdate_current_phase()function deleted — it was re-writing the legacycurrent_phasefield on every Task spawn, silently undoing the deprecation.- Codex hooks integration:
configureCodexnow auto-writes shared-hooks (was skipping them); stderr warning ontrellis init --codexaboutfeatures.codex_hooks = truerequirement in user’s~/.codex/config.toml. get_context.py --mode phase(no--step) returns Phase Index + Phase 1/2/3 bodies (was Phase Index only) — agent-less platforms (Kilo / Antigravity / Windsurf) running/startmanually get the same content as hook-based platforms.- Hook-path CWD robustness (partial):
inject-workflow-state.pywalks up from CWD to find.trellis/, fixing subdirectory / submodule CWD drift for this hook. Full coverage across all hooks is a post-beta task.
Spec docs updated
- platform-integration.md — new sections: Workflow State Injection (per-turn breadcrumb), Subagent Context Injection: Hook-based vs Pull-based, Guidelines: Paths-only vs Inline, Per-Turn Hook design principle (no silent-exit on “nothing to say”)
- quality-guidelines.md — new section: Schema Deprecation: Audit ALL Writers, Not Just the Creator (from a Codex cross-review finding where
cmd_createdropped a field but a hook kept re-writing it) - workflow.md — full English translation; slim structure; task.py 16-subcommand reference table
- directory-structure.md + script-conventions.md — multi-agent references removed
Tests
595 tests passing, lint + typecheck clean. 41 new tests since the first draft of this changelog: workflow-state per-turn breadcrumb (7 cases), Phase Index expansion, paths-only guidelines,update_current_phase deletion regression, UserPromptSubmit platform wiring invariants, breaking-change gate (3 cases: block / dry-run bypass / --migrate pass), 0.5.0-beta.0 manifest shape (65-entry coverage, per-platform path invariant, breaking+recommendMigrate flags), worktree backup exclusion (12 cases across platform conventions + user data + edge cases).
Deferred to follow-up beta / rc
- Kiro
agentSpawnhook output-format validation in real environment - Cursor / CodeBuddy / Droid sub-agent hook injection real-env testing
- Full hook-path CWD-robustness across all hooks (Windows cmd / PowerShell)
- Parent-child Trellis config for submodule / micro-service repos (issue #172)
Migration
Runtrellis update --migrate (the --migrate flag is required this release — 68 rename entries don’t auto-execute without it, and the new gate will exit 1 telling you to add it). Then the 138-entry safe-file-delete runs. User-modified files are preserved with warnings; only pristine Trellis-written files get cleaned up. Use trellis update --migrate --dry-run first if you want to preview.
/trellis:record-session users: this command is removed. Its single job (writing a session journal via add_session.py) is now Step 3 of /trellis:finish-work, which also covers Quality Gate and Commit reminders. Replace any aliases or scripts that invoke record-session with finish-work.
Codex users: enable features.codex_hooks = true in ~/.codex/config.toml to receive SessionStart + UserPromptSubmit breadcrumb injection. Without this flag hooks.json is silently ignored by Codex.
iFlow users: the .iflow/ directory will be removed. Copy it out first if you want to keep it.
Install: npm install -g @mindfoldhq/trellis@beta