@khalilgharbaoui/opencode-claude-code-plugin 0.22.0 → 0.23.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.
- package/README.md +2 -0
- package/dist/index.js +38 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/claude-code-plugin/SKILL.md +2 -0
package/README.md
CHANGED
|
@@ -334,6 +334,8 @@ Every variable the plugin itself reads, in one place. Config is read once at ope
|
|
|
334
334
|
| `OPENCODE_CONFIG` / `OPENCODE_CONFIG_DIR` | config discovery | Where the plugin looks for your opencode config when bridging MCP and skills. See [Discovery order](#discovery-order-highest-to-lowest-priority). |
|
|
335
335
|
| `OPENCODE_VERSION` | startup diagnostics | Reported as the opencode version when set, sparing the plugin a `--version` spawn. Diagnostics only. |
|
|
336
336
|
| `ANTHROPIC_API_KEY` / `ANTHROPIC_AUTH_TOKEN` | spawn environment | Not set by the plugin: these are yours, and Claude Code authenticates with them in preference to your subscription login when present. `ignoreAnthropicApiKey: true` strips them from the spawn. See [Billing](#billing). |
|
|
337
|
+
| `DISABLE_AUTOUPDATER` | spawn environment | Set to `1` on every `claude` the plugin spawns, **only if you have not set it yourself**. The plugin detects your CLI version once and caches it, and gates `--thinking-display summarized`, `--plugin-dir` and fast mode on the answer, so a CLI that updates itself mid-session would leave those gates describing a binary that is no longer running. Export `DISABLE_AUTOUPDATER=0` to keep the autoupdater; your value is never overwritten, and updating the CLI between opencode restarts works normally either way. |
|
|
338
|
+
| `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` | spawn environment | Set to `1` on every spawned `claude` under the same never-overwrite rule. It suppresses the CLI's non-essential network calls and is a second, independent way Claude Code declines to auto-update. Export it yourself (including as an empty string, which the CLI reads as off) to take control. |
|
|
337
339
|
|
|
338
340
|
The plugin also honours the usual path conventions rather than defining its own: `XDG_CONFIG_HOME` and `XDG_CACHE_HOME` (falling back to `~/.config` and `~/.cache`), `HOME` / `USERPROFILE`, and Claude Code's `CLAUDE_CONFIG_DIR` when the interactive transport needs to find the session transcript. Account providers set `CLAUDE_CONFIG_DIR` themselves for the process they spawn.
|
|
339
341
|
|
package/dist/index.js
CHANGED
|
@@ -381,6 +381,17 @@ import { execFile } from "child_process";
|
|
|
381
381
|
import { promisify } from "util";
|
|
382
382
|
var execFileAsync = promisify(execFile);
|
|
383
383
|
var cache = /* @__PURE__ */ new Map();
|
|
384
|
+
var CLI_HYGIENE_ENV_VARS = [
|
|
385
|
+
"DISABLE_AUTOUPDATER",
|
|
386
|
+
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC"
|
|
387
|
+
];
|
|
388
|
+
function cliHygieneEnv(inherited = process.env) {
|
|
389
|
+
const filled = {};
|
|
390
|
+
for (const name of CLI_HYGIENE_ENV_VARS) {
|
|
391
|
+
if (inherited[name] === void 0) filled[name] = "1";
|
|
392
|
+
}
|
|
393
|
+
return filled;
|
|
394
|
+
}
|
|
384
395
|
function detectCliVersion(cliPath) {
|
|
385
396
|
const cached = cache.get(cliPath);
|
|
386
397
|
if (cached) return cached;
|
|
@@ -2056,7 +2067,11 @@ function cliEffortLevel(effort) {
|
|
|
2056
2067
|
function claudeSpawnEnv(opts) {
|
|
2057
2068
|
const env = {
|
|
2058
2069
|
...process.env,
|
|
2059
|
-
TERM: "xterm-256color"
|
|
2070
|
+
TERM: "xterm-256color",
|
|
2071
|
+
// Pin the child to the binary whose version we detected, and keep it off
|
|
2072
|
+
// non-essential network calls. Fills gaps only, so an explicit shell value
|
|
2073
|
+
// survives: see `cliHygieneEnv` for why the version has to hold still.
|
|
2074
|
+
...cliHygieneEnv()
|
|
2060
2075
|
};
|
|
2061
2076
|
if (opts?.effort) {
|
|
2062
2077
|
env.CLAUDE_CODE_EFFORT_LEVEL = cliEffortLevel(opts.effort);
|
|
@@ -3396,9 +3411,10 @@ function finishBridge(input) {
|
|
|
3396
3411
|
};
|
|
3397
3412
|
}
|
|
3398
3413
|
const body = JSON.stringify({ mcpServers: servers }, null, 2);
|
|
3414
|
+
const bodyDigest = crypto2.createHash("sha256").update(body).digest("hex").slice(0, 12);
|
|
3399
3415
|
const outPath = path3.join(
|
|
3400
3416
|
pluginTmpDir(),
|
|
3401
|
-
`mcp-${
|
|
3417
|
+
`mcp-${bodyDigest}.json`
|
|
3402
3418
|
);
|
|
3403
3419
|
try {
|
|
3404
3420
|
if (!fileExists(outPath)) {
|
|
@@ -4936,6 +4952,19 @@ function resolveClaude(cmd = "claude") {
|
|
|
4936
4952
|
function encodeCwd(cwd) {
|
|
4937
4953
|
return path7.resolve(cwd).replace(/[^a-zA-Z0-9]/g, "-");
|
|
4938
4954
|
}
|
|
4955
|
+
function interactiveSpawnEnv(opts) {
|
|
4956
|
+
return {
|
|
4957
|
+
...process.env,
|
|
4958
|
+
CLAUDE_CONFIG_DIR: opts.configDir,
|
|
4959
|
+
TERM: "xterm-256color",
|
|
4960
|
+
// Pin the binary so a mid-session autoupdate cannot invalidate the
|
|
4961
|
+
// detected version the flag gates read, and skip non-essential traffic.
|
|
4962
|
+
// Fills gaps only, so a var the user exported survives untouched.
|
|
4963
|
+
...cliHygieneEnv(),
|
|
4964
|
+
...opts.ignoreAnthropicApiKey ? { ANTHROPIC_API_KEY: void 0, ANTHROPIC_AUTH_TOKEN: void 0 } : {},
|
|
4965
|
+
...opts.effort ? { CLAUDE_CODE_EFFORT_LEVEL: opts.effort } : {}
|
|
4966
|
+
};
|
|
4967
|
+
}
|
|
4939
4968
|
var TERMINAL_STOP = /* @__PURE__ */ new Set(["end_turn", "stop_sequence", "max_tokens"]);
|
|
4940
4969
|
var delay = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
4941
4970
|
function resolveConfigDir(configDir) {
|
|
@@ -5022,13 +5051,13 @@ var ClaudeSession = class {
|
|
|
5022
5051
|
this.lastDataAt = Date.now();
|
|
5023
5052
|
this.proc = Bun.spawn([claude, ...args], {
|
|
5024
5053
|
cwd: this.cwd,
|
|
5025
|
-
env: {
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
|
|
5031
|
-
},
|
|
5054
|
+
env: interactiveSpawnEnv({
|
|
5055
|
+
// The resolved field, not `this.o.configDir`: same value (the
|
|
5056
|
+
// constructor copies it in) but typed as always present.
|
|
5057
|
+
configDir: this.configDir,
|
|
5058
|
+
ignoreAnthropicApiKey: this.o.ignoreAnthropicApiKey,
|
|
5059
|
+
effort: this.o.effort
|
|
5060
|
+
}),
|
|
5032
5061
|
terminal: {
|
|
5033
5062
|
cols: this.o.cols,
|
|
5034
5063
|
rows: this.o.rows,
|