Skip to content

Commit 6b18022

Browse files
studd
1 parent bfbb9d6 commit 6b18022

7 files changed

Lines changed: 61 additions & 67 deletions

File tree

.ai-workspace/docs/configuration.md

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -75,19 +75,9 @@ Controls repository status reporting at session start. Section: `[repositories]`
7575

7676
## Session hooks
7777

78-
Session hooks are pre-configured statically in each tool's config directory -- they're committed to the repo and work out of the box.
78+
Session hooks are pre-configured in each tool's config directory -- they're committed to the repo and work out of the box. No configuration needed.
7979

80-
The session-start script (`.ai-workspace/scripts/session-start.py`) runs two tasks:
81-
82-
1. **Repository status** -- Reports each submodule's branch, uncommitted changes, and how far behind remote
83-
2. **Tool discovery** -- Detects installed CLI tools and injects usage instructions
84-
85-
The output is wrapped in `<session-context>` XML tags that agents consume automatically.
86-
87-
Hook configurations are stored in:
88-
89-
- **Claude Code** -- `.claude/settings.json`
90-
- **OpenCode** -- `.opencode/plugins/session-sync.ts`
80+
The session-start script runs repository status reporting and tool discovery, then injects the results into the agent's context. See [Session Hooks](development/session-hooks.md) for supported tools and details.
9181

9282
---
9383

.ai-workspace/docs/features/tool-discovery.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Tool Discovery detects installed CLI tools on your system and tells AI agents ab
44

55
!!! info "Requires hook support"
66

7-
Tool discovery context is injected via session hooks, which currently work with [Claude Code](https://code.claude.com/docs/en/hooks) and [OpenCode](https://opencode.ai/docs/plugins/).
7+
Tool discovery context is injected via session hooks. See [Session Hooks](../development/session-hooks.md) for which tools are supported and how to add more.
88

99
Other tools can still use the workspace but won't receive automatic tool discovery context.
1010

.ai-workspace/docs/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ A meta-repository template that aggregates related repositories using git submod
7070

7171
Some AI tools support **hooks** -- scripts that run automatically at specific lifecycle points (e.g., session start, pre-prompt). This workspace uses a session-start hook to inject context into the agent before it begins work.
7272

73-
For tools with hook support ([Claude Code](https://code.claude.com/docs/en/hooks), [OpenCode](https://opencode.ai/docs/plugins/)), the session-start script runs automatically when an AI session begins:
73+
For tools with hook support ([Claude Code](https://code.claude.com/docs/en/hooks), [OpenCode](https://opencode.ai/docs/plugins/), [Cursor](https://cursor.com/docs/agent/hooks), [Gemini CLI](https://geminicli.com/docs/hooks/)), the session-start script runs automatically when an AI session begins:
7474

7575
``` mermaid
7676
graph LR
@@ -95,7 +95,7 @@ These are two independent flows -- session hooks handle runtime context, pre-com
9595

9696
!!! info "Other AI tools"
9797

98-
Tools without hook support (Cursor, Roo Code, etc.) still work with skills, commands, and agent docs -- they just won't get automatic session-start context injection.
98+
Tools without hook support still work with skills, commands, and agent docs -- they just won't get automatic session-start context injection. See [Session Hooks](development/session-hooks.md) for which tools are supported and how to add more.
9999

100100
## Project structure
101101

.ai-workspace/scripts/session-start.py

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,25 @@
11
#!/usr/bin/env python3
2-
"""Main session-start orchestrator for AI tool hooks.
2+
"""Session-start orchestrator for AI tool hooks.
33
4-
This script runs at the start of AI tool sessions (OpenCode, Claude Code, etc.)
5-
and collects context from multiple sources into a unified output.
4+
Runs at the start of AI tool sessions and collects context from multiple
5+
sources into a unified output.
66
7-
Each source adds its section to the SessionContext, and the final output
8-
is wrapped in <session-context> tags for the LLM to understand.
7+
Supports two output modes:
8+
- Plain text (default): For tools that capture stdout directly
9+
(Claude Code, OpenCode, manual runs).
10+
- JSON (--tool <name>): For tools that require a JSON hook protocol
11+
(Cursor, Gemini CLI). Each tool's JSON schema is defined in FORMATTERS.
12+
13+
Adding a new tool: add an entry to FORMATTERS and create the tool's config file.
914
"""
1015

16+
from __future__ import annotations
17+
18+
import argparse
19+
import json
1120
import sys
1221
from pathlib import Path
22+
from typing import Any
1323

1424
# Add lib to path for imports
1525
sys.path.insert(0, str(Path(__file__).parent.parent / "lib"))
@@ -20,9 +30,17 @@
2030
from repository_status import run_repository_status
2131
from tool_discovery import run_tool_discovery
2232

33+
# JSON output formatters for tools that use a JSON hook protocol.
34+
# Each formatter receives the rendered context string and returns a dict
35+
# matching the tool's expected sessionStart output schema.
36+
FORMATTERS: dict[str, Any] = {
37+
"cursor": lambda ctx: {"additional_context": ctx},
38+
"gemini": lambda ctx: {"hookSpecificOutput": {"additionalContext": ctx}},
39+
}
2340

24-
def main() -> None:
25-
"""Run all session-start tasks and output unified context."""
41+
42+
def collect_context() -> str:
43+
"""Run all session-start tasks and return the rendered context."""
2644
ctx = SessionContext()
2745

2846
# Get repository root (scripts are in .ai-workspace/scripts/)
@@ -34,8 +52,33 @@ def main() -> None:
3452
# Run tool discovery
3553
run_tool_discovery(ctx, repo_root)
3654

37-
# Output the combined context
38-
ctx.print()
55+
return ctx.render()
56+
57+
58+
def main() -> None:
59+
"""Run session-start tasks and output context in the requested format."""
60+
parser = argparse.ArgumentParser(description="Session-start context collector")
61+
parser.add_argument(
62+
"--tool",
63+
choices=FORMATTERS,
64+
help="Output JSON in the specified tool's hook format. "
65+
"Without this flag, outputs plain text.",
66+
)
67+
args = parser.parse_args()
68+
69+
# Tools with JSON protocols send input on stdin; consume it so the
70+
# process doesn't hang.
71+
if args.tool:
72+
sys.stdin.read()
73+
74+
output = collect_context()
75+
76+
if args.tool:
77+
response = FORMATTERS[args.tool](output) if output else {}
78+
json.dump(response, sys.stdout)
79+
else:
80+
if output:
81+
print(output)
3982

4083

4184
if __name__ == "__main__":

.ai-workspace/zensical.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ nav = [
1717
{ Skills = "features/skills.md" },
1818
{ Commands = "features/commands.md" },
1919
] },
20+
{ Development = [
21+
{ "Session Hooks" = "development/session-hooks.md" },
22+
] },
2023

2124
]
2225

.cursor/hooks.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"hooks": {
44
"sessionStart": [
55
{
6-
"command": "uv run .cursor/hooks/session-start.py",
6+
"command": "uv run .ai-workspace/scripts/session-start.py --tool cursor",
77
"timeout": 120
88
}
99
]

.cursor/hooks/session-start.py

Lines changed: 0 additions & 42 deletions
This file was deleted.

0 commit comments

Comments
 (0)