opencode-rtk-plugin 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +132 -0
  3. package/index.js +45 -0
  4. package/package.json +51 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nabheet S. Sandhu
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,132 @@
1
+ # opencode-rtk-plugin
2
+
3
+ > An [OpenCode](https://opencode.ai) **v2** plugin that routes every shell
4
+ > command through [`rtk`](https://github.com/rtk-ai/rtk), cutting LLM token
5
+ > usage by **60-90%** on common dev commands.
6
+
7
+ OpenCode sends tool output back to the model. `rtk` compresses that output
8
+ (git, grep, ls, test runners, build logs, and more) into a token-efficient
9
+ form before the model ever sees it. This plugin wires the two together.
10
+
11
+ ## Why
12
+
13
+ - **Smaller context, lower cost.** Command output is the biggest hidden token
14
+ sink in an agent loop.
15
+ - **No prompt changes.** Rewriting happens in the shell hook, transparently.
16
+ - **Single source of truth.** All rewrite rules live in `rtk rewrite`; this
17
+ plugin is a thin delegating adapter, so rules never drift.
18
+
19
+ ## Requirements
20
+
21
+ - OpenCode **v2** (`opencode --version` reports 2.x).
22
+ - `rtk` >= 0.23.0 on `PATH` — see [rtk-ai/rtk](https://github.com/rtk-ai/rtk):
23
+ `brew install rtk`
24
+
25
+ ## Install
26
+
27
+ ### From npm
28
+
29
+ ```bash
30
+ opencode plugin add opencode-rtk-plugin
31
+ ```
32
+
33
+ ### From GitHub
34
+
35
+ ```bash
36
+ opencode plugin add github:nabheet/opencode-rtk-plugin
37
+ ```
38
+
39
+ Or add it to `opencode.json(c)` directly:
40
+
41
+ ```jsonc
42
+ {
43
+ "$schema": "https://opencode.ai/config.json",
44
+ "plugins": ["opencode-rtk-plugin"]
45
+ }
46
+ ```
47
+
48
+ ### Manual
49
+
50
+ Copy this directory to `.opencode/plugins/opencode-rtk-plugin/` (project) or
51
+ `~/.config/opencode/plugins/opencode-rtk-plugin/` (global), then list it:
52
+
53
+ ```jsonc
54
+ {
55
+ "plugins": [{ "package": "./.opencode/plugins/opencode-rtk-plugin" }]
56
+ }
57
+ ```
58
+
59
+ ## Options
60
+
61
+ ```jsonc
62
+ {
63
+ "plugins": [
64
+ {
65
+ "package": "opencode-rtk-plugin",
66
+ "options": {
67
+ "binary": "rtk",
68
+ "timeoutMs": 5000,
69
+ "enabled": true
70
+ }
71
+ }
72
+ ]
73
+ }
74
+ ```
75
+
76
+ | Option | Default | Description |
77
+ | ----------- | ------- | ------------------------------------ |
78
+ | `binary` | `"rtk"` | Path or name of the rtk executable. |
79
+ | `timeoutMs` | `5000` | Per-rewrite timeout in milliseconds. |
80
+ | `enabled` | `true` | Set `false` to disable the plugin. |
81
+
82
+ ## How it works
83
+
84
+ The plugin registers one OpenCode v2 shell hook:
85
+
86
+ ```js
87
+ ctx.shell.hook("create.before", (event) => {
88
+ // event.command is the command about to run; mutate it to rewrite
89
+ })
90
+ ```
91
+
92
+ For each shell command it runs `rtk rewrite <command>` and replaces the command
93
+ with rtk's output when it differs. If `rtk` is missing, times out, or errors,
94
+ the original command runs unchanged.
95
+
96
+ ## Compatibility
97
+
98
+ - Targets **OpenCode v2** (`plugins` config + `id`/`setup` plugin definition).
99
+ OpenCode v1 used a different plugin API and is not supported.
100
+ - `rtk` ships hooks for Claude Code, Codex, Cursor, Gemini CLI, Copilot and
101
+ others. OpenCode is not among them, so this plugin fills that gap.
102
+
103
+ ## Prereleases
104
+
105
+ Every push to a PR publishes an installable beta to the npm `beta` dist-tag:
106
+
107
+ ```bash
108
+ opencode plugin add opencode-rtk-plugin@beta
109
+ ```
110
+
111
+ ## Releases (maintainers)
112
+
113
+ All publishing happens in GitHub Actions via npm **trusted publishing** (OIDC
114
+ provenance). Never publish from a local shell.
115
+
116
+ `.github/workflows/ci.yml` is the single workflow file (npm allows one trusted
117
+ publisher per package; the workflow filename must stay `ci.yml`):
118
+
119
+ - `test` — lint + plugin-export smoke check on `main` and PRs (Node 24).
120
+ - push to `main` → `publish` job publishes the next patch to `latest`, pushes a
121
+ `vX.Y.Z` tag, and opens a GitHub release. The version is derived from the
122
+ last published `latest`, so repeated merges never collide; an intentional
123
+ minor/major bump in `package.json` is honored.
124
+ - tag `v*-beta*` → `publish` job publishes `beta` + a prerelease GitHub release.
125
+ - every PR push → `prerelease` job publishes `<version>-beta.<run_number>` to
126
+ `beta` (same-repo, non-draft, non-dependabot PRs; re-runs deduped).
127
+ - manual dispatch → next `-beta.X` staging publish from `main`, no git change.
128
+
129
+ ## License
130
+
131
+ MIT — see [LICENSE](./LICENSE). `rtk` itself is Apache-2.0 and is **not**
132
+ bundled or vendored here.
package/index.js ADDED
@@ -0,0 +1,45 @@
1
+ // opencode-rtk — OpenCode v2 plugin
2
+ //
3
+ // Rewrites shell commands through `rtk rewrite` so command output reaches the
4
+ // model in a token-efficient form. All rewrite logic lives in rtk itself; this
5
+ // plugin is a thin delegating adapter for OpenCode's shell hook.
6
+ //
7
+ // Requires: rtk >= 0.23.0 on PATH (https://github.com/rtk-ai/rtk)
8
+
9
+ import { execFile } from "node:child_process";
10
+
11
+ /** Run `rtk rewrite <command>`; resolve to the rewritten command or null. */
12
+ function rewriteCommand(binary, command, timeoutMs) {
13
+ return new Promise((resolve) => {
14
+ const child = execFile(
15
+ binary,
16
+ ["rewrite", command],
17
+ { timeout: timeoutMs },
18
+ (err, stdout) => {
19
+ if (err) return resolve(null);
20
+ const rewritten = String(stdout).trim();
21
+ resolve(rewritten && rewritten !== command ? rewritten : null);
22
+ }
23
+ );
24
+ // execFile can emit before the callback; never let it surface.
25
+ child.on("error", () => resolve(null));
26
+ });
27
+ }
28
+
29
+ export default {
30
+ id: "rtk",
31
+
32
+ async setup(ctx) {
33
+ const options = ctx.options ?? {};
34
+ if (options.enabled === false) return;
35
+
36
+ const binary = typeof options.binary === "string" ? options.binary : "rtk";
37
+ const timeoutMs = Number.isFinite(options.timeoutMs) ? options.timeoutMs : 5000;
38
+
39
+ await ctx.shell.hook("create.before", async (event) => {
40
+ if (!event || typeof event.command !== "string" || !event.command) return;
41
+ const rewritten = await rewriteCommand(binary, event.command, timeoutMs);
42
+ if (rewritten) event.command = rewritten;
43
+ });
44
+ },
45
+ };
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "opencode-rtk-plugin",
3
+ "version": "0.1.0",
4
+ "description": "OpenCode v2 plugin that rewrites shell commands through rtk to cut LLM token usage by 60-90%.",
5
+ "type": "module",
6
+ "main": "index.js",
7
+ "exports": {
8
+ ".": "./index.js"
9
+ },
10
+ "files": [
11
+ "index.js",
12
+ "README.md",
13
+ "LICENSE"
14
+ ],
15
+ "keywords": [
16
+ "opencode",
17
+ "opencode-plugin",
18
+ "opencode-v2",
19
+ "rtk",
20
+ "token-optimization",
21
+ "token-savings",
22
+ "llm",
23
+ "ai-coding-agent",
24
+ "context-window",
25
+ "shell"
26
+ ],
27
+ "license": "MIT",
28
+ "author": "Nabheet S. Sandhu",
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "git+https://github.com/nabheet/opencode-rtk-plugin.git"
32
+ },
33
+ "bugs": {
34
+ "url": "https://github.com/nabheet/opencode-rtk-plugin/issues"
35
+ },
36
+ "homepage": "https://github.com/nabheet/opencode-rtk-plugin#readme",
37
+ "engines": {
38
+ "node": ">=18"
39
+ },
40
+ "publishConfig": {
41
+ "access": "public"
42
+ },
43
+ "scripts": {
44
+ "lint": "markdownlint-cli2 \"**/*.md\"",
45
+ "test": "node --check index.js && node -e \"import('./index.js').then(m => { if (!m.default?.id || typeof m.default.setup !== 'function') { console.error('invalid plugin export'); process.exit(1) } console.log('plugin id:', m.default.id) })\"",
46
+ "check": "npm run lint && npm test"
47
+ },
48
+ "devDependencies": {
49
+ "markdownlint-cli2": "^0.23.0"
50
+ }
51
+ }