Merge pull request #17: promote 1.2 to main

Brings the rtk output-filtering hooks to the default branch, so sessions
cloned from main get them, and opens the 1.2 series on main.

Verified by ci.yml runs 76, 77 and 80; run 80 published v1.2.80-dev from
this tree.
This commit is contained in:
adrianoftyriel
2026-08-07 23:01:00 -06:00
committed by GitHub
5 changed files with 124 additions and 2 deletions
+39
View File
@@ -0,0 +1,39 @@
#!/usr/bin/env bash
# Make sure rtk is on PATH, so the PreToolUse hook in .claude/settings.json has
# something to call. Without this the sandbox starts every session with an empty
# container and the rewrite hook quietly no-ops.
#
# Deliberately never fails: a missing rtk costs tokens, not correctness, and a
# session that refuses to start because a compression tool did not download
# would be a much worse trade.
set -uo pipefail
RTK_VERSION="v0.45.0"
INSTALLER="https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh"
export PATH="$HOME/.local/bin:$PATH"
if command -v rtk >/dev/null 2>&1; then
exit 0
fi
# Only install unattended in the ephemeral web sandbox. On a personal machine,
# say what to run instead — dropping a binary into someone's ~/.local/bin
# without asking is not ours to do.
if [ "${CLAUDE_CODE_REMOTE:-}" != "true" ]; then
echo "rtk is not installed, so bash output will not be compressed."
echo "To install it: curl -fsSL $INSTALLER | sh"
exit 0
fi
# The version has to be pinned. The installer's default is to look up the latest
# tag through api.github.com, which the sandbox proxy answers with a 403 for
# every repository except this one, so the lookup fails and takes the install
# with it. Bump this by hand.
if ! curl -fsSL "$INSTALLER" 2>/dev/null | RTK_VERSION="$RTK_VERSION" sh >/dev/null 2>&1; then
echo "rtk $RTK_VERSION did not install; continuing without output compression."
exit 0
fi
echo "rtk $(rtk --version 2>/dev/null | awk '{print $2}') ready; bash output is compressed."
+25
View File
@@ -0,0 +1,25 @@
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/session-start.sh"
}
]
}
],
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "command -v rtk >/dev/null 2>&1 && exec rtk hook claude || exit 0"
}
]
}
]
}
}
+13
View File
@@ -0,0 +1,13 @@
# Project-local RTK filters — commit this file with your repo.
# Filters here override user-global and built-in filters.
# Docs: https://github.com/rtk-ai/rtk#custom-filters
schema_version = 1
# Example: suppress build noise from a custom tool
# [filters.my-tool]
# description = "Compact my-tool output"
# match_command = "^my-tool\\s+build"
# strip_ansi = true
# strip_lines_matching = ["^\\s*$", "^Downloading", "^Installing"]
# max_lines = 30
# on_empty = "my-tool: ok"
+45
View File
@@ -67,3 +67,48 @@ The suppression is a property of the sandbox's credential, so it cannot be
fixed from inside a session. Giving the environment a personal access token to
push with would make pushes and PRs behave normally for everyone. Until then,
the dispatch step above is the workaround.
## Bash output is filtered before it reaches the model
`.claude/settings.json` registers a `PreToolUse` hook on `Bash` that rewrites
each command through [rtk](https://github.com/rtk-ai/rtk): `git status` runs as
`rtk git status`, and rtk compresses the output. Write commands normally — the
rewrite is transparent and costs nothing to invoke.
Measured on this repo rather than quoted from rtk's README:
| Command | Raw | Filtered | Saved |
| --- | --- | --- | --- |
| `git diff HEAD~3` | 521 KB | 28 KB | 95% |
| `grep -rn "fun " app/src/main` | 117 KB | 19 KB | 84% |
| `find . -name "*.kt"` | 7.7 KB | 1.7 KB | 79% |
| `git log -20` | 20 KB | 5.3 KB | 74% |
| `git diff --stat` | 4.0 KB | 4.0 KB | 1% |
| `ls` of a single package | 50 B | 62 B | −24% |
The saving is all in the large outputs, which is the point — a full diff of a
few commits is otherwise most of a context window. Already-compact output grows
slightly, because rtk adds a header; at those sizes it does not matter. `rtk
gain` reports what the current session has actually saved.
Two limits are worth knowing. The `Read`, `Grep` and `Glob` tools are not
`Bash`, so they never reach the hook and are unaffected; a deliberate `rg` or
`find` in a shell *is* filtered. And filtering never truncates a file: `cat`
becomes `rtk read`, which was checked byte-for-byte against this repo's longest
Kotlin source (`GameSetupScreen.kt`, 946 lines) and came back identical. Commit
messages survive the rewrite intact, quotes and colons included. To bypass
filtering for one command, run `rtk proxy <cmd>`.
## rtk is reinstalled at the start of every session
The container starts empty, so `.claude/hooks/session-start.sh` installs rtk
before the session does anything. It pins `RTK_VERSION`, because the installer
otherwise asks `api.github.com` for the latest tag and the proxy answers 403 for
every repository except this one — the lookup fails and takes the install with
it. Bump that variable by hand.
The hook is written not to matter when it fails. Outside the sandbox it installs
nothing and just prints the command to run, since dropping a binary into
someone's `~/.local/bin` uninvited is not its business; if the download fails it
says so and exits clean. With rtk absent the rewrite hook no-ops, and the only
consequence is verbose output.
+2 -2
View File
@@ -16,10 +16,10 @@ android.nonTransitiveRClass=true
# <series>.<run number>, a production tag is v<series>.<n> and a dev tag adds
# -dev. It lives here rather than in the build file because the workflows have
# to name the tag as well, and they read it straight out of this file — three
# copies of "1.1" would be three chances for a release to be tagged one thing
# copies of "1.2" would be three chances for a release to be tagged one thing
# and built as another.
#
# Only the series is set by hand. The number after it is the CI run number, so
# it keeps climbing on its own and an APK's versionCode never goes backwards
# when this changes.
plgVersionSeries=1.1
plgVersionSeries=1.2