diff --git a/.claude/hooks/statusline.py b/.claude/hooks/statusline.py new file mode 100644 index 00000000..696d6087 --- /dev/null +++ b/.claude/hooks/statusline.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Trellis StatusLine — project-level status display for Claude Code. + +Reads Claude Code session JSON from stdin + Trellis task data from filesystem. +Outputs 1-2 lines: + With active task: [P1] Task title (status) + info line + Without task: info line only +Info line: model · ctx% · branch · duration · developer · tasks · rate limits +""" +from __future__ import annotations + +import json +import re +import subprocess +import sys +from pathlib import Path + + +def _read_text(path: Path) -> str: + try: + return path.read_text(encoding="utf-8").strip() + except (FileNotFoundError, PermissionError, OSError): + return "" + + +def _read_json(path: Path) -> dict: + text = _read_text(path) + if not text: + return {} + try: + return json.loads(text) + except (json.JSONDecodeError, ValueError): + return {} + + +def _find_trellis_dir() -> Path | None: + """Walk up from cwd to find .trellis/ directory.""" + current = Path.cwd() + for parent in [current, *current.parents]: + candidate = parent / ".trellis" + if candidate.is_dir(): + return candidate + return None + + +def _get_current_task(trellis_dir: Path) -> dict | None: + """Load current task info. Returns dict with title/status/priority or None.""" + task_ref = _read_text(trellis_dir / ".current-task") + if not task_ref: + return None + + # Resolve task directory + task_path = Path(task_ref) if Path(task_ref).is_absolute() else trellis_dir.parent / task_ref + task_data = _read_json(task_path / "task.json") + if not task_data: + return None + + return { + "title": task_data.get("title") or task_data.get("name") or "unknown", + "status": task_data.get("status", "unknown"), + "priority": task_data.get("priority", "P2"), + } + + +def _count_active_tasks(trellis_dir: Path) -> int: + """Count non-archived task directories with valid task.json.""" + tasks_dir = trellis_dir / "tasks" + if not tasks_dir.is_dir(): + return 0 + count = 0 + for d in tasks_dir.iterdir(): + if d.is_dir() and d.name != "archive" and (d / "task.json").is_file(): + count += 1 + return count + + +def _get_developer(trellis_dir: Path) -> str: + content = _read_text(trellis_dir / ".developer") + if not content: + return "unknown" + for line in content.splitlines(): + if line.startswith("name="): + return line[5:].strip() + return content.splitlines()[0].strip() or "unknown" + + +def _get_git_branch() -> str: + try: + result = subprocess.run( + ["git", "branch", "--show-current"], + capture_output=True, text=True, timeout=3, + ) + return result.stdout.strip() if result.returncode == 0 else "" + except (FileNotFoundError, subprocess.TimeoutExpired): + return "" + + +def _format_ctx_size(size: int) -> str: + if size >= 1_000_000: + return f"{size // 1_000_000}M" + if size >= 1_000: + return f"{size // 1_000}K" + return str(size) + + +def _format_duration(ms: int) -> str: + secs = ms // 1000 + hours, remainder = divmod(secs, 3600) + mins = remainder // 60 + if hours > 0: + return f"{hours}h{mins}m" + return f"{mins}m" + + +def main() -> None: + # Read Claude Code session JSON from stdin + try: + cc_data = json.loads(sys.stdin.read()) + except (json.JSONDecodeError, ValueError): + cc_data = {} + + trellis_dir = _find_trellis_dir() + SEP = " \033[90m·\033[0m " + + # --- Trellis data --- + task = _get_current_task(trellis_dir) if trellis_dir else None + dev = _get_developer(trellis_dir) if trellis_dir else "" + task_count = _count_active_tasks(trellis_dir) if trellis_dir else 0 + + # --- CC session data --- + model = cc_data.get("model", {}).get("display_name", "?") + ctx_pct = int(cc_data.get("context_window", {}).get("used_percentage") or 0) + ctx_size = _format_ctx_size(cc_data.get("context_window", {}).get("context_window_size") or 0) + duration = _format_duration(cc_data.get("cost", {}).get("total_duration_ms") or 0) + branch = _get_git_branch() + + # Avoid "Opus 4.6 (1M context) (1M)" + if re.search(r"\d+[KMG]\b", model, re.IGNORECASE): + model_label = model + else: + model_label = f"{model} ({ctx_size})" + + # Context % with color + if ctx_pct >= 90: + ctx_color = "\033[31m" + elif ctx_pct >= 70: + ctx_color = "\033[33m" + else: + ctx_color = "\033[32m" + + # Build info line: model · ctx · branch · duration · dev · tasks [· rate limits] + parts = [ + model_label, + f"ctx {ctx_color}{ctx_pct}%\033[0m", + ] + if branch: + parts.append(f"\033[35m{branch}\033[0m") + parts.append(duration) + if dev: + parts.append(f"\033[32m{dev}\033[0m") + if task_count: + parts.append(f"{task_count} task(s)") + + five_hr = cc_data.get("rate_limits", {}).get("five_hour", {}).get("used_percentage") + if five_hr is not None: + parts.append(f"5h {int(five_hr)}%") + seven_day = cc_data.get("rate_limits", {}).get("seven_day", {}).get("used_percentage") + if seven_day is not None: + parts.append(f"7d {int(seven_day)}%") + + info_line = SEP.join(parts) + + # Output: task line (only if active) + info line + if task: + print(f"\033[36m[{task['priority']}]\033[0m {task['title']} \033[33m({task['status']})\033[0m") + print(info_line) + + +if __name__ == "__main__": + main() diff --git a/.claude/settings.json b/.claude/settings.json index d6ed2708..1e1f9904 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -1,4 +1,8 @@ { + "statusLine": { + "type": "command", + "command": "python3 .claude/hooks/statusline.py" + }, "hooks": { "SessionStart": [ { diff --git a/.codex/config.toml b/.codex/config.toml index a38658f8..e4ec8e30 100644 --- a/.codex/config.toml +++ b/.codex/config.toml @@ -1,5 +1,5 @@ # Project-scoped Codex defaults for Trellis workflows. -# Codex loads this after ~/.codex/config.toml when you work in this repository. +# Codex loads this after ~/.codex/config.toml when you work in this project. # Keep AGENTS.md as the primary project instruction file. project_doc_fallback_filenames = ["AGENTS.md"] diff --git a/.trellis/.template-hashes.json b/.trellis/.template-hashes.json index 43b84e56..0cd63962 100644 --- a/.trellis/.template-hashes.json +++ b/.trellis/.template-hashes.json @@ -77,5 +77,6 @@ ".agents/skills/onboard/SKILL.md": "ec6db142f763c81a3273be45b5d7726f695c32aaa5404e90dbd6e40aec92fb98", ".agents/skills/record-session/SKILL.md": "2f3781d894b7a45b517d36845fa18e6fac98acad40e77438a3d85760f1d7d247", ".agents/skills/start/SKILL.md": "8853e4ddc1681e043dec34be76c7c6fd961a3d52cbd0a2320225d72440425639", - ".agents/skills/update-spec/SKILL.md": "7ccf7d29ea26d28b0bd8af94ea5b8bfcddaddd9f2797f3becedbe5f3a0a9e9a7" + ".agents/skills/update-spec/SKILL.md": "7ccf7d29ea26d28b0bd8af94ea5b8bfcddaddd9f2797f3becedbe5f3a0a9e9a7", + ".codex/config.toml": "7543da7e1773a0f26bc9178716b34154fdc5fefd820fb184e7cb169f1910cc99" } \ No newline at end of file diff --git a/.trellis/.version b/.trellis/.version index 32a665cf..5e9ef6d0 100644 --- a/.trellis/.version +++ b/.trellis/.version @@ -1 +1 @@ -0.4.0-beta.7 \ No newline at end of file +0.4.0-beta.8 diff --git a/.trellis/tasks/03-24-py39-compat/prd.md b/.trellis/tasks/03-24-py39-compat/prd.md new file mode 100644 index 00000000..50b8cfc0 --- /dev/null +++ b/.trellis/tasks/03-24-py39-compat/prd.md @@ -0,0 +1,35 @@ +# fix: Python 3.9 compatibility — add future annotations + +## Goal + +Fix Python 3.9 compatibility issue (#113). Trellis Python scripts use `X | Y` union type syntax (PEP 604, Python 3.10+), causing runtime errors on Python 3.9. + +## Requirements + +- Add `from __future__ import annotations` to all 21 affected Python files in `.trellis/scripts/` +- Add the same to all corresponding template copies in `packages/cli/src/templates/trellis/scripts/` +- Verify both copies remain identical after changes +- Consider adding Python version check during `trellis init` + +## Affected Files (21) + +- add_session.py +- common/cli_adapter.py, config.py, developer.py, git.py, io.py +- common/packages_context.py, paths.py, registry.py, session_context.py +- common/task_context.py, task_queue.py, task_store.py, task_utils.py, tasks.py, types.py, worktree.py +- hooks/linear_sync.py +- multi_agent/create_pr.py, status_display.py, status_monitor.py + +## Acceptance Criteria + +- [ ] All scripts work on Python 3.9+ +- [ ] `from __future__ import annotations` added to all affected files +- [ ] Template copies identical to live scripts +- [ ] `pnpm test` passes +- [ ] No `tuple[...]` runtime usage (only in annotations) + +## Technical Notes + +- `from __future__ import annotations` makes all annotations strings (PEP 563), so `X | Y` works on 3.9 +- Must check for runtime type usage like `isinstance(x, str | int)` — those need `Union[str, int]` instead +- GitHub issue: #113 diff --git a/.trellis/tasks/03-24-py39-compat/task.json b/.trellis/tasks/03-24-py39-compat/task.json new file mode 100644 index 00000000..6847082b --- /dev/null +++ b/.trellis/tasks/03-24-py39-compat/task.json @@ -0,0 +1,47 @@ +{ + "id": "py39-compat", + "name": "py39-compat", + "title": "fix: Python 3.9 compatibility — add future annotations", + "description": "", + "status": "planning", + "dev_type": null, + "scope": null, + "package": "cli", + "priority": "P2", + "creator": "taosu", + "assignee": "taosu", + "createdAt": "2026-03-24", + "completedAt": null, + "branch": null, + "base_branch": "feat/v0.4.0-beta", + "worktree_path": null, + "current_phase": 0, + "next_action": [ + { + "phase": 1, + "action": "implement" + }, + { + "phase": 2, + "action": "check" + }, + { + "phase": 3, + "action": "finish" + }, + { + "phase": 4, + "action": "create-pr" + } + ], + "commit": null, + "pr_url": null, + "subtasks": [], + "children": [], + "parent": null, + "relatedFiles": [], + "notes": "", + "meta": { + "linear_issue": "MIN-415" + } +} diff --git a/.trellis/tasks/archive/2026-03/03-26-statusline-integration/task.json b/.trellis/tasks/archive/2026-03/03-26-statusline-integration/task.json new file mode 100644 index 00000000..cd58a8be --- /dev/null +++ b/.trellis/tasks/archive/2026-03/03-26-statusline-integration/task.json @@ -0,0 +1,47 @@ +{ + "id": "statusline-integration", + "name": "statusline-integration", + "title": "StatusLine: 集成 Trellis 任务状态到 Claude Code 状态栏", + "description": "", + "status": "completed", + "dev_type": null, + "scope": null, + "package": "cli", + "priority": "P2", + "creator": "taosu", + "assignee": "taosu", + "createdAt": "2026-03-26", + "completedAt": "2026-03-26", + "branch": null, + "base_branch": "feat/v0.4.0-beta", + "worktree_path": null, + "current_phase": 0, + "next_action": [ + { + "phase": 1, + "action": "implement" + }, + { + "phase": 2, + "action": "check" + }, + { + "phase": 3, + "action": "finish" + }, + { + "phase": 4, + "action": "create-pr" + } + ], + "commit": null, + "pr_url": null, + "subtasks": [], + "children": [], + "parent": null, + "relatedFiles": [], + "notes": "", + "meta": { + "linear_issue": "MIN-416" + } +} \ No newline at end of file diff --git a/.trellis/workspace/taosu/index.md b/.trellis/workspace/taosu/index.md index 1c67cd3a..b9cd6ef2 100644 --- a/.trellis/workspace/taosu/index.md +++ b/.trellis/workspace/taosu/index.md @@ -8,8 +8,8 @@ - **Active File**: `journal-4.md` -- **Total Sessions**: 104 -- **Last Active**: 2026-03-24 +- **Total Sessions**: 105 +- **Last Active**: 2026-03-26 --- @@ -19,7 +19,7 @@ | File | Lines | Status | |------|-------|--------| -| `journal-4.md` | ~153 | Active | +| `journal-4.md` | ~187 | Active | | `journal-3.md` | ~1988 | Archived | | `journal-2.md` | ~1963 | Archived | | `journal-1.md` | ~1998 | Archived | @@ -32,6 +32,7 @@ | # | Date | Title | Commits | Branch | |---|------|-------|---------|--------| +| 105 | 2026-03-26 | StatusLine: 集成 Trellis 任务状态到 CC 状态栏 | `9e4411c` | `feat/v0.4.0-beta` | | 104 | 2026-03-24 | Decouple .agents/skills as shared layer + Codex .codex support | `ba75c30` | `feat/v0.4.0-beta` | | 103 | 2026-03-16 | Rename empty templates to from scratch | `57a243d` | | 102 | 2026-03-13 | Publish-Skill Command & Docs-Site Sync | `d8d7dfb`, `b93ef30` | diff --git a/.trellis/workspace/taosu/journal-4.md b/.trellis/workspace/taosu/journal-4.md index 7b91cd2b..3f28ed54 100644 --- a/.trellis/workspace/taosu/journal-4.md +++ b/.trellis/workspace/taosu/journal-4.md @@ -151,3 +151,37 @@ Major architecture change: decoupled .agents/skills/ from Codex platform into sh ### Next Steps - None - task complete + + +## Session 105: StatusLine: 集成 Trellis 任务状态到 CC 状态栏 + +**Date**: 2026-03-26 +**Task**: StatusLine: 集成 Trellis 任务状态到 CC 状态栏 +**Package**: cli +**Branch**: `feat/v0.4.0-beta` + +### Summary + +基于推文灵感,为 Trellis 添加项目级 statusLine。读取 CC stdin JSON + Trellis 任务数据,在状态栏显示当前任务、model/ctx/branch/duration、开发者和活跃任务数。无任务时 1 行,有任务时 2 行。 + +### Main Changes + +(Add details) + +### Git Commits + +| Hash | Message | +|------|---------| +| `9e4411c` | (see git log) | + +### Testing + +- [OK] (Add test results) + +### Status + +[OK] **Completed** + +### Next Steps + +- None - task complete diff --git a/docs-site b/docs-site index b61d8982..aaab4c42 160000 --- a/docs-site +++ b/docs-site @@ -1 +1 @@ -Subproject commit b61d8982ad8a0a737e8ab03765aa3fccc4c6e988 +Subproject commit aaab4c4233c04393460607d29e30a6a31f7f70cf diff --git a/marketplace/skills/cc-codex-spec-bootstrap/SKILL.md b/marketplace/skills/cc-codex-spec-bootstrap/SKILL.md index a654135d..a692116d 100644 --- a/marketplace/skills/cc-codex-spec-bootstrap/SKILL.md +++ b/marketplace/skills/cc-codex-spec-bootstrap/SKILL.md @@ -27,7 +27,7 @@ Before running this skill, ensure these tools are set up. See [references/mcp-se |------|---------|----------| | [Trellis](https://github.com/mindfold/trellis) | Workflow framework with `.trellis/spec/` structure | Yes | | [GitNexus](https://github.com/abhigyanpatwari/GitNexus) | Code → knowledge graph (Tree-sitter + KuzuDB) | Yes | -| [ABCoder](https://github.com/nicepkg/abcoder) | Code → UniAST (ts-morph for TS, tree-sitter for others) | Yes | +| [ABCoder](https://github.com/cloudwego/abcoder) | Code → UniAST (ts-morph for TS, tree-sitter for others) | Yes | | [Codex CLI](https://github.com/openai/codex) | Parallel task execution agent | Yes | Quick check: diff --git a/marketplace/skills/trellis-meta/SKILL.md b/marketplace/skills/trellis-meta/SKILL.md index 7941ab36..2682f8ad 100644 --- a/marketplace/skills/trellis-meta/SKILL.md +++ b/marketplace/skills/trellis-meta/SKILL.md @@ -1,17 +1,18 @@ --- name: trellis-meta -description: "Meta-skill for understanding and customizing Mindfold Trellis — the all-in-one AI workflow system for 9 AI coding platforms (Claude Code, Cursor, OpenCode, iFlow, Codex, Kilo, Kiro, Gemini CLI, Antigravity). Documents the original Trellis system design including architecture, commands, hooks, and multi-agent pipelines. Use when understanding Trellis architecture, customizing workflows, adding commands or agents, troubleshooting issues, or adapting Trellis to specific projects. Modifications should be recorded in a project-local trellis-local skill, not here." +description: "Meta-skill for understanding and customizing Mindfold Trellis — the all-in-one AI workflow system for 11 AI coding platforms (Claude Code, Cursor, OpenCode, iFlow, Codex, Kilo, Kiro, Gemini CLI, Antigravity, Qoder, CodeBuddy). Documents the original Trellis system design including architecture, commands, hooks, multi-agent pipelines, monorepo support, and task lifecycle hooks. Use when understanding Trellis architecture, customizing workflows, adding commands or agents, troubleshooting issues, or adapting Trellis to specific projects. Modifications should be recorded in a project-local trellis-local skill, not here." --- # Trellis Meta-Skill ## Version Compatibility -| Item | Value | -| --------------------------- | ---------- | -| **Trellis CLI Version** | 0.3.0 | -| **Skill Last Updated** | 2026-02-28 | -| **Min Claude Code Version** | 1.0.0+ | +| Item | Value | +| --------------------------- | ---------------- | +| **Trellis CLI Version** | 0.4.0-beta.8 | +| **Skill Last Updated** | 2026-03-24 | +| **Min Claude Code Version** | 1.0.0+ | +| **Min Node.js Version** | >=18.17.0 | > ⚠️ **Version Mismatch Warning**: If your Trellis CLI version differs from above, some features may not work as documented. Run `trellis --version` to check. @@ -21,23 +22,24 @@ description: "Meta-skill for understanding and customizing Mindfold Trellis — ### Feature Support Matrix -| Feature | Claude Code | iFlow | Cursor | OpenCode | Codex | Kilo | Kiro | Gemini CLI | Antigravity | -| --------------------------- | ----------- | ------- | ---------- | ---------- | ---------- | ---------- | ---------- | ---------- | ------------ | -| **Core Systems** | | | | | | | | | | -| Workspace system | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | -| Task system | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | -| Spec system | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | -| Commands/Skills | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Skills | ✅ Full | ✅ Skills | ✅ TOML | ✅ Workflows | -| Agent definitions | ✅ Full | ✅ Full | ⚠️ Manual | ✅ Full | ⚠️ Manual | ⚠️ Manual | ⚠️ Manual | ⚠️ Manual | ⚠️ Manual | -| **Hook-Dependent Features** | | | | | | | | | | -| SessionStart hook | ✅ Full | ✅ Full | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | -| PreToolUse hook | ✅ Full | ✅ Full | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | -| SubagentStop hook | ✅ Full | ✅ Full | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | -| Auto context injection | ✅ Full | ✅ Full | ❌ Manual | ❌ Manual | ❌ Manual | ❌ Manual | ❌ Manual | ❌ Manual | ❌ Manual | -| Ralph Loop | ✅ Full | ✅ Full | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | -| **Multi-Agent/Session** | | | | | | | | | | -| Multi-Agent (current dir) | ✅ Full | ✅ Full | ⚠️ Limited | ⚠️ Limited | ⚠️ Limited | ⚠️ Limited | ⚠️ Limited | ⚠️ Limited | ⚠️ Limited | -| Multi-Session (worktrees) | ✅ Full | ✅ Full | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | +| Feature | Claude Code | iFlow | Cursor | OpenCode | Codex | Kilo | Kiro | Gemini CLI | Antigravity | Qoder | CodeBuddy | +| --------------------------- | ----------- | ------- | ---------- | ---------- | ------------- | ---------- | ---------- | ---------- | ------------ | ---------- | ---------- | +| **Core Systems** | | | | | | | | | | | | +| Workspace system | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | +| Task system | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | +| Spec system | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full | +| Commands/Skills | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Skills | ✅ Full | ✅ Skills | ✅ TOML | ✅ Workflows | ✅ Skills | ✅ Full | +| Agent definitions | ✅ Full | ✅ Full | ⚠️ Manual | ✅ Full | ✅ TOML | ⚠️ Manual | ⚠️ Manual | ⚠️ Manual | ⚠️ Manual | ⚠️ Manual | ⚠️ Manual | +| Shared agent skills | — | — | — | — | ✅ Full | — | — | — | — | — | — | +| **Hook-Dependent Features** | | | | | | | | | | | | +| SessionStart hook | ✅ Full | ✅ Full | ❌ None | ❌ None | ⚠️ Optional | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | +| PreToolUse hook | ✅ Full | ✅ Full | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | +| SubagentStop hook | ✅ Full | ✅ Full | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | +| Auto context injection | ✅ Full | ✅ Full | ❌ Manual | ❌ Manual | ❌ Manual | ❌ Manual | ❌ Manual | ❌ Manual | ❌ Manual | ❌ Manual | ❌ Manual | +| Ralph Loop | ✅ Full | ✅ Full | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | +| **Multi-Agent/Session** | | | | | | | | | | | | +| Multi-Agent (current dir) | ✅ Full | ✅ Full | ⚠️ Limited | ⚠️ Limited | ⚠️ Limited | ⚠️ Limited | ⚠️ Limited | ⚠️ Limited | ⚠️ Limited | ⚠️ Limited | ⚠️ Limited | +| Multi-Session (worktrees) | ✅ Full | ✅ Full | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None | ### Legend @@ -51,12 +53,18 @@ description: "Meta-skill for understanding and customizing Mindfold Trellis — All features work as documented. Hooks provide automatic context injection and quality enforcement. iFlow shares the same Python hook system as Claude Code. -#### Commands Only (Cursor, OpenCode, Codex, Kilo, Kiro, Gemini CLI, Antigravity) +#### Partial Hook Support (Codex) + +- **Works**: Workspace, tasks, specs, skills (`.codex/skills/` + `.agents/skills/` shared layer), TOML agent definitions (`.codex/agents/`), optional SessionStart hook +- **Doesn't work**: PreToolUse, SubagentStop, Ralph Loop, Multi-Session +- **Note**: SessionStart hook requires `codex_hooks = true` in `~/.codex/config.toml` + +#### Commands Only (Cursor, OpenCode, Kilo, Kiro, Gemini CLI, Antigravity, Qoder, CodeBuddy) - **Works**: Workspace, tasks, specs, commands/skills (platform-specific format) - **Doesn't work**: Hooks, auto-injection, Ralph Loop, Multi-Session - **Workaround**: Manually read spec files at session start; no automatic quality gates -- **Note**: Each platform uses its own command format (Codex uses Skills, Gemini uses TOML, Antigravity uses Workflows) +- **Note**: Each platform uses its own command format (Kiro/Qoder use Skills, Gemini uses TOML, Antigravity uses Workflows, CodeBuddy uses nested Markdown commands) ### Designing for Portability @@ -64,18 +72,25 @@ When customizing Trellis, consider platform compatibility: ``` ┌─────────────────────────────────────────────────────────────┐ -│ PORTABLE (All 9 Platforms) │ +│ PORTABLE (All 11 Platforms) │ │ - .trellis/workspace/ - .trellis/tasks/ │ │ - .trellis/spec/ - Platform commands/skills │ │ - File-based configs - JSONL context files │ +│ - config.yaml - Monorepo packages support │ └─────────────────────────────────────────────────────────────┘ │ ┌─────────────────────────────▼───────────────────────────────┐ +│ SHARED AGENT SKILLS (agentskills.io standard) │ +│ - .agents/skills/ (Codex + universal agent CLIs) │ +└─────────────────────────────┬───────────────────────────────┘ + │ +┌─────────────────────────────▼───────────────────────────────┐ │ HOOK-CAPABLE (Claude Code + iFlow) │ │ - .claude/hooks/ or .iflow/hooks/ │ │ - settings.json hook configuration │ │ - Auto context injection - SubagentStop control │ │ - Ralph Loop - Multi-Session worktrees │ +│ - Task lifecycle hooks - Dynamic spec discovery │ └─────────────────────────────────────────────────────────────┘ ``` @@ -223,27 +238,32 @@ Trellis transforms AI assistants into structured development partners through ** ``` ┌─────────────────────────────────────────────────────────────────────┐ │ USER INTERACTION │ -│ /trellis:start /trellis:brainstorm /trellis:parallel /trellis:finish-work │ +│ /trellis:start /trellis:brainstorm /trellis:parallel │ +│ /trellis:finish-work /trellis:before-dev /trellis:check │ └─────────────────────────────────┬───────────────────────────────────┘ │ ┌─────────────────────────────────▼───────────────────────────────────┐ │ SKILLS LAYER │ -│ .claude/commands/trellis/*.md (slash commands) │ -│ .claude/agents/*.md (sub-agent definitions) │ +│ .claude/commands/trellis/*.md (17 slash commands) │ +│ .claude/agents/*.md (6 sub-agent definitions) │ +│ .agents/skills/*/SKILL.md (shared agent skills layer) │ └─────────────────────────────────┬───────────────────────────────────┘ │ ┌─────────────────────────────────▼───────────────────────────────────┐ │ HOOKS LAYER │ -│ SessionStart → session-start.py (injects workflow + context) │ -│ PreToolUse:Task → inject-subagent-context.py (spec injection) │ -│ SubagentStop → ralph-loop.py (quality enforcement) │ +│ SessionStart → session-start.py (workflow + context + status) │ +│ PreToolUse:Agent → inject-subagent-context.py (spec injection) │ +│ SubagentStop → ralph-loop.py (quality enforcement) │ +│ Task Lifecycle → config.yaml hooks (after_create/start/finish/ │ +│ archive → e.g. Linear sync) │ └─────────────────────────────────┬───────────────────────────────────┘ │ ┌─────────────────────────────────▼───────────────────────────────────┐ │ PERSISTENCE LAYER │ │ .trellis/workspace/ (journals, session history) │ -│ .trellis/tasks/ (task tracking, context files) │ -│ .trellis/spec/ (coding guidelines) │ +│ .trellis/tasks/ (task tracking, context files, subtasks) │ +│ .trellis/spec/ (coding guidelines, monorepo per-package) │ +│ .trellis/config.yaml (packages, hooks, update.skip, spec_scope) │ └─────────────────────────────────────────────────────────────────────┘ ``` @@ -277,37 +297,61 @@ Track development progress across sessions with per-developer isolation. ### 2. Task System -Track work items with phase-based execution. +Track work items with phase-based execution, parent-child subtasks, and lifecycle hooks. ``` -.trellis/tasks/{MM-DD-slug-assignee}/ -├── task.json # Metadata, phases, branch +.trellis/tasks/{MM-DD-slug}/ +├── task.json # Metadata, phases, branch, subtasks ├── prd.md # Requirements +├── info.md # Technical design (optional) ├── implement.jsonl # Context for implement agent ├── check.jsonl # Context for check agent -└── debug.jsonl # Context for debug agent +├── debug.jsonl # Context for debug agent +├── research.jsonl # Context for research agent (optional) +└── cr.jsonl # Context for code review (optional) ``` ### 3. Spec System -Maintain coding standards that get injected to agents. +Maintain coding standards that get injected to agents. Supports both single-repo and monorepo layouts. ``` +# Single repo .trellis/spec/ ├── frontend/ # Frontend guidelines ├── backend/ # Backend guidelines └── guides/ # Thinking guides + +# Monorepo (per-package) +.trellis/spec/ +├── / # Per-package specs +│ ├── backend/ +│ ├── frontend/ +│ └── unit-test/ +└── guides/ # Shared thinking guides ``` ### 4. Hooks System Automatically inject context and enforce quality. -| Hook | When | Purpose | -| -------------------- | ----------------- | --------------------------------- | -| `SessionStart` | Session begins | Inject workflow, guidelines | -| `PreToolUse:Task` | Before sub-agent | Inject specs via JSONL | -| `SubagentStop:check` | Check agent stops | Enforce verification (Ralph Loop) | +**Claude Code / iFlow Hooks** (settings.json): + +| Hook | When | Purpose | +| --------------------- | ------------------------------ | ------------------------------------------ | +| `SessionStart` | startup, clear, compact events | Inject workflow, guidelines, task status | +| `PreToolUse:Agent` | Before sub-agent launch | Inject specs via JSONL | +| `PreToolUse:Task` | Before Task tool (legacy) | Same as Agent (CC renamed Task→Agent) | +| `SubagentStop:check` | Check agent stops | Enforce verification (Ralph Loop) | + +**Task Lifecycle Hooks** (config.yaml): + +| Event | When | Purpose | +| ---------------- | ------------------- | ------------------------------- | +| `after_create` | Task created | e.g. create Linear issue | +| `after_start` | Task started | e.g. update Linear status | +| `after_finish` | Task finished | e.g. mark Linear complete | +| `after_archive` | Task archived | e.g. close Linear issue | ### 5. Agent System @@ -386,9 +430,10 @@ references/ | `overview.md` | Core systems introduction | | `files.md` | All `.trellis/` files with purposes | | `workspace.md` | Workspace system, journals, developer identity | -| `tasks.md` | Task system, directories, JSONL context files | -| `specs.md` | Spec system, guidelines organization | +| `tasks.md` | Task system, subtasks, lifecycle hooks, JSONL | +| `specs.md` | Spec system, monorepo layout, guidelines | | `scripts.md` | Platform-independent scripts | +| `config.md` | config.yaml full reference | ### `claude-code/` - Claude Code Only @@ -428,21 +473,27 @@ references/ ### Key Scripts -| Script | Purpose | -| ---------------------- | -------------------- | -| `get_context.py` | Get session context | -| `task.py` | Task management | -| `add_session.py` | Record session | -| `multi_agent/start.py` | Start parallel agent | +| Script | Purpose | +| ------------------------ | ------------------------------------ | +| `get_context.py` | Get session context (text/JSON) | +| `task.py` | Task management (16 subcommands) | +| `add_session.py` | Record session | +| `create_bootstrap.py` | First-time spec bootstrap | +| `multi_agent/start.py` | Start parallel agent | +| `multi_agent/status.py` | Monitor agent status | +| `multi_agent/create_pr.py` | Create PR from worktree | ### Key Paths -| Path | Purpose | -| ------------------------ | ------------------- | -| `.trellis/.developer` | Developer identity | -| `.trellis/.current-task` | Active task pointer | -| `.trellis/workflow.md` | Main workflow docs | -| `.claude/settings.json` | Hook configuration | +| Path | Purpose | +| ------------------------ | ---------------------------------- | +| `.trellis/.developer` | Developer identity | +| `.trellis/.current-task` | Active task pointer | +| `.trellis/workflow.md` | Main workflow docs | +| `.trellis/config.yaml` | Project config (packages, hooks) | +| `.trellis/worktree.yaml` | Multi-session config | +| `.claude/settings.json` | Hook configuration | +| `.agents/skills/` | Shared agent skills (agentskills.io) | --- diff --git a/marketplace/skills/trellis-meta/references/claude-code/hooks.md b/marketplace/skills/trellis-meta/references/claude-code/hooks.md index 209df4a0..30e544a2 100644 --- a/marketplace/skills/trellis-meta/references/claude-code/hooks.md +++ b/marketplace/skills/trellis-meta/references/claude-code/hooks.md @@ -1,29 +1,44 @@ # Hooks System -Claude Code hooks for automatic context injection and quality enforcement. +Claude Code / iFlow hooks for automatic context injection and quality enforcement, plus task lifecycle hooks configured in config.yaml. --- ## Overview -Hooks intercept Claude Code lifecycle events to inject context and enforce quality. +There are two types of hooks in Trellis: + +1. **Platform hooks** (Claude Code / iFlow) — Intercept AI lifecycle events via `settings.json` +2. **Task lifecycle hooks** (all platforms) — Shell commands triggered by task.py operations via `config.yaml` ``` ┌─────────────────────────────────────────────────────────────────────────┐ -│ HOOK LIFECYCLE │ +│ PLATFORM HOOK LIFECYCLE │ │ │ -│ Session Start ──► SessionStart hook ──► Inject workflow context │ +│ Session Start ──► SessionStart hook ──► Inject workflow + task status │ +│ (startup/clear/compact) │ │ │ -│ Task() called ──► PreToolUse:Task hook ──► Inject specs from JSONL │ +│ Agent() called ──► PreToolUse:Agent hook ──► Inject specs from JSONL │ +│ Task() called ──► PreToolUse:Task hook ──► (same, legacy matcher) │ │ │ │ Agent stops ──► SubagentStop hook ──► Ralph Loop verification │ │ │ └─────────────────────────────────────────────────────────────────────────┘ + +┌─────────────────────────────────────────────────────────────────────────┐ +│ TASK LIFECYCLE HOOKS │ +│ │ +│ task.py create ──► after_create ──► e.g. Create Linear issue │ +│ task.py start ──► after_start ──► e.g. Update status │ +│ task.py finish ──► after_finish ──► e.g. Mark done │ +│ task.py archive ──► after_archive ──► e.g. Close issue │ +│ │ +└─────────────────────────────────────────────────────────────────────────┘ ``` --- -## Configuration +## Platform Hook Configuration ### `.claude/settings.json` @@ -40,6 +55,26 @@ Hooks intercept Claude Code lifecycle events to inject context and enforce quali "timeout": 10 } ] + }, + { + "matcher": "clear", + "hooks": [ + { + "type": "command", + "command": "python3 \"$CLAUDE_PROJECT_DIR/.claude/hooks/session-start.py\"", + "timeout": 10 + } + ] + }, + { + "matcher": "compact", + "hooks": [ + { + "type": "command", + "command": "python3 \"$CLAUDE_PROJECT_DIR/.claude/hooks/session-start.py\"", + "timeout": 10 + } + ] } ], "PreToolUse": [ @@ -52,6 +87,16 @@ Hooks intercept Claude Code lifecycle events to inject context and enforce quali "timeout": 30 } ] + }, + { + "matcher": "Agent", + "hooks": [ + { + "type": "command", + "command": "python3 \"$CLAUDE_PROJECT_DIR/.claude/hooks/inject-subagent-context.py\"", + "timeout": 30 + } + ] } ], "SubagentStop": [ @@ -70,13 +115,23 @@ Hooks intercept Claude Code lifecycle events to inject context and enforce quali } ``` +**Note**: PreToolUse matches both `Task` and `Agent` because Claude Code renamed the Task tool to Agent in v2.1.63. Both matchers are kept for backward compatibility. + --- ## SessionStart Hook ### Purpose -Inject initial context when a Claude Code session starts. +Inject initial context when a Claude Code session starts, clears, or compacts. + +### Matchers + +| Matcher | When | +|---------|------| +| `startup` | Session first starts | +| `clear` | User runs `/clear` | +| `compact` | Context window compresses | ### Script: `session-start.py` @@ -84,23 +139,31 @@ Inject initial context when a Claude Code session starts. - Developer identity from `.trellis/.developer` - Git status and recent commits -- Current task (if `.trellis/.current-task` exists) +- Current task info (if `.trellis/.current-task` exists) - `workflow.md` content -- All `spec/*/index.md` files +- All dynamically discovered `spec/*/index.md` files (supports monorepo layout) +- Spec guideline indexes - Start instructions +- **Task status tag** (``) with structured state: + - `NO ACTIVE TASK` — no current task set + - `NOT READY` — task exists but no JSONL context files + - `READY` — task has context, ready to implement + - `COMPLETED` — task is done + +**Dynamic spec discovery**: The hook iterates `spec/` subdirectories at runtime instead of hardcoding `frontend/backend/guides`. This means adding a new spec category requires no hook modification. **Output format:** ```json { "result": "continue", - "message": "# Session Context\n\n## Developer\ntaosu\n\n## Git Status\n..." + "message": "# Session Context\n\n## Developer\ntaosu\n\nStatus: READY\n..." } ``` --- -## PreToolUse:Task Hook +## PreToolUse:Agent Hook ### Purpose @@ -108,7 +171,7 @@ Inject relevant specs when a subagent is invoked. ### Script: `inject-subagent-context.py` -**Trigger:** When `Task(subagent_type="...")` is called. +**Trigger:** When `Agent(subagent_type="...")` or `Task(subagent_type="...")` is called. **Flow:** @@ -133,9 +196,9 @@ Inject relevant specs when a subagent is invoked. ### JSONL Format ```jsonl -{"file": ".trellis/spec/backend/index.md", "reason": "Backend guidelines"} +{"file": ".trellis/spec/cli/backend/index.md", "reason": "Backend guidelines"} {"file": "src/services/auth.ts", "reason": "Existing pattern"} -{"file": ".trellis/tasks/01-31-add-login/prd.md", "reason": "Requirements"} +{"file": ".trellis/tasks/03-24-add-login/prd.md", "reason": "Requirements"} ``` --- @@ -161,20 +224,78 @@ Quality enforcement via Ralph Loop. --- +## Task Lifecycle Hooks + +### Purpose + +Run shell commands after task lifecycle events. Works on all platforms (file-based, no hook system required). + +### Configuration (config.yaml) + +```yaml +hooks: + after_create: + - python3 .trellis/scripts/hooks/linear_sync.py create + after_start: + - python3 .trellis/scripts/hooks/linear_sync.py start + after_finish: + - python3 .trellis/scripts/hooks/linear_sync.py finish + after_archive: + - python3 .trellis/scripts/hooks/linear_sync.py archive +``` + +### Events + +| Event | Trigger | Example Use Case | +|-------|---------|------------------| +| `after_create` | `task.py create` | Create Linear/Jira issue | +| `after_start` | `task.py start` | Update issue to "In Progress" | +| `after_finish` | `task.py finish` | Mark issue complete | +| `after_archive` | `task.py archive` | Close external issue | + +### Environment Variable + +| Variable | Description | +|----------|-------------| +| `TASK_JSON_PATH` | Absolute path to the task's `task.json` file | + +### Built-in: Linear Sync Hook + +Ships with `hooks/linear_sync.py` that syncs task events to Linear via the `linearis` CLI tool. + +--- + +## Codex SessionStart Hook + +Codex has its own optional SessionStart hook at `.codex/hooks/session-start.py` configured via `.codex/hooks.json`. + +**Requires**: `codex_hooks = true` in `~/.codex/config.toml` + +**Injects**: Same Trellis context as the Claude Code hook (workflow, guidelines, task status). + +--- + ## Hook Scripts Location ``` -.claude/hooks/ -├── session-start.py # SessionStart handler -├── inject-subagent-context.py # PreToolUse:Task handler -└── ralph-loop.py # SubagentStop:check handler +.claude/hooks/ # Claude Code platform hooks +├── session-start.py # SessionStart handler +├── inject-subagent-context.py # PreToolUse:Agent/Task handler +└── ralph-loop.py # SubagentStop:check handler + +.trellis/scripts/hooks/ # Task lifecycle hooks (all platforms) +└── linear_sync.py # Linear issue sync + +.codex/hooks/ # Codex platform hooks (optional) +├── session-start.py # Codex SessionStart handler +└── hooks.json # Codex hook configuration ``` --- ## Environment Variables -Available in hook scripts: +Available in platform hook scripts: | Variable | Description | | -------------------- | ------------------------------------------- | @@ -237,9 +358,10 @@ TOOL_INPUT='{"subagent_type":"implement","prompt":"test"}' \ ### Common Issues -| Issue | Cause | Solution | -| ------------------- | --------------------- | ---------------------------- | -| Hook not running | Wrong matcher | Check settings.json matcher | -| Timeout | Script too slow | Increase timeout or optimize | -| No context injected | Missing .current-task | Run `task.py start` | -| JSONL not found | Wrong task directory | Check .current-task path | +| Issue | Cause | Solution | +| ------------------- | ---------------------------- | ----------------------------------- | +| Hook not running | Wrong matcher | Check settings.json (both Task+Agent) | +| Timeout | Script too slow | Increase timeout or optimize | +| No context injected | Missing .current-task | Run `task.py start` | +| JSONL not found | Wrong task directory | Check .current-task path | +| Import warnings | IDE Pyright/Pylance | `# type: ignore[import-not-found]` added | diff --git a/marketplace/skills/trellis-meta/references/core/config.md b/marketplace/skills/trellis-meta/references/core/config.md new file mode 100644 index 00000000..78d607b9 --- /dev/null +++ b/marketplace/skills/trellis-meta/references/core/config.md @@ -0,0 +1,185 @@ +# Configuration Reference + +Complete reference for `.trellis/config.yaml`. + +--- + +## Overview + +`config.yaml` is the project-level configuration file for Trellis. All values have sensible hardcoded defaults — if the file is missing or a key is absent, the default is used. + +**Read by**: `common/config.py` + +--- + +## Full Schema + +```yaml +# --- Session --- +# Commit message used when auto-committing journal/index changes +session_commit_message: 'chore: record journal' + +# Maximum lines per journal file before rotating to a new one +max_journal_lines: 2000 + +# --- Monorepo Packages --- +packages: + : + path: # Required. Path relative to repo root + type: local # Optional. "local" (default) or "submodule" + git: false # Optional. true if package has own git repo + tags: # Optional. Tags for filtering (e.g., [backend, unit-test]) + - + +# Default package when --package is omitted +default_package: + +# --- Update --- +update: + skip: # Files/dirs to permanently exclude from `trellis update` + - + +# --- Task Lifecycle Hooks --- +hooks: + after_create: # Shell commands run after task creation + - + after_start: # Shell commands run after task start + - + after_finish: # Shell commands run after task finish + - + after_archive: # Shell commands run after task archive + - + +# --- Session Context --- +session: + spec_scope: active_task # Control which packages' specs are scanned + # Options: "active_task" | list of package names | null (all) +``` + +--- + +## Section Details + +### Session Settings + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| `session_commit_message` | string | `"chore: record journal"` | Commit message for `add_session.py` auto-commit | +| `max_journal_lines` | int | `2000` | Max lines per journal file before rotation | + +### Monorepo Packages + +Declares packages in a monorepo. If absent or empty, the project is treated as single-repo. + +```yaml +packages: + cli: + path: packages/cli + tags: [backend, unit-test] + docs-site: + path: docs-site + type: submodule + tags: [docs] +default_package: cli +``` + +**Package types**: + +| Type | Description | +|------|-------------| +| `local` (default) | Regular directory in the repo | +| `submodule` | Git submodule — worktree agents auto-init it | + +**`git: true`**: Marks packages with their own independent git repo. Session context shows branch, working directory status, and recent commits for these packages. + +**Effect on spec system**: When packages are configured, specs live at `.trellis/spec///` instead of `.trellis/spec//`. + +### Update Skip + +Permanently exclude files or directories from `trellis update`: + +```yaml +update: + skip: + - .trellis/spec/custom/ + - .claude/commands/trellis/my-command.md +``` + +### Task Lifecycle Hooks + +Shell commands executed after task lifecycle events. Task info is passed via the `TASK_JSON_PATH` environment variable. + +```yaml +hooks: + after_create: + - python3 .trellis/scripts/hooks/linear_sync.py create + after_start: + - python3 .trellis/scripts/hooks/linear_sync.py start + after_archive: + - python3 .trellis/scripts/hooks/linear_sync.py archive +``` + +**Events**: + +| Event | Trigger | Use Case | +|-------|---------|----------| +| `after_create` | `task.py create` | Create external issue (Linear, Jira) | +| `after_start` | `task.py start` | Update issue status to "In Progress" | +| `after_finish` | `task.py finish` | Mark issue as "Done" | +| `after_archive` | `task.py archive` | Close external issue | + +**Environment variables available to hook commands**: + +| Variable | Description | +|----------|-------------| +| `TASK_JSON_PATH` | Absolute path to the task's `task.json` file | + +### Session Spec Scope + +Control which packages' specs are scanned during session start: + +```yaml +session: + spec_scope: active_task # Only scan the package of the current task +``` + +| Value | Behavior | +|-------|----------| +| `"active_task"` | Scan only the active task's package | +| `["cli", "docs"]` | Scan only listed packages | +| `null` / absent | Scan all packages | + +--- + +## Example: Full config.yaml + +```yaml +session_commit_message: 'chore: record journal' +max_journal_lines: 2000 + +packages: + cli: + path: packages/cli + tags: [backend, unit-test] + docs-site: + path: docs-site + type: submodule + tags: [docs] + +default_package: cli + +update: + skip: + - .trellis/spec/custom-internal/ + +hooks: + after_create: + - python3 .trellis/scripts/hooks/linear_sync.py create + after_start: + - python3 .trellis/scripts/hooks/linear_sync.py start + after_archive: + - python3 .trellis/scripts/hooks/linear_sync.py archive + +session: + spec_scope: active_task +``` diff --git a/marketplace/skills/trellis-meta/references/core/files.md b/marketplace/skills/trellis-meta/references/core/files.md index 3020d9d5..e54b9a2d 100644 --- a/marketplace/skills/trellis-meta/references/core/files.md +++ b/marketplace/skills/trellis-meta/references/core/files.md @@ -15,13 +15,16 @@ Complete reference of all files in the `.trellis/` directory. ├── .version # Installed Trellis version ├── .gitignore # Git ignore rules ├── workflow.md # Main workflow documentation -├── config.yaml # Project-level configuration +├── config.yaml # Project-level configuration (packages, hooks, etc.) ├── worktree.yaml # Multi-session configuration │ ├── workspace/ # Developer workspaces -├── tasks/ # Task tracking -├── spec/ # Coding guidelines +├── tasks/ # Task tracking (with subtask support) +├── spec/ # Coding guidelines (monorepo: per-package) └── scripts/ # Automation scripts + ├── common/ # Shared utilities (19 modules) + ├── hooks/ # Task lifecycle hook scripts + └── multi_agent/ # Multi-agent pipeline scripts ``` --- @@ -130,7 +133,7 @@ taosu **Format**: Plain text, semver version string. ``` -0.3.0 +0.4.0-beta.8 ``` **Used by**: @@ -208,17 +211,46 @@ taosu **Format**: YAML ```yaml -# Commit message used when auto-committing journal/index changes +# Session settings session_commit_message: 'chore: record journal' - -# Maximum lines per journal file before rotating to a new one max_journal_lines: 2000 + +# Monorepo packages +packages: + cli: + path: packages/cli + tags: [backend, unit-test] + docs-site: + path: docs-site + type: submodule + tags: [docs] +default_package: cli + +# Update exclusions +update: + skip: + - .trellis/spec/custom/ + +# Task lifecycle hooks +hooks: + after_create: + - python3 .trellis/scripts/hooks/linear_sync.py create + after_start: + - python3 .trellis/scripts/hooks/linear_sync.py start + after_archive: + - python3 .trellis/scripts/hooks/linear_sync.py archive + +# Session context scope +session: + spec_scope: active_task ``` -**Used by**: `common/config.py` (read by `add_session.py`) +**Used by**: `common/config.py` **Behavior**: All values have sensible hardcoded defaults. If config.yaml is missing or a key is absent, the default is used. +→ See `core/config.md` for full schema reference. + --- ### `worktree.yaml` @@ -315,23 +347,34 @@ Automation scripts. These files are managed by `trellis update`: -| File | Purpose | -| ------------------------ | ------------------------ | -| `.trellis/workflow.md` | Workflow documentation | -| `.trellis/config.yaml` | Project-level config | -| `.trellis/worktree.yaml` | Multi-session config | -| `.trellis/.gitignore` | Git ignore rules | -| `.claude/hooks/*.py` | Hook scripts | -| `.claude/commands/*.md` | Slash commands | -| `.claude/agents/*.md` | Agent definitions | -| `.cursor/commands/*.md` | Cursor commands (mirror) | +| File | Purpose | +| ------------------------------- | -------------------------- | +| `.trellis/workflow.md` | Workflow documentation | +| `.trellis/config.yaml` | Project-level config | +| `.trellis/worktree.yaml` | Multi-session config | +| `.trellis/.gitignore` | Git ignore rules | +| `.trellis/scripts/**/*.py` | All Python scripts | +| `.claude/hooks/*.py` | Hook scripts | +| `.claude/commands/trellis/*.md` | Slash commands (17 files) | +| `.claude/agents/*.md` | Agent definitions (6 files) | +| `.cursor/commands/*.md` | Cursor commands | +| `.agents/skills/*/SKILL.md` | Shared agent skills | +| Platform-specific dirs | Per-platform templates | **Update behavior**: 1. Compare file hash with `.template-hashes.json` 2. If unchanged → Auto-update 3. If modified → Create `.new` file for manual merge -4. Update hashes after successful update +4. If user-deleted → Skip (respects intentional deletion) +5. Update hashes after successful update + +**Protected paths** (never touched by update/migration): +- `.trellis/workspace/` +- `.trellis/spec/` +- `.trellis/tasks/` + +**Exclusions**: Files listed in `update.skip` in config.yaml are permanently excluded. --- @@ -347,11 +390,12 @@ These files are managed by `trellis update`: ├── workflow.md ├── config.yaml ├── worktree.yaml -├── spec/ -│ ├── frontend/ -│ ├── backend/ -│ └── guides/ +├── spec/ # Single repo: frontend/, backend/, guides/ +│ └── ... # Monorepo: //, guides/ └── scripts/ + ├── common/ + ├── hooks/ + └── multi_agent/ ``` ### Created at runtime diff --git a/marketplace/skills/trellis-meta/references/core/overview.md b/marketplace/skills/trellis-meta/references/core/overview.md index ca03a685..2f2aa8b0 100644 --- a/marketplace/skills/trellis-meta/references/core/overview.md +++ b/marketplace/skills/trellis-meta/references/core/overview.md @@ -1,18 +1,19 @@ # Core Systems Overview -These systems work on **all 9 platforms** (Claude Code, Cursor, OpenCode, iFlow, Codex, Kilo, Kiro, Gemini CLI, Antigravity). +These systems work on **all 11 platforms** (Claude Code, Cursor, OpenCode, iFlow, Codex, Kilo, Kiro, Gemini CLI, Antigravity, Qoder, CodeBuddy). --- ## What's in Core? -| System | Purpose | Files | -| --------- | -------------------------- | --------------------------------- | -| Workspace | Session tracking, journals | `.trellis/workspace/` | -| Tasks | Work item tracking | `.trellis/tasks/` | -| Specs | Coding guidelines | `.trellis/spec/` | -| Commands | Slash command prompts | `.claude/commands/` | -| Scripts | Automation utilities | `.trellis/scripts/` (core subset) | +| System | Purpose | Files | +| --------- | ------------------------------- | --------------------------------- | +| Workspace | Session tracking, journals | `.trellis/workspace/` | +| Tasks | Work items, subtasks, hooks | `.trellis/tasks/` | +| Specs | Coding guidelines (per-package) | `.trellis/spec/` | +| Config | Packages, hooks, skip rules | `.trellis/config.yaml` | +| Commands | Slash command prompts | `.claude/commands/` | +| Scripts | Automation utilities | `.trellis/scripts/` (core subset) | --- @@ -30,13 +31,17 @@ All core systems are **file-based**: │ │ │ .trellis/ │ │ ├── workspace/ → Journals, session history │ -│ ├── tasks/ → Task directories, PRDs, context files │ -│ ├── spec/ → Coding guidelines │ +│ ├── tasks/ → Task directories, PRDs, subtasks │ +│ ├── spec/ → Coding guidelines (monorepo support) │ +│ ├── config.yaml → Packages, hooks, update.skip │ │ └── scripts/ → Python utilities (core subset) │ │ │ │ .claude/ │ │ └── commands/ → Slash command prompts │ │ │ +│ .agents/ │ +│ └── skills/ → Shared agent skills (agentskills.io) │ +│ │ └─────────────────────────────────────────────────────────────┘ ``` @@ -52,7 +57,11 @@ All core systems work automatically with hook integration. All core systems work automatically with hook integration (same as Claude Code). -### Cursor, OpenCode, Codex, Kilo, Kiro, Gemini CLI, Antigravity +### Codex + +Core systems work with optional SessionStart hook and TOML agents. See `meta/platform-compatibility.md`. + +### Cursor, OpenCode, Kilo, Kiro, Gemini CLI, Antigravity, Qoder, CodeBuddy Read files manually at session start: @@ -69,6 +78,7 @@ Read files manually at session start: | -------------- | ---------------------------------------------- | | `files.md` | All files in `.trellis/` with purposes | | `workspace.md` | Workspace system, journals, developer identity | -| `tasks.md` | Task system, directories, JSONL context files | -| `specs.md` | Spec system, guidelines organization | +| `tasks.md` | Task system, subtasks, lifecycle hooks, JSONL | +| `specs.md` | Spec system, monorepo layout, guidelines | | `scripts.md` | Core scripts (platform-independent) | +| `config.md` | config.yaml full schema reference | diff --git a/marketplace/skills/trellis-meta/references/core/scripts.md b/marketplace/skills/trellis-meta/references/core/scripts.md index 98f8bdc6..50707dac 100644 --- a/marketplace/skills/trellis-meta/references/core/scripts.md +++ b/marketplace/skills/trellis-meta/references/core/scripts.md @@ -6,23 +6,41 @@ Platform-independent Python scripts for Trellis automation. ## Overview -These scripts work on all platforms - they only read/write files and don't require Claude Code's hook system. +These scripts work on all platforms — they only read/write files and don't require Claude Code's hook system. ``` .trellis/scripts/ -├── common/ # Shared utilities -│ ├── paths.py -│ ├── developer.py -│ ├── config.py -│ ├── task_utils.py -│ ├── phase.py -│ └── git_context.py +├── common/ # Shared utilities (19 modules) +│ ├── __init__.py +│ ├── paths.py # Path constants +│ ├── types.py # Core type definitions (TaskData, AgentRecord) +│ ├── developer.py # Developer management +│ ├── config.py # config.yaml reader +│ ├── io.py # I/O utilities +│ ├── log.py # Logging with colors +│ ├── git.py # Git command utilities +│ ├── git_context.py # Git and session context shim +│ ├── session_context.py # Session context generation +│ ├── packages_context.py # Package discovery (monorepo) +│ ├── tasks.py # Task loading and iteration +│ ├── task_utils.py # Task utilities (resolve, hooks) +│ ├── task_store.py # Task store ops (create, archive, subtasks) +│ ├── task_queue.py # Task queue (list by status/assignee) +│ ├── task_context.py # JSONL context management +│ ├── phase.py # Phase tracking +│ ├── registry.py # Agent registry (registry.json) +│ ├── worktree.py # Worktree utilities +│ └── cli_adapter.py # Multi-platform CLI adapter │ -├── init_developer.py # Initialize developer -├── get_developer.py # Get developer name -├── get_context.py # Get session context -├── task.py # Task management CLI -└── add_session.py # Record session +├── hooks/ # Task lifecycle hook scripts +│ └── linear_sync.py # Linear issue sync +│ +├── init_developer.py # Initialize developer +├── get_developer.py # Get developer name +├── get_context.py # Get session context +├── task.py # Task management CLI (16 subcommands) +├── add_session.py # Record session +└── create_bootstrap.py # First-time spec bootstrap ``` --- @@ -69,15 +87,28 @@ python3 .trellis/scripts/get_developer.py Get session context for AI consumption. ```bash -python3 .trellis/scripts/get_context.py +python3 .trellis/scripts/get_context.py # Default mode (text) +python3 .trellis/scripts/get_context.py --json # JSON output +python3 .trellis/scripts/get_context.py --mode record # For record-session +python3 .trellis/scripts/get_context.py --mode packages # Package info only ``` +**Modes:** + +| Mode | Output | +|------|--------| +| `default` | Full context: developer, git status, current task, active tasks, journal, packages, paths | +| `record` | Focused context with MY ACTIVE TASKS shown first | +| `packages` | Package names, paths, types, and spec layers only | + **Output includes:** - Developer identity - Git status and recent commits - Current task (if any) +- Active tasks list - Workspace summary +- Package info (monorepo) --- @@ -99,6 +130,7 @@ python3 .trellis/scripts/add_session.py \ - `--summary` - Brief summary - `--content-file` - Path to file with detailed content - `--no-commit` - Skip auto-commit of workspace changes +- `--package` - Package name (monorepo) **Actions:** @@ -109,11 +141,23 @@ python3 .trellis/scripts/add_session.py \ --- +### `create_bootstrap.py` + +Create a bootstrap task for first-time setup. + +```bash +python3 .trellis/scripts/create_bootstrap.py +``` + +Creates a task that guides filling in project-specific spec guidelines. + +--- + ## Task Scripts ### `task.py` -Task management CLI. +Task management CLI with 16 subcommands. #### Create Task @@ -125,77 +169,103 @@ python3 .trellis/scripts/task.py create "Task name" --slug task-slug - `--slug` - URL-safe identifier - `--assignee` - Developer name (default: current) -- `--type` - Dev type: frontend, backend, fullstack +- `--priority` - Priority level (P0, P1, P2, P3) +- `--description` - Task description +- `--parent` - Parent task directory (for subtasks) +- `--package` - Package name (monorepo) #### List Tasks ```bash python3 .trellis/scripts/task.py list +python3 .trellis/scripts/task.py list --mine # My tasks only +python3 .trellis/scripts/task.py list --status active # Filter by status ``` -**Output:** +#### Start / Finish Task -``` -Active Tasks: - 01-31-add-login-taosu (active) - 01-30-fix-api-cursor-agent (paused) +```bash +python3 .trellis/scripts/task.py start # Set .current-task +python3 .trellis/scripts/task.py finish # Clear .current-task ``` -#### Start Task +#### Initialize Context ```bash -python3 .trellis/scripts/task.py start +python3 .trellis/scripts/task.py init-context ``` -Sets `.trellis/.current-task` to the task directory. +**Dev types:** `frontend`, `backend`, `fullstack`, `test`, `docs` + +Creates JSONL files with appropriate spec references. After initialization, outputs available spec files as hints. -#### Stop Task +#### Manage Context ```bash -python3 .trellis/scripts/task.py stop +python3 .trellis/scripts/task.py add-context +python3 .trellis/scripts/task.py list-context +python3 .trellis/scripts/task.py validate ``` -Clears `.trellis/.current-task`. +**Agent types for add-context:** `implement`, `check`, `debug` -#### Initialize Context +#### Branch Management ```bash -python3 .trellis/scripts/task.py init-context +python3 .trellis/scripts/task.py set-branch +python3 .trellis/scripts/task.py set-base-branch +python3 .trellis/scripts/task.py set-scope ``` -**Dev types:** `frontend`, `backend`, `fullstack` - -Creates JSONL files with appropriate spec references. - -#### Set Branch +#### Subtask Management ```bash -python3 .trellis/scripts/task.py set-branch +python3 .trellis/scripts/task.py create "Subtask" --parent +python3 .trellis/scripts/task.py add-subtask +python3 .trellis/scripts/task.py remove-subtask ``` -Updates `branch` field in task.json. - -#### Archive Task +#### Archive and PR ```bash -python3 .trellis/scripts/task.py archive +python3 .trellis/scripts/task.py archive # Auto-commits +python3 .trellis/scripts/task.py archive --no-commit +python3 .trellis/scripts/task.py list-archive [YYYY-MM] +python3 .trellis/scripts/task.py create-pr # Delegates to multi_agent/create_pr.py ``` -Moves task to `.trellis/tasks/archive/YYYY-MM/`. +--- + +## Hook Scripts -#### List Archive +### `hooks/linear_sync.py` + +Syncs task lifecycle events to Linear via `linearis` CLI. ```bash -python3 .trellis/scripts/task.py list-archive [month] +# Called automatically by task lifecycle hooks in config.yaml +python3 .trellis/scripts/hooks/linear_sync.py create +python3 .trellis/scripts/hooks/linear_sync.py start +python3 .trellis/scripts/hooks/linear_sync.py archive ``` +**Environment variable:** `TASK_JSON_PATH` — path to the task's `task.json`. + --- ## Common Utilities -### `common/paths.py` +### Core Types (`common/types.py`) + +```python +from common.types import TaskData, TaskInfo, AgentRecord +``` -Path constants and utilities. +- `TaskData` — TypedDict for task.json fields +- `TaskInfo` — Extended task info with directory path +- `AgentRecord` — Agent registry entry + +### Paths (`common/paths.py`) ```python from common.paths import ( @@ -206,9 +276,7 @@ from common.paths import ( ) ``` -### `common/developer.py` - -Developer management. +### Developer (`common/developer.py`) ```python from common.developer import ( @@ -217,52 +285,69 @@ from common.developer import ( ) ``` -### `common/task_utils.py` +### Config (`common/config.py`) + +```python +from common.config import ( + get_session_commit_message, # Commit message for auto-commit + get_max_journal_lines, # Max lines per journal file + get_packages, # Monorepo package dict or None + get_default_package, # Default package name + is_monorepo, # Check if packages are configured + get_submodule_packages, # Packages with type: submodule + get_git_packages, # Packages with git: true + get_spec_base, # "spec" or "spec/" + get_spec_scope, # Session spec scope setting +) +``` -Task lookup functions. +### Task Modules ```python from common.task_utils import ( - get_current_task, # Get current task directory - load_task_json, # Load task.json - save_task_json, # Save task.json + resolve_task_dir, # Resolve task directory from name + run_task_hooks, # Execute task lifecycle hooks ) -``` -### `common/phase.py` +from common.task_store import ( + create_task, # Create new task directory + archive_task, # Archive completed task + add_subtask, # Link child to parent + remove_subtask, # Unlink child from parent +) -Phase tracking. +from common.task_queue import ( + list_by_status, # List tasks by status + list_by_assignee, # List tasks by assignee +) -```python -from common.phase import ( - get_current_phase, # Get current phase number - advance_phase, # Move to next phase +from common.task_context import ( + init_context, # Create JSONL files for a task + add_context, # Add entry to a JSONL file + validate_context, # Validate JSONL files + list_context, # List JSONL entries ) ``` -### `common/config.py` - -Project-level configuration reader. +### Git (`common/git.py`) ```python -from common.config import ( - get_session_commit_message, # Commit message for auto-commit - get_max_journal_lines, # Max lines per journal file -) +from common.git import run_git # Execute git commands ``` -Reads from `.trellis/config.yaml` with hardcoded fallback defaults. +### I/O and Logging + +```python +from common.io import read_file, write_file # File operations +from common.log import info, warn, error # Colored logging +``` -### `common/git_context.py` +### Multi-Platform (`common/cli_adapter.py`) -Git context generation. +Abstracts CLI differences between all 11 platforms for the multi-agent pipeline. ```python -from common.git_context import ( - get_git_status, # Get git status - get_recent_commits, # Get recent commit messages - get_branch_name, # Get current branch -) +from common.cli_adapter import get_cli_adapter # Get platform-specific adapter ``` --- @@ -284,11 +369,19 @@ python3 .trellis/scripts/task.py create "Add user login" --slug add-login # Initialize context for fullstack work python3 .trellis/scripts/task.py init-context \ - .trellis/tasks/01-31-add-login-john-doe fullstack + .trellis/tasks/03-24-add-login fullstack # Start task python3 .trellis/scripts/task.py start \ - .trellis/tasks/01-31-add-login-john-doe + .trellis/tasks/03-24-add-login +``` + +### Create Subtask + +```bash +# Create a child task under an existing parent +python3 .trellis/scripts/task.py create "Login API endpoint" \ + --slug login-api --parent .trellis/tasks/03-24-add-login ``` ### Record Session @@ -304,5 +397,5 @@ python3 .trellis/scripts/add_session.py \ ```bash python3 .trellis/scripts/task.py archive \ - .trellis/tasks/01-31-add-login-john-doe + .trellis/tasks/03-24-add-login ``` diff --git a/marketplace/skills/trellis-meta/references/core/specs.md b/marketplace/skills/trellis-meta/references/core/specs.md index 4a8f3946..2b6e230e 100644 --- a/marketplace/skills/trellis-meta/references/core/specs.md +++ b/marketplace/skills/trellis-meta/references/core/specs.md @@ -1,61 +1,78 @@ # Spec System -Maintain coding standards that guide AI development. +Maintain coding standards that guide AI development. Supports single-repo and monorepo layouts with dynamic discovery. --- ## Directory Structure +### Single Repo + ``` .trellis/spec/ ├── frontend/ # Frontend guidelines │ ├── index.md # Overview and quick reference │ ├── component-guidelines.md -│ ├── hook-guidelines.md -│ ├── state-management.md │ └── ... │ ├── backend/ # Backend guidelines │ ├── index.md │ ├── directory-structure.md -│ ├── error-handling.md -│ ├── api-patterns.md │ └── ... │ -└── guides/ # Thinking guides +└── guides/ # Thinking guides (shared) ├── index.md ├── cross-layer-thinking-guide.md ├── code-reuse-thinking-guide.md └── cross-platform-thinking-guide.md ``` ---- +### Monorepo (Per-Package) -## Spec Categories +When `packages:` is defined in `config.yaml`, specs are organized per-package: + +``` +.trellis/spec/ +├── cli/ # Package: cli +│ ├── backend/ +│ │ ├── index.md +│ │ └── *.md +│ └── unit-test/ +│ ├── index.md +│ └── *.md +│ +├── docs-site/ # Package: docs-site +│ └── docs/ +│ ├── index.md +│ └── *.md +│ +└── guides/ # Shared across all packages + ├── index.md + └── *.md +``` -### Frontend (`frontend/`) +**Discovery**: `python3 .trellis/scripts/get_context.py --mode packages` lists all packages, paths, types, and spec layers. -UI and client-side patterns: +--- -- Component structure -- React hooks usage -- State management -- Styling conventions -- Accessibility +## Spec Categories -### Backend (`backend/`) +### Package-Specific Layers -Server-side patterns: +Each package can have its own set of layers (subdirectories): -- Directory structure -- API design -- Error handling -- Database access -- Security +| Layer | Content | +|-------|---------| +| `frontend/` | UI, components, state management, styling | +| `backend/` | API, services, database, error handling | +| `unit-test/` | Test conventions, mock strategies, integration patterns | +| `docs/` | Documentation guidelines | +| `shared/` | Cross-layer standards (TypeScript, git, quality) | +| `big-question/` | Deep-dive technical investigations | ### Guides (`guides/`) -Cross-cutting thinking guides: +Cross-cutting thinking guides shared across all packages: - How to think about cross-layer changes - Code reuse strategies @@ -65,72 +82,60 @@ Cross-cutting thinking guides: ## Index Files -Each category has an `index.md` that: +Each layer has an `index.md` that: 1. Provides category overview -2. Lists all specs in the category -3. Gives quick reference for common patterns +2. Lists all specs with links +3. Includes a **Pre-Development Checklist** +4. Includes a **Quality Check** section -### Example: `frontend/index.md` +### Example: `cli/backend/index.md` ```markdown -# Frontend Specifications +# Backend Development Guidelines -## Quick Reference +## Guidelines Index -| Topic | Guideline | -| ---------- | -------------------------------- | -| Components | Functional components only | -| State | Use React Query for server state | -| Styling | Tailwind CSS | +| Guide | Description | Status | +|-------|-------------|--------| +| [Directory Structure](./directory-structure.md) | Module organization | Done | +| [Error Handling](./error-handling.md) | Error strategies | Done | -## Specifications +## Pre-Development Checklist -1. [Component Guidelines](./component-guidelines.md) -2. [Hook Guidelines](./hook-guidelines.md) -3. [State Management](./state-management.md) -``` +Before writing backend code, read: +- Error handling → error-handling.md +- Logging → logging-guidelines.md ---- - -## Spec File Format - -````markdown -# [Spec Title] +## Quality Check -## Overview +After writing code: +1. Run `pnpm lint && pnpm typecheck` +2. Check relevant guidelines +``` -Brief description of what this spec covers. +--- -## Guidelines +## Dynamic Spec Discovery -### 1. [Guideline Name] +The session-start hook dynamically discovers spec directories instead of hardcoding `frontend/backend/guides`: -Detailed explanation... +1. Iterates all subdirectories under `.trellis/spec/` +2. For monorepo: iterates `spec///` +3. Reads `index.md` from each discovered layer +4. Injects all found indexes into session context -**Do:** +This means adding a new spec category only requires creating the directory — no hook modification needed. -```typescript -// Good example -``` -```` +### Spec Scope Filtering -**Don't:** +In monorepo projects, `session.spec_scope` in `config.yaml` controls which packages' specs are loaded: -```typescript -// Bad example +```yaml +session: + spec_scope: active_task # Only load specs for the current task's package ``` -### 2. [Another Guideline] - -... - -## Related Specs - -- [Related Spec 1](./related-spec.md) - -```` - --- ## Using Specs @@ -140,78 +145,68 @@ Detailed explanation... Reference specs in task context: ```jsonl -{"file": ".trellis/spec/frontend/index.md", "reason": "Frontend overview"} -{"file": ".trellis/spec/frontend/component-guidelines.md", "reason": "Component patterns"} -```` +{"file": ".trellis/spec/cli/backend/index.md", "reason": "Backend overview"} +{"file": ".trellis/spec/cli/backend/error-handling.md", "reason": "Error patterns"} +``` -### Manual Reading (Cursor) +### Manual Reading (Non-Hook Platforms) Read specs at session start: ``` -1. Read .trellis/spec/{category}/index.md -2. Read specific guidelines as needed -3. Follow patterns in your code +1. Read .trellis/spec/{package}/{layer}/index.md +2. Follow the Pre-Development Checklist +3. Read specific guidelines as needed ``` --- ## Creating New Specs -### 1. Choose Category +### 1. Choose Location -- Frontend UI patterns → `frontend/` -- Backend/API patterns → `backend/` -- Cross-cutting guides → `guides/` +- Single repo: `.trellis/spec//` +- Monorepo: `.trellis/spec///` ### 2. Create Spec File ```bash -touch .trellis/spec/frontend/new-pattern.md +touch .trellis/spec/cli/backend/new-pattern.md ``` ### 3. Follow Format -Use the spec file format above. +````markdown +# [Spec Title] -### 4. Update Index +## Overview +Brief description. -Add to category's `index.md`: +## Guidelines -```markdown -## Specifications +### 1. [Guideline Name] -... -N. [New Pattern](./new-pattern.md) +**Do:** +```typescript +// Good example ``` -### 5. Reference in JSONL - -Add to relevant task context files. - ---- - -## Adding New Categories - -### 1. Create Directory - -```bash -mkdir .trellis/spec/mobile +**Don't:** +```typescript +// Bad example ``` -### 2. Create Index - -```bash -touch .trellis/spec/mobile/index.md -``` +## Related Specs +- [Related Spec](./related-spec.md) +```` -### 3. Add Category Specs +### 4. Update Index -Create individual spec files. +Add to the layer's `index.md` Guidelines Index table. -### 4. Update Task Templates +### 5. Reference in JSONL -Ensure new category is available in JSONL templates. +Add to relevant task context files. --- @@ -222,3 +217,4 @@ Ensure new category is available in JSONL templates. 3. **Link related specs** - Cross-reference 4. **Update regularly** - Specs evolve with codebase 5. **Index everything** - Keep index files current +6. **Guides are shared** - Put cross-package concerns in `guides/` diff --git a/marketplace/skills/trellis-meta/references/core/tasks.md b/marketplace/skills/trellis-meta/references/core/tasks.md index b460ba3c..b868bacd 100644 --- a/marketplace/skills/trellis-meta/references/core/tasks.md +++ b/marketplace/skills/trellis-meta/references/core/tasks.md @@ -1,6 +1,6 @@ # Task System -Track work items with phase-based execution. +Track work items with phase-based execution, parent-child subtasks, and lifecycle hooks. --- @@ -8,15 +8,17 @@ Track work items with phase-based execution. ``` .trellis/tasks/ -├── {MM-DD-slug-assignee}/ # Active task directories -│ ├── task.json # Metadata, phases, branch -│ ├── prd.md # Requirements document -│ ├── info.md # Additional context (optional) -│ ├── implement.jsonl # Context for implement phase -│ ├── check.jsonl # Context for check phase -│ └── debug.jsonl # Context for debug phase +├── {MM-DD-slug}/ # Active task directories +│ ├── task.json # Metadata, phases, branch, subtasks +│ ├── prd.md # Requirements document +│ ├── info.md # Technical design (optional) +│ ├── implement.jsonl # Context for implement phase +│ ├── check.jsonl # Context for check phase +│ ├── debug.jsonl # Context for debug phase +│ ├── research.jsonl # Context for research phase (optional) +│ └── cr.jsonl # Context for code review (optional) │ -└── archive/ # Completed tasks +└── archive/ # Completed tasks └── {YYYY-MM}/ └── {task-dir}/ ``` @@ -25,12 +27,12 @@ Track work items with phase-based execution. ## Task Directory Naming -Format: `{MM-DD}-{slug}-{assignee}` +Format: `{MM-DD}-{slug}` Examples: -- `01-31-add-login-taosu` -- `02-01-fix-api-bug-cursor-agent` +- `03-24-add-login` +- `03-10-fix-api-bug` --- @@ -40,39 +42,69 @@ Task metadata and workflow configuration. ```json { + "id": "03-24-add-login", "name": "Add user login", - "slug": "add-login", - "created": "2026-01-31T10:30:00", - "assignee": "taosu", - "status": "active", + "title": "Add user login", + "description": "Implement email/password authentication", + "status": "planning", "dev_type": "fullstack", - "scope": ["frontend", "backend"], + "scope": "auth", + "package": "cli", + "priority": "P1", + "creator": "taosu", + "assignee": "taosu", + "createdAt": "2026-03-24T10:30:00", + "completedAt": null, "branch": "feature/add-login", "base_branch": "main", + "worktree_path": null, "current_phase": 1, "next_action": [ { "phase": 1, "action": "implement" }, { "phase": 2, "action": "check" }, { "phase": 3, "action": "finish" } - ] + ], + "commit": null, + "pr_url": null, + "children": [], + "parent": null, + "subtasks": [], + "relatedFiles": [], + "notes": "", + "meta": {} } ``` ### Fields -| Field | Type | Description | -| --------------- | -------- | ---------------------------------- | -| `name` | string | Human-readable task name | -| `slug` | string | URL-safe identifier | -| `created` | ISO date | Creation timestamp | -| `assignee` | string | Developer name | -| `status` | string | `active`, `paused`, `completed` | -| `dev_type` | string | `frontend`, `backend`, `fullstack` | -| `scope` | array | Affected areas | -| `branch` | string | Git branch name | -| `base_branch` | string | Branch to merge into | -| `current_phase` | number | Current workflow phase | -| `next_action` | array | Workflow phases | +| Field | Type | Description | +| --------------- | -------------- | ---------------------------------------------- | +| `id` | string | Task identifier | +| `name` | string | Human-readable task name | +| `title` | string | Task title | +| `description` | string | Task description | +| `status` | string | `planning`, `in_progress`, `review`, `completed` | +| `dev_type` | string | `frontend`, `backend`, `fullstack`, `test`, `docs` | +| `scope` | string \| null | Scope for PR title | +| `package` | string \| null | Package name (monorepo) | +| `priority` | string | `P0`, `P1`, `P2`, `P3` | +| `creator` | string | Developer who created the task | +| `assignee` | string | Assigned developer | +| `createdAt` | ISO date | Creation timestamp | +| `completedAt` | ISO date\|null | Completion timestamp | +| `branch` | string \| null | Git branch name | +| `base_branch` | string \| null | Branch to merge into (PR target) | +| `worktree_path` | string \| null | Worktree path (multi-session) | +| `current_phase` | number | Current workflow phase | +| `next_action` | array | Workflow phases | +| `commit` | string \| null | Commit hash | +| `pr_url` | string \| null | Pull request URL | +| `children` | array | Child task directory names (subtasks) | +| `parent` | string \| null | Parent task directory name | +| `subtasks` | array | Subtask list (legacy) | +| `relatedFiles` | array | Related file paths | +| `notes` | string | Free-form notes | +| `meta` | dict | Metadata dictionary (extensible) | --- @@ -83,41 +115,34 @@ Requirements document for the task. ```markdown # Add User Login -## Overview - +## Goal Implement user authentication with email/password. ## Requirements - -1. Login form with email and password fields -2. Form validation -3. API endpoint for authentication -4. Session management +- Login form with email and password fields +- Form validation +- API endpoint for authentication ## Acceptance Criteria - - [ ] User can log in with valid credentials - [ ] Error shown for invalid credentials -- [ ] Session persists across page refresh ## Technical Notes - - Use existing auth service pattern -- Follow security guidelines in spec ``` --- ## JSONL Context Files -List files to inject as context for each phase. +List files to inject as context for each agent phase. ### Format ```jsonl {"file": ".trellis/spec/backend/index.md", "reason": "Backend guidelines"} -{"file": "src/services/auth.ts", "reason": "Existing auth service"} -{"file": ".trellis/tasks/01-31-add-login/prd.md", "reason": "Requirements"} +{"file": "src/services/auth.ts", "reason": "Existing pattern"} +{"file": ".trellis/tasks/03-24-add-login/prd.md", "reason": "Requirements"} ``` ### Files @@ -127,66 +152,115 @@ List files to inject as context for each phase. | `implement.jsonl` | implement | Dev specs, patterns to follow | | `check.jsonl` | check | Quality criteria, review specs | | `debug.jsonl` | debug | Debug context, error reports | +| `research.jsonl` | research | Codebase analysis context | +| `cr.jsonl` | code review | Code review criteria | --- -## Current Task Pointer +## Subtasks -### `.trellis/.current-task` +Tasks can have parent-child relationships for decomposing complex work. -Points to active task directory. - -``` -.trellis/tasks/01-31-add-login-taosu -``` - -### Set Current Task +### Create Subtask ```bash -python3 .trellis/scripts/task.py start +# Option 1: Create with --parent flag +python3 .trellis/scripts/task.py create "Login API" --parent .trellis/tasks/03-24-add-login + +# Option 2: Link existing tasks +python3 .trellis/scripts/task.py add-subtask ``` -### Clear Current Task +### Behavior -```bash -python3 .trellis/scripts/task.py stop -``` +- Parent's `children` array contains child directory names +- Child's `parent` field points to parent directory name +- `task.py list` shows subtask hierarchy +- Unlinking: `task.py remove-subtask ` --- -## Task CLI +## Task Lifecycle Hooks -### Create Task +Shell commands that run automatically after task lifecycle events. -```bash -python3 .trellis/scripts/task.py create "Task name" --slug task-slug +### Configuration (config.yaml) + +```yaml +hooks: + after_create: + - python3 .trellis/scripts/hooks/linear_sync.py create + after_start: + - python3 .trellis/scripts/hooks/linear_sync.py start + after_finish: + - python3 .trellis/scripts/hooks/linear_sync.py finish + after_archive: + - python3 .trellis/scripts/hooks/linear_sync.py archive ``` -### List Tasks +### Events + +| Event | Trigger | Use Case | +|-------|---------|----------| +| `after_create` | `task.py create` completes | Create issue in Linear/Jira | +| `after_start` | `task.py start` completes | Update issue status | +| `after_finish` | `task.py finish` completes | Mark issue done | +| `after_archive` | `task.py archive` completes | Close external issue | + +### Environment + +Hook commands receive `TASK_JSON_PATH` — the absolute path to the task's `task.json`. + +### Built-in Hook: Linear Sync + +Ships with `hooks/linear_sync.py` that syncs task events to Linear via the `linearis` CLI tool. + +--- + +## Current Task Pointer + +### `.trellis/.current-task` + +Points to active task directory. -```bash -python3 .trellis/scripts/task.py list +``` +.trellis/tasks/03-24-add-login ``` -### Start Task +### Set Current Task ```bash python3 .trellis/scripts/task.py start ``` -### Initialize Context +### Clear Current Task ```bash -python3 .trellis/scripts/task.py init-context +python3 .trellis/scripts/task.py finish ``` -Dev types: `frontend`, `backend`, `fullstack` - -### Archive Task +--- -```bash -python3 .trellis/scripts/task.py archive -``` +## Task CLI (16 Subcommands) + +| Subcommand | Description | +|------------|-------------| +| `create` | Create new task (with --slug, --assignee, --priority, --parent, --package) | +| `init-context` | Initialize JSONL files (backend/frontend/fullstack/test/docs) | +| `add-context` | Add entry to JSONL (implement/check/debug) | +| `validate` | Validate JSONL files | +| `list-context` | List JSONL entries | +| `start` | Set as current task | +| `finish` | Clear current task | +| `set-branch` | Set git branch | +| `set-base-branch` | Set PR target branch | +| `set-scope` | Set scope for PR title | +| `create-pr` | Create PR from task | +| `archive` | Archive completed task (--no-commit to skip auto-commit) | +| `add-subtask` | Link child task to parent | +| `remove-subtask` | Unlink child from parent | +| `list` | List active tasks (--mine, --status filters) | +| `list-archive` | List archived tasks (optional YYYY-MM filter) | --- @@ -221,3 +295,5 @@ Modify `next_action` in task.json: 2. **Clear PRDs** - Write specific, testable requirements 3. **Relevant context** - Only include needed files in JSONL 4. **Archive completed** - Keep task directory clean +5. **Use subtasks** - Decompose complex work into trackable units +6. **Configure lifecycle hooks** - Integrate with external issue trackers diff --git a/marketplace/skills/trellis-meta/references/how-to-modify/add-command.md b/marketplace/skills/trellis-meta/references/how-to-modify/add-command.md index 0a69d12d..bbef04fa 100644 --- a/marketplace/skills/trellis-meta/references/how-to-modify/add-command.md +++ b/marketplace/skills/trellis-meta/references/how-to-modify/add-command.md @@ -2,7 +2,7 @@ Add a new `/trellis:my-command` command. -**Platform**: All (9 platforms — each has its own command format) +**Platform**: All (11 platforms — each has its own command format) --- @@ -59,16 +59,18 @@ What the command produces. Commands are automatically mirrored to configured platforms by `trellis init` and `trellis update`. Each platform uses its own format: -| Platform | Path | Format | -| ----------- | ------------------------------------------ | -------- | -| Cursor | `.cursor/commands/trellis-my-command.md` | Markdown | -| OpenCode | `.opencode/agents/trellis-my-command.md` | Markdown | -| iFlow | `.iflow/commands/trellis/my-command.md` | Markdown | -| Codex | `.agents/skills/my-command/SKILL.md` | Skill | -| Kilo | `.kilocode/commands/trellis/my-command.md` | Markdown | -| Kiro | `.kiro/skills/my-command/SKILL.md` | Skill | -| Gemini CLI | `.gemini/commands/trellis/my-command.toml` | TOML | -| Antigravity | `.agent/workflows/my-command.md` | Markdown | +| Platform | Path | Format | +| ----------- | ----------------------------------------------- | -------- | +| Cursor | `.cursor/commands/trellis-my-command.md` | Markdown | +| OpenCode | `.opencode/agents/trellis-my-command.md` | Markdown | +| iFlow | `.iflow/commands/trellis/my-command.md` | Markdown | +| Codex | `.codex/skills/my-command/SKILL.md` | Skill | +| Kilo | `.kilocode/workflows/my-command.md` | Workflow | +| Kiro | `.kiro/skills/my-command/SKILL.md` | Skill | +| Gemini CLI | `.gemini/commands/trellis/my-command.toml` | TOML | +| Antigravity | `.agent/workflows/my-command.md` | Workflow | +| Qoder | `.qoder/skills/my-command/SKILL.md` | Skill | +| CodeBuddy | `.codebuddy/commands/trellis/my-command.md` | Markdown | --- diff --git a/marketplace/skills/trellis-meta/references/how-to-modify/overview.md b/marketplace/skills/trellis-meta/references/how-to-modify/overview.md index 49ff53cc..a6afa304 100644 --- a/marketplace/skills/trellis-meta/references/how-to-modify/overview.md +++ b/marketplace/skills/trellis-meta/references/how-to-modify/overview.md @@ -19,7 +19,7 @@ Common Trellis customization scenarios and what files need to be modified. | [Add core script](#add-core-script) | scripts/, trellis-local | All | | [Change task types](#change-task-types) | task.py, jsonl templates | All | -**Platform**: `All` = All 9 platforms | `CC` = Claude Code + iFlow (hook-capable) +**Platform**: `All` = All 11 platforms | `CC` = Claude Code + iFlow (hook-capable) --- diff --git a/marketplace/skills/trellis-meta/references/meta/platform-compatibility.md b/marketplace/skills/trellis-meta/references/meta/platform-compatibility.md index 25df7f4f..f2963dfc 100644 --- a/marketplace/skills/trellis-meta/references/meta/platform-compatibility.md +++ b/marketplace/skills/trellis-meta/references/meta/platform-compatibility.md @@ -1,24 +1,26 @@ # Platform Compatibility Reference -Detailed guide on Trellis feature availability across 9 AI coding platforms. +Detailed guide on Trellis feature availability across 11 AI coding platforms. --- ## Overview -Trellis v0.3.0 supports **9 platforms**. The key differentiator is **hook support** — Claude Code and iFlow have Python hook systems that enable automatic context injection and quality enforcement. Other platforms use commands/skills with manual context loading. - -| Platform | Config Directory | CLI Flag | Hooks | Command Format | -| ----------- | ----------------------------- | --------------- | ----- | -------------- | -| Claude Code | `.claude/` | (default) | ✅ | Markdown | -| iFlow | `.iflow/` | `--iflow` | ✅ | Markdown | -| Cursor | `.cursor/` | `--cursor` | ❌ | Markdown | -| OpenCode | `.opencode/` | `--opencode` | ❌ | Markdown | -| Codex | `.agents/skills/` | `--codex` | ❌ | Skills | -| Kilo | `.kilocode/commands/trellis/` | `--kilo` | ❌ | Markdown | -| Kiro | `.kiro/skills/` | `--kiro` | ❌ | Skills | -| Gemini CLI | `.gemini/commands/trellis/` | `--gemini` | ❌ | TOML | -| Antigravity | `.agent/workflows/` | `--antigravity` | ❌ | Markdown | +Trellis v0.4.0 supports **11 platforms**. The key differentiator is **hook support** — Claude Code and iFlow have Python hook systems that enable automatic context injection and quality enforcement. Codex has optional SessionStart hooks. Other platforms use commands/skills with manual context loading. + +| Platform | Config Directory | CLI Flag | Hooks | Command Format | +| ----------- | ----------------------- | --------------- | ----------- | ---------------- | +| Claude Code | `.claude/` | (default) | ✅ Full | Markdown | +| iFlow | `.iflow/` | `--iflow` | ✅ Full | Markdown | +| Cursor | `.cursor/` | `--cursor` | ❌ | Markdown | +| OpenCode | `.opencode/` | `--opencode` | ❌ | Markdown | +| Codex | `.codex/` | `--codex` | ⚠️ Optional | Skills + TOML | +| Kilo | `.kilocode/` | `--kilo` | ❌ | Workflows | +| Kiro | `.kiro/skills/` | `--kiro` | ❌ | Skills | +| Gemini CLI | `.gemini/` | `--gemini` | ❌ | TOML | +| Antigravity | `.agent/workflows/` | `--antigravity` | ❌ | Markdown | +| Qoder | `.qoder/` | `--qoder` | ❌ | Skills | +| CodeBuddy | `.codebuddy/` | `--codebuddy` | ❌ | Markdown (nested)| --- @@ -30,24 +32,32 @@ Trellis v0.3.0 supports **9 platforms**. The key differentiator is **hook suppor ├─────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌────────────────────────────────────────────────────────────────────┐ │ -│ │ LAYER 3: AUTOMATION │ │ +│ │ LAYER 4: AUTOMATION │ │ │ │ Hooks, Ralph Loop, Auto-injection, Multi-Session │ │ │ │ ─────────────────────────────────────────────────────────────────│ │ -│ │ Platform: Claude Code + iFlow │ │ +│ │ Platform: Claude Code + iFlow (full), Codex (SessionStart only) │ │ +│ └────────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ┌────────────────────────────────▼───────────────────────────────────┐ │ +│ │ LAYER 3: AGENTS │ │ +│ │ Agent definitions, Agent tool, Subagent invocation │ │ +│ │ ─────────────────────────────────────────────────────────────────│ │ +│ │ Platform: Claude Code + iFlow (full), Codex (TOML agents), │ │ +│ │ others (manual) │ │ │ └────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ ┌────────────────────────────────▼───────────────────────────────────┐ │ -│ │ LAYER 2: AGENTS │ │ -│ │ Agent definitions, Task tool, Subagent invocation │ │ +│ │ LAYER 2: SHARED AGENT SKILLS │ │ +│ │ .agents/skills/ (agentskills.io open standard) │ │ │ │ ─────────────────────────────────────────────────────────────────│ │ -│ │ Platform: Claude Code + iFlow (full), others (manual) │ │ +│ │ Platform: Codex + universal agent CLIs (Kimi, Amp, Cline, etc.) │ │ │ └────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ ┌────────────────────────────────▼───────────────────────────────────┐ │ │ │ LAYER 1: PERSISTENCE │ │ │ │ Workspace, Tasks, Specs, Commands/Skills, JSONL files │ │ │ │ ─────────────────────────────────────────────────────────────────│ │ -│ │ Platform: ALL 9 (file-based, portable) │ │ +│ │ Platform: ALL 11 (file-based, portable) │ │ │ └────────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────┘ @@ -57,41 +67,48 @@ Trellis v0.3.0 supports **9 platforms**. The key differentiator is **hook suppor ## Detailed Feature Breakdown -### Layer 1: Persistence (All 9 Platforms) +### Layer 1: Persistence (All 11 Platforms) These features work on all platforms because they're file-based. | Feature | Location | Description | | ------------------ | ------------------------ | ----------------------------------------- | | Workspace system | `.trellis/workspace/` | Journals, session history | -| Task system | `.trellis/tasks/` | Task tracking, requirements | -| Spec system | `.trellis/spec/` | Coding guidelines | +| Task system | `.trellis/tasks/` | Task tracking, subtasks, lifecycle hooks | +| Spec system | `.trellis/spec/` | Coding guidelines (monorepo per-package) | +| Config system | `.trellis/config.yaml` | Packages, hooks, update.skip, spec_scope | | Commands/Skills | Platform-specific dirs | Command prompts in each platform's format | | JSONL context | `*.jsonl` in task dirs | Context file lists | | Developer identity | `.trellis/.developer` | Who is working | | Current task | `.trellis/.current-task` | Active task pointer | -### Layer 2: Agents (Claude Code + iFlow Full, Others Manual) +### Layer 2: Shared Agent Skills -| Feature | Claude Code / iFlow | Other Platforms | -| ------------------ | ------------------------------ | ------------------------- | -| Agent definitions | Auto-loaded via `--agent` flag | Read agent files manually | -| Task tool | Full subagent support | No Task tool | -| Context injection | Automatic via hooks | Manual copy-paste | -| Agent restrictions | Enforced by definition | Honor code only | +| Feature | Location | Description | +| ------------------ | ---------------------- | ------------------------------------------ | +| Shared skills | `.agents/skills/` | agentskills.io standard, SKILL.md format | -### Layer 3: Automation (Claude Code + iFlow Only) +Readable by Codex and any universal agent CLI that follows the agentskills.io open standard. -| Feature | Dependency | Why Hook-Platforms Only | -| ---------------------- | ------------------ | -------------------------------- | -| SessionStart hook | `settings.json` | Hook system for lifecycle events | -| PreToolUse hook | Hook system | Intercepts tool calls | -| SubagentStop hook | Hook system | Controls agent lifecycle | -| Auto context injection | PreToolUse:Task | Hooks inject JSONL content | -| Ralph Loop | SubagentStop:check | Blocks agent until verify passes | -| Multi-Session | CLI + hooks | Session resume, worktree scripts | +### Layer 3: Agents (Claude Code + iFlow Full, Codex TOML, Others Manual) -**No workaround**: These features fundamentally require a hook system. +| Feature | Claude Code / iFlow | Codex | Other Platforms | +| ------------------ | ------------------------------ | ------------------------------ | ------------------------- | +| Agent definitions | Auto-loaded via `--agent` flag | TOML agents in `.codex/agents/` | Read agent files manually | +| Agent tool | Full subagent support | Built-in agent support | No Agent tool | +| Context injection | Automatic via hooks | Manual / SessionStart only | Manual copy-paste | +| Agent restrictions | Enforced by definition | TOML `sandbox_mode` | Honor code only | + +### Layer 4: Automation (Claude Code + iFlow Full, Codex Partial) + +| Feature | Dependency | Claude Code / iFlow | Codex | +| ---------------------- | ---------------------- | ------------------- | ----------------- | +| SessionStart hook | `settings.json` | ✅ Full | ⚠️ Optional | +| PreToolUse hook | Hook system | ✅ Full | ❌ None | +| SubagentStop hook | Hook system | ✅ Full | ❌ None | +| Auto context injection | PreToolUse:Agent | ✅ Full | ❌ None | +| Ralph Loop | SubagentStop:check | ✅ Full | ❌ None | +| Multi-Session | CLI + hooks | ✅ Full | ❌ None | --- @@ -132,9 +149,29 @@ trellis init --opencode -u your-name trellis init --codex -u your-name ``` -- Commands mapped to Codex Skills format under `.agents/skills/` +- Platform-specific skills in `.codex/skills/` + shared skills in `.agents/skills/` +- TOML agent definitions in `.codex/agents/` (implement, research, check) +- Optional SessionStart hook (requires `codex_hooks = true` in `~/.codex/config.toml`) - Use `$start`, `$finish-work`, `$brainstorm` etc. to invoke +### Qoder + +```bash +trellis init --qoder -u your-name +``` + +- Skills-based platform with templates at `.qoder/skills/{name}/SKILL.md` +- Uses YAML frontmatter for skill metadata + +### CodeBuddy (Tencent Cloud) + +```bash +trellis init --codebuddy -u your-name +``` + +- Nested slash commands at `.codebuddy/commands/trellis/{name}.md` +- 12 command templates included + ### Kilo, Kiro, Gemini CLI, Antigravity ```bash @@ -145,16 +182,22 @@ trellis init --antigravity -u your-name ``` - Each platform uses its native command format +- Kilo uses workflows (`.kilocode/workflows/`) +- Kiro uses skills (`.kiro/skills/{name}/SKILL.md`) +- Gemini uses TOML commands (`.gemini/commands/trellis/{name}.toml`) +- Antigravity uses workflows (`.agent/workflows/`) - Core file-based systems work the same across all platforms --- ## Version Compatibility Matrix -| Trellis Version | Platforms Supported | -| --------------- | ------------------- | -| 0.2.x | Claude Code, Cursor | -| 0.3.0 | All 9 platforms | +| Trellis Version | Platforms Supported | +| ----------------- | ------------------------------- | +| 0.2.x | Claude Code, Cursor | +| 0.3.0 | 9 platforms (+ OpenCode through Antigravity) | +| 0.3.4 | 10 platforms (+ Qoder) | +| 0.4.0-beta.6 | 11 platforms (+ CodeBuddy) | --- @@ -171,7 +214,7 @@ cat .claude/settings.json | grep -A 5 '"hooks"' ```bash # Check if platform config directory exists -ls -la .cursor/ .opencode/ .iflow/ .agents/ .kilocode/ .kiro/ .gemini/ .agent/ 2>/dev/null +ls -la .cursor/ .opencode/ .iflow/ .codex/ .agents/ .kilocode/ .kiro/ .gemini/ .agent/ .qoder/ .codebuddy/ 2>/dev/null ``` ### Determining Support Level @@ -179,7 +222,8 @@ ls -la .cursor/ .opencode/ .iflow/ .agents/ .kilocode/ .kiro/ .gemini/ .agent/ 2 ``` Does the platform have hook support? ├── YES (Claude Code, iFlow) → Full Trellis support +├── PARTIAL (Codex) → SessionStart hook + TOML agents + shared skills └── NO (all others) → Partial support ├── Can read files → Layer 1 works - └── Has agent system → Layer 2 partial + └── Has agent system → Layer 3 partial ``` diff --git a/packages/cli/src/templates/claude/hooks/statusline.py b/packages/cli/src/templates/claude/hooks/statusline.py new file mode 100644 index 00000000..696d6087 --- /dev/null +++ b/packages/cli/src/templates/claude/hooks/statusline.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Trellis StatusLine — project-level status display for Claude Code. + +Reads Claude Code session JSON from stdin + Trellis task data from filesystem. +Outputs 1-2 lines: + With active task: [P1] Task title (status) + info line + Without task: info line only +Info line: model · ctx% · branch · duration · developer · tasks · rate limits +""" +from __future__ import annotations + +import json +import re +import subprocess +import sys +from pathlib import Path + + +def _read_text(path: Path) -> str: + try: + return path.read_text(encoding="utf-8").strip() + except (FileNotFoundError, PermissionError, OSError): + return "" + + +def _read_json(path: Path) -> dict: + text = _read_text(path) + if not text: + return {} + try: + return json.loads(text) + except (json.JSONDecodeError, ValueError): + return {} + + +def _find_trellis_dir() -> Path | None: + """Walk up from cwd to find .trellis/ directory.""" + current = Path.cwd() + for parent in [current, *current.parents]: + candidate = parent / ".trellis" + if candidate.is_dir(): + return candidate + return None + + +def _get_current_task(trellis_dir: Path) -> dict | None: + """Load current task info. Returns dict with title/status/priority or None.""" + task_ref = _read_text(trellis_dir / ".current-task") + if not task_ref: + return None + + # Resolve task directory + task_path = Path(task_ref) if Path(task_ref).is_absolute() else trellis_dir.parent / task_ref + task_data = _read_json(task_path / "task.json") + if not task_data: + return None + + return { + "title": task_data.get("title") or task_data.get("name") or "unknown", + "status": task_data.get("status", "unknown"), + "priority": task_data.get("priority", "P2"), + } + + +def _count_active_tasks(trellis_dir: Path) -> int: + """Count non-archived task directories with valid task.json.""" + tasks_dir = trellis_dir / "tasks" + if not tasks_dir.is_dir(): + return 0 + count = 0 + for d in tasks_dir.iterdir(): + if d.is_dir() and d.name != "archive" and (d / "task.json").is_file(): + count += 1 + return count + + +def _get_developer(trellis_dir: Path) -> str: + content = _read_text(trellis_dir / ".developer") + if not content: + return "unknown" + for line in content.splitlines(): + if line.startswith("name="): + return line[5:].strip() + return content.splitlines()[0].strip() or "unknown" + + +def _get_git_branch() -> str: + try: + result = subprocess.run( + ["git", "branch", "--show-current"], + capture_output=True, text=True, timeout=3, + ) + return result.stdout.strip() if result.returncode == 0 else "" + except (FileNotFoundError, subprocess.TimeoutExpired): + return "" + + +def _format_ctx_size(size: int) -> str: + if size >= 1_000_000: + return f"{size // 1_000_000}M" + if size >= 1_000: + return f"{size // 1_000}K" + return str(size) + + +def _format_duration(ms: int) -> str: + secs = ms // 1000 + hours, remainder = divmod(secs, 3600) + mins = remainder // 60 + if hours > 0: + return f"{hours}h{mins}m" + return f"{mins}m" + + +def main() -> None: + # Read Claude Code session JSON from stdin + try: + cc_data = json.loads(sys.stdin.read()) + except (json.JSONDecodeError, ValueError): + cc_data = {} + + trellis_dir = _find_trellis_dir() + SEP = " \033[90m·\033[0m " + + # --- Trellis data --- + task = _get_current_task(trellis_dir) if trellis_dir else None + dev = _get_developer(trellis_dir) if trellis_dir else "" + task_count = _count_active_tasks(trellis_dir) if trellis_dir else 0 + + # --- CC session data --- + model = cc_data.get("model", {}).get("display_name", "?") + ctx_pct = int(cc_data.get("context_window", {}).get("used_percentage") or 0) + ctx_size = _format_ctx_size(cc_data.get("context_window", {}).get("context_window_size") or 0) + duration = _format_duration(cc_data.get("cost", {}).get("total_duration_ms") or 0) + branch = _get_git_branch() + + # Avoid "Opus 4.6 (1M context) (1M)" + if re.search(r"\d+[KMG]\b", model, re.IGNORECASE): + model_label = model + else: + model_label = f"{model} ({ctx_size})" + + # Context % with color + if ctx_pct >= 90: + ctx_color = "\033[31m" + elif ctx_pct >= 70: + ctx_color = "\033[33m" + else: + ctx_color = "\033[32m" + + # Build info line: model · ctx · branch · duration · dev · tasks [· rate limits] + parts = [ + model_label, + f"ctx {ctx_color}{ctx_pct}%\033[0m", + ] + if branch: + parts.append(f"\033[35m{branch}\033[0m") + parts.append(duration) + if dev: + parts.append(f"\033[32m{dev}\033[0m") + if task_count: + parts.append(f"{task_count} task(s)") + + five_hr = cc_data.get("rate_limits", {}).get("five_hour", {}).get("used_percentage") + if five_hr is not None: + parts.append(f"5h {int(five_hr)}%") + seven_day = cc_data.get("rate_limits", {}).get("seven_day", {}).get("used_percentage") + if seven_day is not None: + parts.append(f"7d {int(seven_day)}%") + + info_line = SEP.join(parts) + + # Output: task line (only if active) + info line + if task: + print(f"\033[36m[{task['priority']}]\033[0m {task['title']} \033[33m({task['status']})\033[0m") + print(info_line) + + +if __name__ == "__main__": + main() diff --git a/packages/cli/src/templates/claude/settings.json b/packages/cli/src/templates/claude/settings.json index 4798bba1..93f5e8b1 100644 --- a/packages/cli/src/templates/claude/settings.json +++ b/packages/cli/src/templates/claude/settings.json @@ -1,4 +1,8 @@ { + "statusLine": { + "type": "command", + "command": "{{PYTHON_CMD}} .claude/hooks/statusline.py" + }, "hooks": { "SessionStart": [ { diff --git a/packages/cli/src/types/ai-tools.ts b/packages/cli/src/types/ai-tools.ts index f18e2110..a15a4157 100644 --- a/packages/cli/src/types/ai-tools.ts +++ b/packages/cli/src/types/ai-tools.ts @@ -129,7 +129,7 @@ export const AI_TOOLS: Record = { supportsAgentSkills: true, cliFlag: "codex", defaultChecked: false, - hasPythonHooks: false, + hasPythonHooks: true, }, kilo: { name: "Kilo CLI",