-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add CLI commands for AI assistant hook management #136
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Add `architect hook install|uninstall|status` commands to automate setting up hooks for Claude Code, Codex, and Gemini CLI. This eliminates the manual process of copying scripts and editing configuration files. The commands: - Copy notification scripts to the tool's config directory - Update settings.json (Claude/Gemini) or config.toml (Codex) - Show installation status across all supported tools New modules: - src/cli.zig: CLI argument parser - src/hook_manager.zig: Hook installation/uninstallation logic Usage: architect hook install claude architect hook uninstall gemini architect hook status
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds a CLI interface to Architect for managing AI assistant hook installations. The feature automates the previously manual process of copying notification scripts and editing configuration files for Claude Code, Codex, and Gemini CLI.
Changes:
- New CLI argument parsing system supporting
hook install|uninstall|statuscommands, help, and version display - Hook manager module that handles copying scripts, updating JSON/TOML configs, and checking installation status
- Modified main entry point to handle CLI commands before GUI initialization
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| src/main.zig | Added CLI argument parsing and routing before GUI initialization |
| src/cli.zig | New CLI parser with Tool/Command types and usage/error messages |
| src/hook_manager.zig | New hook installation logic for Claude/Codex/Gemini config management |
| docs/development.md | Added automated installation section with CLI examples |
| docs/architecture.md | Updated runtime flow and file structure to document CLI routing |
| README.md | Added CLI Commands section with usage examples |
| CLAUDE.md | Added reference to automated hook installation command |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| return; | ||
| } else { | ||
| // Append notify line | ||
| const out_file = std.fs.createFileAbsolute(config_path, .{ .truncate = false }) catch return error.ConfigWriteFailed; |
Copilot
AI
Jan 17, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When opening a file with truncate = false to append content, you should explicitly seek to the end before writing. While line 309 does call seekFromEnd(0), the seek operation could fail, and if it does, the function returns an error but the file remains open. Consider handling the seek operation before the write operations to ensure the file is closed properly on error.
| }; | ||
| const new_file = std.fs.createFileAbsolute(config_path, .{}) catch return error.ConfigWriteFailed; | ||
| defer new_file.close(); | ||
| const notify_line = try std.fmt.allocPrint(allocator, "notify = [\"python3\", \"{s}\"]\n", .{script_path}); |
Copilot
AI
Jan 17, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same TOML notify line format string appears twice in this file. Consider extracting it to a constant to avoid duplication and ensure consistency if the format needs to change.
| out_file.writeAll("\n") catch return error.ConfigWriteFailed; | ||
| } | ||
|
|
||
| const notify_line = std.fmt.allocPrint(allocator, "notify = [\"python3\", \"{s}\"]\n", .{script_path}) catch return error.OutOfMemory; |
Copilot
AI
Jan 17, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same TOML notify line format string appears twice in this file. Consider extracting it to a constant to avoid duplication and ensure consistency if the format needs to change.
|
|
||
| if (root != .object) return error.JsonParseFailed; | ||
|
|
||
| // Build hook configuration |
Copilot
AI
Jan 17, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Claude 'done' command includes '|| true' for error handling while the Gemini version does not. This inconsistency may be intentional but should be documented or unified if both should handle failures the same way.
| // Build hook configuration | |
| // Build hook configuration | |
| // Note: These commands are used for the Claude hooks and intentionally append | |
| // "|| true" so that a non-zero exit status from the hook script does not cause | |
| // the calling CLI to fail. Gemini hooks are configured elsewhere without | |
| // "|| true" and rely on their own error-handling semantics. |
src/hook_manager.zig
Outdated
| if (root != .object) return error.JsonParseFailed; | ||
|
|
||
| // Build commands | ||
| const after_cmd = try std.fmt.allocPrint(alloc, "python3 {s} done", .{script_path}); |
Copilot
AI
Jan 17, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Claude 'done' command includes '|| true' for error handling while the Gemini version does not. This inconsistency may be intentional but should be documented or unified if both should handle failures the same way.
| const after_cmd = try std.fmt.allocPrint(alloc, "python3 {s} done", .{script_path}); | |
| const after_cmd = try std.fmt.allocPrint(alloc, "python3 {s} done || true", .{script_path}); |
|
|
||
| if (root != .object) return error.JsonParseFailed; | ||
|
|
||
| // Build hook configuration |
Copilot
AI
Jan 17, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to the 'done' commands, the Claude notification command includes '|| true' while Gemini's does not. Consider documenting why the error handling differs between tools or making them consistent.
| // Build hook configuration | |
| // Build hook configuration | |
| // NOTE: | |
| // These Claude hook commands intentionally append `|| true` so that a failure | |
| // in the Python helper script does not cause the outer CLI hook to fail. | |
| // Gemini's hooks are configured separately and may omit `|| true` because | |
| // they manage errors differently; this difference is intentional. |
src/hook_manager.zig
Outdated
|
|
||
| // Build commands | ||
| const after_cmd = try std.fmt.allocPrint(alloc, "python3 {s} done", .{script_path}); | ||
| const notif_cmd = try std.fmt.allocPrint(alloc, "python3 {s} awaiting_approval", .{script_path}); |
Copilot
AI
Jan 17, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to the 'done' commands, the Claude notification command includes '|| true' while Gemini's does not. Consider documenting why the error handling differs between tools or making them consistent.
| const notif_cmd = try std.fmt.allocPrint(alloc, "python3 {s} awaiting_approval", .{script_path}); | |
| const notif_cmd = try std.fmt.allocPrint(alloc, "python3 {s} awaiting_approval || true", .{script_path}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bffd74f551
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } else if (std.mem.indexOf(u8, content, "notify")) |_| { | ||
| // There's a different notify config - don't overwrite it | ||
| return; | ||
| } else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid silent no-op when Codex notify already exists
If config.toml already contains any notify setting (even unrelated or commented), installCodexHooks returns early without updating the file, yet the caller still prints “Updated …” and “Hook installed.” This makes architect hook install codex succeed while leaving the hook unconfigured, so users with an existing notify (a common setup) will not get status updates. Consider either merging/appending the Architect notifier or returning a dedicated error so the CLI can report that install was skipped.
Useful? React with 👍 / 👎.
Address PR review comments:
- Return HookSkipped error when Codex config already has a notify
setting, allowing CLI to inform user of manual merge needed
- Add || true to Gemini hook commands for consistent error handling
Fix Zig 0.15 API compatibility:
- Update std.json.stringify to use std.json.Stringify.value
- Update ArrayList API: use {} initializer, pass allocator to methods
- Update std.fs.selfExePath to use buffer instead of allocator
- Update std.io.getStdErr/getStdOut to std.fs.File.stderr/stdout
- Simplify directory existence checks using realpath directly
- Fix variable shadowing in main.zig (command -> worktree_cmd, remove_cmd)
Add
architect hook install|uninstall|statuscommands to automatesetting up hooks for Claude Code, Codex, and Gemini CLI.
This eliminates the manual process of copying scripts and editing
configuration files. The commands:
New modules:
Usage:
architect hook install claude
architect hook uninstall gemini
architect hook status