Files
rtk-ai__rtk/openclaw/index.ts
Alex 56160d8399 feat: OpenClaw plugin for transparent exec rewriting (#358)
* feat: add OpenClaw plugin for transparent exec rewriting

Adds an OpenClaw plugin that intercepts exec tool calls via the
before_tool_call hook and rewrites commands to their RTK equivalents.

This is the OpenClaw equivalent of hooks/rtk-rewrite.sh for Claude Code.

The plugin:
- Registers a before_tool_call hook on the exec tool
- Rewrites git, grep, find, ls, gh, docker, kubectl, and test commands
- Guards against rewriting piped/compound commands and heredocs
- Returns properly typed PluginHookBeforeToolCallResult
- Supports enabled/verbose config options

Measured savings: 48-87% token reduction on common commands.

Files:
- openclaw/index.ts — plugin source
- openclaw/openclaw.plugin.json — plugin manifest
- openclaw/README.md — installation and usage docs

* refactor: delegate OpenClaw plugin to rtk rewrite

Replace 60+ hardcoded regex rules with a single call to `rtk rewrite`,
matching the OpenCode plugin pattern (hooks/opencode-rtk.ts).

Benefits:
- Zero maintenance: new RTK filters work automatically
- Single source of truth: rewrite logic in Rust (src/discover/registry.rs)
- 122 → 73 lines, no rule duplication

Also: rebase on develop, fix homepage URL, bump version to 1.0.0.
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>

* feat: add package.json for npm publishing

Enables `openclaw plugins install @rtk-ai/rtk-rewrite` for OpenClaw users.

Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>

---------

Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
Co-authored-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
2026-03-18 15:00:30 +01:00

75 lines
1.8 KiB
TypeScript

/**
* RTK Rewrite Plugin for OpenClaw
*
* Transparently rewrites exec tool commands to RTK equivalents
* before execution, achieving 60-90% LLM token savings.
*
* All rewrite logic lives in `rtk rewrite` (src/discover/registry.rs).
* This plugin is a thin delegate — to add or change rules, edit the
* Rust registry, not this file.
*/
import { execSync } from "node:child_process";
let rtkAvailable: boolean | null = null;
function checkRtk(): boolean {
if (rtkAvailable !== null) return rtkAvailable;
try {
execSync("which rtk", { stdio: "ignore" });
rtkAvailable = true;
} catch {
rtkAvailable = false;
}
return rtkAvailable;
}
function tryRewrite(command: string): string | null {
try {
const result = execSync(`rtk rewrite ${JSON.stringify(command)}`, {
encoding: "utf-8",
timeout: 2000,
}).trim();
return result && result !== command ? result : null;
} catch {
return null;
}
}
export default function register(api: any) {
const pluginConfig = api.config ?? {};
const enabled = pluginConfig.enabled !== false;
const verbose = pluginConfig.verbose === true;
if (!enabled) return;
if (!checkRtk()) {
console.warn("[rtk] rtk binary not found in PATH — plugin disabled");
return;
}
api.on(
"before_tool_call",
(event: { toolName: string; params: Record<string, unknown> }) => {
if (event.toolName !== "exec") return;
const command = event.params?.command;
if (typeof command !== "string") return;
const rewritten = tryRewrite(command);
if (!rewritten) return;
if (verbose) {
console.log(`[rtk] ${command} -> ${rewritten}`);
}
return { params: { ...event.params, command: rewritten } };
},
{ priority: 10 }
);
if (verbose) {
console.log("[rtk] OpenClaw plugin registered");
}
}