Skip to content
Open
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
2 changes: 1 addition & 1 deletion .github/hooks/rtk-rewrite.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"PreToolUse": [
{
"type": "command",
"command": "rtk hook",
"command": "rtk hook copilot",
"cwd": ".",
"timeout": 5
}
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ All notable changes to rtk (Rust Token Killer) will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Features

* `rtk init --agent copilot` — one-command setup for GitHub Copilot (VS Code + CLI): installs `.github/copilot-instructions.md` and `.github/hooks/rtk-rewrite.json` PreToolUse hook; idempotent; `--uninstall --agent copilot` removes both

### Bug Fixes

* **hook:** `rtk hook copilot` now correctly registered in `RTK_META_COMMANDS` — bare `rtk hook` no longer falls through to passthrough mode (exit 127); `.github/hooks/rtk-rewrite.json` corrected to invoke `rtk hook copilot`

## [0.33.0-rc.54](https://github.com/rtk-ai/rtk/compare/v0.32.0-rc.54...v0.33.0-rc.54) (2026-03-24)


Expand Down
14 changes: 7 additions & 7 deletions hooks/copilot-rtk-awareness.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
The `.github/copilot-instructions.md` file is loaded at session start by both Copilot CLI and VS Code Copilot Chat.
It instructs Copilot to prefix commands with `rtk` automatically.

The `.github/hooks/rtk-rewrite.json` hook adds a `PreToolUse` safety net via `rtk hook` —
The `.github/hooks/rtk-rewrite.json` hook adds a `PreToolUse` safety net via `rtk hook copilot` —
a cross-platform Rust binary that intercepts raw bash tool calls and rewrites them.
No shell scripts, no `jq` dependency, works on Windows natively.

Expand All @@ -33,21 +33,21 @@ which rtk # Verify correct binary path

## How the hook works

`rtk hook` reads `PreToolUse` JSON from stdin, detects the agent format, and responds appropriately:
`rtk hook copilot` reads `PreToolUse` JSON from stdin, detects the agent format, and responds appropriately:

**VS Code Copilot Chat** (supports `updatedInput` — transparent rewrite, no denial):
1. Agent runs `git status` → `rtk hook` intercepts via `PreToolUse`
2. `rtk hook` detects VS Code format (`tool_name`/`tool_input` keys)
1. Agent runs `git status` → `rtk hook copilot` intercepts via `PreToolUse`
2. `rtk hook copilot` detects VS Code format (`tool_name`/`tool_input` keys)
3. Returns `hookSpecificOutput.updatedInput.command = "rtk git status"`
4. Agent runs the rewritten command silently — no denial, no retry

**GitHub Copilot CLI** (deny-with-suggestion — CLI ignores `updatedInput` today, see [issue #2013](https://github.com/github/copilot-cli/issues/2013)):
1. Agent runs `git status` → `rtk hook` intercepts via `PreToolUse`
2. `rtk hook` detects Copilot CLI format (`toolName`/`toolArgs` keys)
1. Agent runs `git status` → `rtk hook copilot` intercepts via `PreToolUse`
2. `rtk hook copilot` detects Copilot CLI format (`toolName`/`toolArgs` keys)
3. Returns `permissionDecision: deny` with reason: `"Token savings: use 'rtk git status' instead"`
4. Copilot reads the reason and re-runs `rtk git status`

When Copilot CLI adds `updatedInput` support, only `rtk hook` needs updating — no config changes.
When Copilot CLI adds `updatedInput` support, only `rtk hook copilot` needs updating — no config changes.

## Integration comparison

Expand Down
10 changes: 5 additions & 5 deletions hooks/test-copilot-rtk-rewrite.sh
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ test_deny() {
TOTAL=$((TOTAL + 1))

local output
output=$(copilot_bash_input "$input_cmd" | "$RTK" hook 2>/dev/null) || true
output=$(copilot_bash_input "$input_cmd" | "$RTK" hook copilot 2>/dev/null) || true

local decision reason
decision=$(echo "$output" | jq -r '.permissionDecision // empty' 2>/dev/null)
Expand All @@ -79,7 +79,7 @@ test_vscode_rewrite() {
TOTAL=$((TOTAL + 1))

local output
output=$(vscode_bash_input "$input_cmd" | "$RTK" hook 2>/dev/null) || true
output=$(vscode_bash_input "$input_cmd" | "$RTK" hook copilot 2>/dev/null) || true

local decision updated_cmd
decision=$(echo "$output" | jq -r '.hookSpecificOutput.permissionDecision // empty' 2>/dev/null)
Expand All @@ -104,7 +104,7 @@ test_allow() {
TOTAL=$((TOTAL + 1))

local output
output=$(echo "$input" | "$RTK" hook 2>/dev/null) || true
output=$(echo "$input" | "$RTK" hook copilot 2>/dev/null) || true

if [ -z "$output" ]; then
printf " ${GREEN}PASS${RESET} %s ${DIM}→ (allow)${RESET}\n" "$description"
Expand Down Expand Up @@ -217,7 +217,7 @@ echo "--- Output format ---"

# Copilot CLI output format
TOTAL=$((TOTAL + 1))
raw_output=$(copilot_bash_input "git status" | "$RTK" hook 2>/dev/null)
raw_output=$(copilot_bash_input "git status" | "$RTK" hook copilot 2>/dev/null)

if echo "$raw_output" | jq . >/dev/null 2>&1; then
printf " ${GREEN}PASS${RESET} Copilot CLI: output is valid JSON\n"
Expand Down Expand Up @@ -249,7 +249,7 @@ fi

# VS Code output format
TOTAL=$((TOTAL + 1))
vscode_output=$(vscode_bash_input "git status" | "$RTK" hook 2>/dev/null)
vscode_output=$(vscode_bash_input "git status" | "$RTK" hook copilot 2>/dev/null)

if echo "$vscode_output" | jq . >/dev/null 2>&1; then
printf " ${GREEN}PASS${RESET} VS Code: output is valid JSON\n"
Expand Down
Loading
Loading