···11+// RTK Pi extension — rewrites bash commands to use rtk for token savings.
22+// Requires: rtk >= 0.23.0 in PATH.
33+//
44+// This is a thin delegating extension: all rewrite logic lives in `rtk rewrite`,
55+// which is the single source of truth (src/discover/registry.rs).
66+// To add or change rewrite rules, edit the Rust registry — not this file.
77+//
88+// Exit code contract for `rtk rewrite`:
99+// 0 + stdout Rewrite found → mutate command
1010+// 1 No RTK equivalent → pass through unchanged
1111+// 3 + stdout Rewrite (advisory) → mutate command
1212+1313+import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"
1414+import { isToolCallEventType } from "@earendil-works/pi-coding-agent"
1515+1616+const REWRITE_TIMEOUT_MS = 2_000
1717+const MIN_SUPPORTED_RTK_MINOR = 23
1818+1919+// Parse "X.Y.Z" semver, return [major, minor, patch] or null.
2020+function parseSemver(raw: string): [number, number, number] | null {
2121+ const m = raw.trim().match(/(\d+)\.(\d+)\.(\d+)/)
2222+ if (!m) return null
2323+ return [parseInt(m[1], 10), parseInt(m[2], 10), parseInt(m[3], 10)]
2424+}
2525+2626+// Calls `rtk rewrite`; returns the rewritten command or null (pass through).
2727+async function rewriteCommand(
2828+ pi: ExtensionAPI,
2929+ cmd: string,
3030+ signal?: AbortSignal
3131+): Promise<string | null> {
3232+ const result = await pi.exec("rtk", ["rewrite", cmd], {
3333+ timeout: REWRITE_TIMEOUT_MS,
3434+ signal,
3535+ })
3636+ if (result.killed) return null
3737+ if (result.code !== 0 && result.code !== 3) return null
3838+ return result.stdout.trim() || null
3939+}
4040+4141+export default async function (pi: ExtensionAPI) {
4242+ // Probe rtk version at load time; disables extension if missing or too old.
4343+ const ver = await pi.exec("rtk", ["--version"], { timeout: REWRITE_TIMEOUT_MS })
4444+ if (ver.code !== 0) {
4545+ console.warn("[rtk] rtk binary not found in PATH — extension disabled")
4646+ return
4747+ }
4848+4949+ // Warn and bail if rtk predates 0.23.0 (when `rtk rewrite` was introduced).
5050+ const parsed = parseSemver(ver.stdout.replace(/^rtk\s+/, ""))
5151+ if (parsed) {
5252+ const [major, minor] = parsed
5353+ if (major === 0 && minor < MIN_SUPPORTED_RTK_MINOR) {
5454+ console.warn(`[rtk] rtk ${ver.stdout.trim()} is too old (need >= 0.23.0) — extension disabled`)
5555+ return
5656+ }
5757+ }
5858+5959+ pi.on("tool_call", async (event, ctx) => {
6060+ try {
6161+ if (!isToolCallEventType("bash", event)) return
6262+6363+ const cmd = event.input.command
6464+ if (typeof cmd !== "string" || cmd.trim() === "") return
6565+6666+ if (cmd.startsWith("rtk ")) return
6767+ if (process.env.RTK_DISABLED === "1") return
6868+6969+ // Delegate to RTK.
7070+ const rewritten = await rewriteCommand(pi, cmd, ctx.signal)
7171+ if (rewritten && rewritten !== cmd) {
7272+ event.input.command = rewritten
7373+ }
7474+ } catch (err) {
7575+ // Fail open: never block execution on an unexpected error.
7676+ console.warn("[rtk] unexpected error in tool_call handler; passing through command", err)
7777+ return
7878+ }
7979+ })
8080+}
+2
AGENTS.md
···11# Monorepo of rssbase.io
22> RSSBase is a RSS feed reader, using [atproto](https://atproto.com/) to store user data.
3344+@RTK.md
55+46## Convention
57- name: RSSBase
68- url: rssbase.io
+7-2
README.md
···3636fi
37373838# Get the codebase
3939-git clone git@tangled.org:mykiwi.dev/rssbase && cd rssbase
3939+git clone git@tangled.org:mykiwi.dev/rssbase.io && cd rssbase.io
4040devenv allow
41414242# Your developer environment is ready 👨🚀🚀
···5050```bash
5151CACHIX_AUTH_TOKEN=... devenv shell cachix-push
5252```
5353-<details>
5353+</details>
5454+5555+## Roadmap (project in very early stages)
5656+- [ ] deployed
5757+- [ ] add feeds
5858+- [ ] list feeds
54595560[devenv]: https://devenv.sh
5661[nix]: https://search.nixos.org/packages
+32
RTK.md
···11+# RTK - Rust Token Killer (Codex CLI)
22+33+**Usage**: Token-optimized CLI proxy for shell commands.
44+55+## Rule
66+77+Always prefix shell commands with `rtk`.
88+99+Examples:
1010+1111+```bash
1212+rtk git status
1313+rtk cargo test
1414+rtk npm run build
1515+rtk pytest -q
1616+```
1717+1818+## Meta Commands
1919+2020+```bash
2121+rtk gain # Token savings analytics
2222+rtk gain --history # Recent command savings history
2323+rtk proxy <cmd> # Run raw command without filtering
2424+```
2525+2626+## Verification
2727+2828+```bash
2929+rtk --version
3030+rtk gain
3131+which rtk
3232+```