Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions backlog/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
project_name: "canaryhook"
default_status: "To Do"
statuses: ["To Do", "In Progress", "Done"]
labels: []
date_format: yyyy-mm-dd
max_column_width: 20
auto_open_browser: false
default_port: 6420
remote_operations: true
auto_commit: false
filesystem_only: false
bypass_git_hooks: false
check_active_branches: true
active_branch_days: 30
task_prefix: "task"
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
id: TASK-1
title: Refactor the Claude Code wiring into an agent adapter
status: To Do
assignee: []
created_date: '2026-10-24 05:41'
labels:
- multi-agent
dependencies: []
priority: high
ordinal: 1000
---

## Description

<!-- SECTION:DESCRIPTION:BEGIN -->
Move the Claude-specific parts (settings path, hook registration, payload parsing, deny/output/session response shapes) behind an Agent interface in src/agents/, so other agents can be added without touching the detection code. No behavior change.
<!-- SECTION:DESCRIPTION:END -->

## Acceptance Criteria
<!-- AC:BEGIN -->
- [ ] #1 src/agents/claude.ts holds everything Claude-specific
- [ ] #2 hook, session-start, init, status, doctor and clean go through the adapter
- [ ] #3 Existing tests pass unchanged
<!-- AC:END -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
id: TASK-2
title: 'Add --agents selection to init, status, doctor and clean'
status: To Do
assignee: []
created_date: '2026-10-24 05:41'
labels:
- multi-agent
dependencies:
- TASK-1
priority: high
ordinal: 2000
---

## Description

<!-- SECTION:DESCRIPTION:BEGIN -->
init takes --agents claude,cursor,... and records the chosen agents in canaries.json; by default it wires Claude plus any agent whose config dir already exists in the project. hook and session-start take --agent <name>; without it they mean claude, so existing installs keep working.
<!-- SECTION:DESCRIPTION:END -->

## Acceptance Criteria
<!-- AC:BEGIN -->
- [ ] #1 init --agents writes only the chosen agents' configs
- [ ] #2 status and doctor report each wired agent
- [ ] #3 clean unregisters every wired agent
- [ ] #4 Old state files without an agents field read as claude
<!-- AC:END -->
29 changes: 29 additions & 0 deletions backlog/tasks/task-3 - Support-Cursor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
id: TASK-3
title: Support Cursor
status: To Do
assignee: []
created_date: '2026-10-24 05:41'
labels:
- multi-agent
dependencies:
- TASK-2
references:
- 'https://cursor.com/docs/agent/hooks'
priority: high
ordinal: 3000
---

## Description

<!-- SECTION:DESCRIPTION:BEGIN -->
Register preToolUse, postToolUse and sessionStart in .cursor/hooks.json (version 1). Cursor blocks the action on empty or invalid output from a permission hook, so a pass must print {"permission":"allow"}. Deny prints permission deny with user_message and agent_message. Root comes from cwd or workspace_roots. Protect .cursor/hooks.json in the tamper check.
<!-- SECTION:DESCRIPTION:END -->

## Acceptance Criteria
<!-- AC:BEGIN -->
- [ ] #1 A read of a decoy through Cursor's preToolUse is denied and recorded
- [ ] #2 A clean call prints an explicit allow
- [ ] #3 postToolUse catches a canary in tool_output
- [ ] #4 Removing the hook from .cursor/hooks.json trips tamper
<!-- AC:END -->
29 changes: 29 additions & 0 deletions backlog/tasks/task-4 - Support-Codex-CLI.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
id: TASK-4
title: Support Codex CLI
status: To Do
assignee: []
created_date: '2026-10-24 05:41'
labels:
- multi-agent
dependencies:
- TASK-2
references:
- 'https://learn.chatgpt.com/docs/hooks'
priority: high
ordinal: 4000
---

## Description

