feat: add copilot hooks and prometheus configuration#1794
Conversation
Add rtk-rewrite and security hooks for copilot, and configure prometheus monitoring. Changes: - Add rtk-rewrite.sh and security.sh hooks to copilot - Add prometheus program configuration - Update sync scripts for codex-security and rtk-rewrite
|
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (2)
📒 Files selected for processing (8)
Disabled knowledge base sources:
📝 WalkthroughSummary by CodeRabbit
WalkthroughThis PR extends Claude Code integration to Copilot by implementing RTK-based command rewriting and security filtering hooks, wires them via Nix, adds Prometheus monitoring packages to Home Manager, and updates project dependencies. ChangesCopilot Hook System
Prometheus Module & Tooling
Possibly related PRs
Suggested labels
Poem
🎯 3 (Moderate) | ⏱️ ~25 minutes ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
|
||
| home.file.".copilot/hooks/rtk-rewrite.sh" = { | ||
| source = ../codex/hooks/rtk-rewrite.sh; | ||
| source = ./hooks/rtk-rewrite.sh; |
There was a problem hiding this comment.
Hook duplication invites drift. Before this PR, source = ../codex/hooks/rtk-rewrite.sh; made the codex and copilot hooks literally the same file, so they could never diverge. Pointing at ./hooks/rtk-rewrite.sh (and ./hooks/security.sh below) introduces a second copy that must be kept in sync via scripts/sync-{rtk-rewrite,codex-security}.sh. A few practical consequences:
- Manual edits to
config/codex/hooks/security.sh(e.g. ad-hoc deny-pattern tweaks) silently won't reach copilot until someone remembers to runscripts/sync-codex-security.sh. - Only
rtk-rewrite.shandsecurity.share mirrored. Other codex hooks (atuin-history.sh,notify.sh,pushover.sh) won't be reachable from copilot at all if/when they're added to its config. - The previous Nix-level sharing was zero-maintenance.
If the intent is to let copilot's hooks evolve independently from codex, that's fine — otherwise consider either reverting the source paths to ../codex/hooks/... or moving the shared hooks under config/shared/hooks/ and pointing both config/codex/default.nix and config/copilot/default.nix at that single location.
| chmod +x "$CODEX_SECURITY" | ||
|
|
||
| # Mirror to copilot hooks so codex + copilot stay identical. | ||
| cp "$CODEX_SECURITY" "$COPILOT_SECURITY" |
There was a problem hiding this comment.
Nit: the codex path is guarded at the top ([[ -f $CODEX_SECURITY ]] || ...), but this new mirror step has no equivalent protection — if config/copilot/hooks/ is missing for any reason, the codex hook has already been mutated by mv above and this cp then fails partway through, leaving the two hooks out of sync. A mkdir -p "$(dirname "$COPILOT_SECURITY")" here (or an existence check up top) would keep behavior consistent with the rest of the script.
There was a problem hiding this comment.
Code Review
This pull request introduces Copilot-specific hooks for command rewriting and security filtering, including synchronization scripts to maintain parity with Codex. It also adds Prometheus packages to the Home Manager configuration and updates various project dependencies. Feedback focused on improving the robustness of the new shell scripts by using printf instead of echo for arbitrary strings, ensuring the rewrite hook fails open on invalid JSON input, and optimizing jq usage for better performance.
| set -euo pipefail | ||
|
|
||
| INPUT=$(cat) | ||
| CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty') |
There was a problem hiding this comment.
The script is currently fail-closed on invalid JSON input. If INPUT is not valid JSON, jq will exit with an error, and because set -e is active, the script will terminate with exit code 1. Following the pattern for execution scripts in this repo, it is safer to handle parsing errors gracefully and fail-open (allowing the command) as seen in security.sh. Additionally, using printf is safer than echo for arbitrary strings.
| CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty') | |
| CMD=$(printf '%s' "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null) || CMD="" |
References
- Do not use set -e in execution scripts that must handle failures gracefully to avoid blocking the process.
| ORIGINAL_INPUT=$(echo "$INPUT" | jq -c '.tool_input') | ||
| UPDATED_INPUT=$(echo "$ORIGINAL_INPUT" | jq --arg cmd "$REWRITTEN" '.command = $cmd') |
There was a problem hiding this comment.
These two jq calls can be combined into a single invocation for better performance and to avoid unnecessary intermediate variables.
| ORIGINAL_INPUT=$(echo "$INPUT" | jq -c '.tool_input') | |
| UPDATED_INPUT=$(echo "$ORIGINAL_INPUT" | jq --arg cmd "$REWRITTEN" '.command = $cmd') | |
| UPDATED_INPUT=$(printf '%s' "$INPUT" | jq -c --arg cmd "$REWRITTEN" '.tool_input | .command = $cmd') |
| ) | ||
|
|
||
| # Split command at logical operators | ||
| IFS=$'\n' read -r -d '' -a segments < <(echo "$command" | sed -E 's/[;&|]+/\n/g' && printf '\0') || true |
There was a problem hiding this comment.
Using echo "$command" is unsafe if the command string starts with a hyphen (e.g., -n), as echo will interpret it as an option. Use printf to safely handle arbitrary command strings. Additionally, to robustly parse command output, use a unique delimiter and read with a matching IFS as per repository standards.
| IFS=$'\n' read -r -d '' -a segments < <(echo "$command" | sed -E 's/[;&|]+/\n/g' && printf '\0') || true | |
| IFS=$'\n' read -r -d '' -a segments < <(printf '%s\n' "$command" | sed -E 's/[;&|]+/\n/g' && printf '\0') || true |
References
- To robustly parse command output in shell scripts, use a unique delimiter (e.g., tab) and read with a matching IFS.
| IFS=$'\n' read -r -d '' -a segments < <(echo "$command" | sed -E 's/[;&|]+/\n/g' && printf '\0') || true | ||
|
|
||
| for segment in "${segments[@]}"; do | ||
| segment=$(echo "$segment" | xargs 2>/dev/null) || continue |
…1795) * fix: add Copilot toolArgs/modifiedArgs support to rtk-rewrite hook Tests added in #1788 check that rtk-rewrite.sh reads Copilot-format input (.toolArgs as object or stringified JSON) and emits .modifiedArgs output, but the hook itself was never updated, so the Shell workflow has been failing on every push to main. #1794 then added two new copilot hook files without updating the coverage list, adding a 5th failure. - Read CMD from .tool_input.command OR .toolArgs.command (object) OR .toolArgs | fromjson | .command (string). - Emit modifiedArgs alongside hookSpecificOutput when input used toolArgs, preserving original fields (e.g. timeout). - Mirror to claude/codex/copilot copies (sync_rtk_rewrite_spec.sh enforces byte equality between claude and codex). - Add config/copilot/hooks/{rtk-rewrite,security}.sh to coverage_spec.sh. Note: scripts/sync-rtk-rewrite.sh fetches from upstream and overwrites all three local copies — next sync will wipe this fix. Documented inline. * fix(hooks): tolerant fromjson, exclude copilot from shfmt, preserve sync Entire-Checkpoint: 9d826b214b88 * refactor(sync): drop patch file, make sync drift-check-only Entire-Checkpoint: 8c976510b69a
Summary
This PR adds new copilot hooks and configures prometheus monitoring.
Changes
rtk-rewrite.shandsecurity.shhooks to copilotTesting
Manual verification of hook scripts and prometheus configuration.
Summary by cubic
Adds Copilot hooks for RTK auto-rewrite and shell command safety, and adds Prometheus tooling via Home Manager. Keeps Claude, Codex, and Copilot hooks in sync.
New Features
config/copilot/hooks/rtk-rewrite.shusesrtk rewrite(supports allow/ask/deny; audit viaRTK_HOOK_AUDIT=1).config/copilot/hooks/security.shblocks risky commands (e.g., sudo, force-push, rm -rf) with exit code 2.prometheus,prometheus-alertmanager,prom2json.scripts/sync-rtk-rewrite.sh,scripts/sync-codex-security.sh.Dependencies
@anthropic-ai/claude-code,@github/copilot,@ccusage/*,turbo,vite,oxlint,openclaw, etc.) and refreshedbun.lockandflake.lock.Written for commit 753840c. Summary will update on new commits. Review in cubic