@khalilgharbaoui/opencode-claude-code-plugin 0.60.2 → 0.61.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/dist/index.d.ts CHANGED
@@ -473,6 +473,8 @@ interface ClaudeCodeConfig {
473
473
  bridgeSkipNativeSkills?: boolean;
474
474
  /** Append a one-line cost / duration / cache footer to each finished turn. */
475
475
  turnStats?: boolean;
476
+ /** Turn Claude Code's todo tools on for every model (`CLAUDE_CODE_ENABLE_TODO_TOOLS=1`). */
477
+ enableTodoTools?: boolean;
476
478
  /** Branch a forked opencode session off the parent's Claude conversation. */
477
479
  forkSessions?: boolean;
478
480
  /** Resume a conversation's Claude session after opencode restarts. Default true. */
@@ -992,6 +994,19 @@ interface ClaudeCodeProviderSettings {
992
994
  * `permission_denials` always reach `providerMetadata`.
993
995
  */
994
996
  turnStats?: boolean;
997
+ /**
998
+ * Start every `claude` with `CLAUDE_CODE_ENABLE_TODO_TOOLS=1`, so the CLI
999
+ * offers its todo tools (`TaskCreate` and family) whatever the model.
1000
+ * Claude Code offers them on its own only to Claude 3.x, Opus 4.0 to 4.7,
1001
+ * Sonnet 4.0 to 4.6 and Haiku 4.5; on Opus 4.8, the 5.x models and Fable
1002
+ * no todo list reaches opencode without this (h #g259).
1003
+ *
1004
+ * Off by default, because the CLI turned the tools off for those models on
1005
+ * purpose. Fills a gap only: a `CLAUDE_CODE_ENABLE_TODO_TOOLS` already in
1006
+ * opencode's environment, `0` included, is passed through and decides.
1007
+ * Never on a compaction spawn, which runs no tools.
1008
+ */
1009
+ enableTodoTools?: boolean;
995
1010
  /**
996
1011
  * When a new opencode session turns out to be a fork of one this provider
997
1012
  * already served, branch the parent's Claude conversation with
package/dist/index.js CHANGED
@@ -7872,6 +7872,7 @@ function claudeSpawnEnv(opts) {
7872
7872
  if (opts?.configDir) {
7873
7873
  env.CLAUDE_CONFIG_DIR = opts.configDir;
7874
7874
  }
7875
+ Object.assign(env, todoToolsEnv(opts?.enableTodoTools === true));
7875
7876
  if (opts?.ignoreAnthropicApiKey) {
7876
7877
  delete env.ANTHROPIC_API_KEY;
7877
7878
  delete env.ANTHROPIC_AUTH_TOKEN;
@@ -7881,6 +7882,10 @@ function claudeSpawnEnv(opts) {
7881
7882
  }
7882
7883
  return env;
7883
7884
  }
7885
+ function todoToolsEnv(enabled) {
7886
+ if (!enabled || process.env.CLAUDE_CODE_ENABLE_TODO_TOOLS !== void 0) return {};
7887
+ return { CLAUDE_CODE_ENABLE_TODO_TOOLS: "1" };
7888
+ }
7884
7889
  function touch(key) {
7885
7890
  const existing = activeProcesses.get(key);
7886
7891
  if (existing) {
@@ -8252,7 +8257,7 @@ function invalidateOtherEffortSessions(baseKey, effort) {
8252
8257
  clearBackgroundTasks(key);
8253
8258
  }
8254
8259
  }
8255
- function spawnClaudeProcess(cliPath, cliArgs, cwd, sessionKey2, proxyServer, mcpHash, systemPromptFile, ignoreAnthropicApiKey, effort, promptCacheTtl, configDir) {
8260
+ function spawnClaudeProcess(cliPath, cliArgs, cwd, sessionKey2, proxyServer, mcpHash, systemPromptFile, ignoreAnthropicApiKey, effort, promptCacheTtl, configDir, enableTodoTools) {
8256
8261
  evictIfNeeded();
8257
8262
  log.info("spawning new claude process", {
8258
8263
  cliPath,
@@ -8261,13 +8266,14 @@ function spawnClaudeProcess(cliPath, cliArgs, cwd, sessionKey2, proxyServer, mcp
8261
8266
  sessionKey: sessionKey2,
8262
8267
  effort,
8263
8268
  promptCacheTtl,
8264
- configDir
8269
+ configDir,
8270
+ ...enableTodoTools ? { enableTodoTools } : {}
8265
8271
  });
8266
8272
  const plan = planClaudeSpawn(cliPath, cliArgs);
8267
8273
  const proc = spawn(plan.file, plan.args, {
8268
8274
  cwd,
8269
8275
  stdio: ["pipe", "pipe", "pipe"],
8270
- env: claudeSpawnEnv({ ignoreAnthropicApiKey, effort, promptCacheTtl, configDir }),
8276
+ env: claudeSpawnEnv({ ignoreAnthropicApiKey, effort, promptCacheTtl, configDir, enableTodoTools }),
8271
8277
  windowsVerbatimArguments: plan.windowsVerbatimArguments
8272
8278
  });
8273
8279
  const lineEmitter = new EventEmitter3();
@@ -8279,6 +8285,7 @@ function spawnClaudeProcess(cliPath, cliArgs, cwd, sessionKey2, proxyServer, mcp
8279
8285
  systemPromptFile,
8280
8286
  effort,
8281
8287
  promptCacheTtl,
8288
+ enableTodoTools,
8282
8289
  startedAt: Date.now(),
8283
8290
  cliPath,
8284
8291
  cliArgs: [...cliArgs],
@@ -8410,7 +8417,8 @@ function respawnActiveProcess(sessionKey2, cliPath, cliArgs, cwd, ignoreAnthropi
8410
8417
  ignoreAnthropicApiKey,
8411
8418
  old.effort,
8412
8419
  old.promptCacheTtl,
8413
- old.configDir
8420
+ old.configDir,
8421
+ old.enableTodoTools
8414
8422
  );
8415
8423
  replacement.mcpServers = old.mcpServers;
8416
8424
  replacement.pendingProxyCompletions = old.pendingProxyCompletions;
@@ -11111,6 +11119,11 @@ function formatDoctorReport(report) {
11111
11119
  `| subagentDispatch | ${report.subagentDispatch}${report.subagentDispatch === "ask" && report.subagentDispatchCrossGroup ? " (cross-group accounts allowed)" : ""} |`
11112
11120
  );
11113
11121
  lines.push(`| turnStats | ${report.turnStats} |`);
11122
+ if (report.todoTools) {
11123
+ lines.push(
11124
+ `| enableTodoTools | ${report.todoTools.option}${report.todoTools.envSet ? " (CLAUDE_CODE_ENABLE_TODO_TOOLS is set in opencode's environment and decides)" : ""} |`
11125
+ );
11126
+ }
11114
11127
  lines.push(`| ANTHROPIC_API_KEY in env | ${report.anthropicApiKeyInEnv ? "yes" : "no"} |`);
11115
11128
  const overriding = report.permissionPresets.filter((row) => row.overrides.length > 0);
11116
11129
  if (overriding.length > 0) {
@@ -11542,6 +11555,10 @@ async function gatherDoctorReport(options) {
11542
11555
  subagentDispatch: base.subagentDispatch,
11543
11556
  subagentDispatchCrossGroup: base.subagentDispatchCrossGroup,
11544
11557
  turnStats: options.turnStats,
11558
+ todoTools: {
11559
+ option: options.enableTodoTools === true,
11560
+ envSet: process.env.CLAUDE_CODE_ENABLE_TODO_TOOLS !== void 0
11561
+ },
11545
11562
  anthropicApiKeyInEnv: base.anthropicApiKeyInEnv,
11546
11563
  processes,
11547
11564
  pendingCalls: snapshotPendingProxyCalls(),
@@ -18019,6 +18036,7 @@ var ClaudeCodeLanguageModel = class {
18019
18036
  cliPath,
18020
18037
  interactive: !!useInteractive,
18021
18038
  turnStats: this.config.turnStats === true,
18039
+ enableTodoTools: this.config.enableTodoTools === true,
18022
18040
  ignoreAnthropicApiKey: this.config.ignoreAnthropicApiKey === true,
18023
18041
  // Where the plugin applies the account itself rather than through a
18024
18042
  // wrapper (`accountInProcess`, Windows), the `/cost` spawn needs the
@@ -19219,7 +19237,8 @@ var ClaudeCodeLanguageModel = class {
19219
19237
  claudeSpawnEnv({
19220
19238
  ignoreAnthropicApiKey: self.config.ignoreAnthropicApiKey,
19221
19239
  effort: reasoningEffort,
19222
- promptCacheTtl
19240
+ promptCacheTtl,
19241
+ enableTodoTools: self.config.enableTodoTools === true
19223
19242
  })
19224
19243
  )
19225
19244
  });
@@ -19337,7 +19356,9 @@ var ClaudeCodeLanguageModel = class {
19337
19356
  self.config.ignoreAnthropicApiKey,
19338
19357
  reasoningEffort,
19339
19358
  promptCacheTtl,
19340
- spawnConfigDir
19359
+ spawnConfigDir,
19360
+ // A compaction spawn runs no tools, so it never asks for them.
19361
+ self.config.enableTodoTools === true && !compactionMode
19341
19362
  );
19342
19363
  ap.mcpServers = spawnMcpServers;
19343
19364
  state.proc = ap.proc;
@@ -21070,6 +21091,7 @@ function createClaudeCode(settings = {}) {
21070
21091
  bridgeOpencodeSkills: settings.bridgeOpencodeSkills === true,
21071
21092
  bridgeSkipNativeSkills: settings.bridgeSkipNativeSkills !== false,
21072
21093
  turnStats: settings.turnStats === true,
21094
+ enableTodoTools: settings.enableTodoTools === true,
21073
21095
  forkSessions: settings.forkSessions === true,
21074
21096
  resumeAfterRestart: settings.resumeAfterRestart !== false,
21075
21097
  resumeAcrossModelChanges: settings.resumeAcrossModelChanges !== false,