<!-- SECTION:DESCRIPTION:BEGIN -->
Register PreToolUse, PostToolUse and SessionStart in .codex/hooks.json (same shape as Claude). Codex accepts hookSpecificOutput.permissionDecision. Project hooks only run once trusted, so init and doctor tell the user to run /hooks in Codex. Handle tool_input.command as a string or an array. Protect .codex/hooks.json and a hooks = false feature flag in .codex/config.toml in the tamper check.
<!-- SECTION:DESCRIPTION:END -->

## Acceptance Criteria
<!-- AC:BEGIN -->
- [ ] #1 A decoy read through Codex PreToolUse is denied and recorded
- [ ] #2 An array command is inspected like a string
- [ ] #3 init prints the trust step
- [ ] #4 Disabling hooks in .codex/config.toml trips tamper
<!-- AC:END -->
29 changes: 29 additions & 0 deletions backlog/tasks/task-5 - Support-Antigravity-CLI.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
id: TASK-5
title: Support Antigravity CLI
status: To Do
assignee: []
created_date: '2026-10-24 05:41'
labels:
- multi-agent
dependencies:
- TASK-2
references:
- 'https://antigravity.google/docs/hooks/'
priority: medium
ordinal: 5000
---

## Description

<!-- SECTION:DESCRIPTION:BEGIN -->
Register PreToolUse, PostToolUse and SessionStart under a canaryhook key in .agents/hooks.json. Payload is camelCase: toolCall.name, toolCall.args (CommandLine, AbsolutePath, TargetFile, CodeContent), workspacePaths. PreToolUse needs a decision on every call: allow on pass, deny with reason on a trip. SessionStart reports through injectSteps. Protect .agents/hooks.json in the tamper check.
<!-- SECTION:DESCRIPTION:END -->

## Acceptance Criteria
<!-- AC:BEGIN -->
- [ ] #1 A view_file of a decoy is denied and recorded
- [ ] #2 run_command CommandLine is checked like a shell command, globs included
- [ ] #3 A pass prints decision allow
- [ ] #4 Removing or disabling the canaryhook entry trips tamper
<!-- AC:END -->
28 changes: 28 additions & 0 deletions backlog/tasks/task-6 - Support-Gemini-CLI.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
id: TASK-6
title: Support Gemini CLI
status: To Do
assignee: []
created_date: '2026-10-24 05:41'
labels:
- multi-agent
dependencies:
- TASK-2
references:
- 'https://geminicli.com/docs/hooks/reference/'
priority: low
ordinal: 6000
---

## Description

<!-- SECTION:DESCRIPTION:BEGIN -->
Gemini CLI is now for paid API keys and enterprise only, but still in use. Register BeforeTool, AfterTool and SessionStart in .gemini/settings.json. Deny prints decision deny with reason; AfterTool can hide a result with decision deny; SessionStart uses hookSpecificOutput.additionalContext. Protect the hooks entry in the tamper check.
<!-- SECTION:DESCRIPTION:END -->

## Acceptance Criteria
<!-- AC:BEGIN -->
- [ ] #1 A read_file of a decoy is denied and recorded
- [ ] #2 AfterTool catches a canary in tool_response.llmContent
- [ ] #3 Removing the hook from .gemini/settings.json trips tamper
<!-- AC:END -->
28 changes: 28 additions & 0 deletions backlog/tasks/task-7 - Document-multi-agent-support.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
id: TASK-7
title: Document multi-agent support
status: To Do
assignee: []
created_date: '2026-10-24 05:41'
labels:
- multi-agent
dependencies:
- TASK-3
- TASK-4
- TASK-5
- TASK-6
priority: medium
ordinal: 7000
---

## Description

<!-- SECTION:DESCRIPTION:BEGIN -->
README: which agents are supported, the --agents flag, the per-agent config file each one writes, and agent-specific caveats (Codex trust step, Antigravity output path limits). CHANGELOG entry under Unreleased.
<!-- SECTION:DESCRIPTION:END -->

## Acceptance Criteria
<!-- AC:BEGIN -->
- [ ] #1 README lists every supported agent and its config file
- [ ] #2 Caveats are stated per agent
<!-- AC:END -->
Loading