claude-task-worker 0.83.0 → 0.85.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 CHANGED
@@ -66,7 +66,7 @@ CLI が GitHub ラベルを検知してタスクを起動し、プラグイン
66
66
  | [Git](https://git-scm.com/) | worktree の作成・ブランチ操作 |
67
67
  | [jq](https://jqlang.org/) | プラグインスキル内での JSON 加工 |
68
68
  | [CodeGraph](https://www.npmjs.com/package/@colbymchenry/codegraph) | コード探索用インデックス。任意(未導入でも探索がテキスト検索に落ちるだけ) |
69
- | [Pencil CLI](https://docs.pencil.dev/for-developers/pencil-cli) | `.pen` デザインファイルの編集・参照。UIデザイン先行ワークフロー使用時のみ |
69
+ | [Pencil CLI](https://docs.pencil.dev/for-developers/pencil-cli) | `.pen` デザインファイルの編集・参照。UIデザイン先行ワークフロー使用時のみ(呼び出しは `claude-task-worker pencil` 経由) |
70
70
  | [herdr](https://herdr.dev) | `--project` / `mode: "herdr"` 使用時のみ |
71
71
 
72
72
  CLI 本体に npm の実行時依存はない(esbuild で `dist/index.js` に単一バンドルされ、Node.js 標準モジュールのみで動作する)。
@@ -149,8 +149,22 @@ claude-task-worker <command> [--epic <issue-number>]... [--label <label>]... [--
149
149
  | `init` | ラベル・テンプレート・設定ファイルの作成と CodeGraph セットアップ |
150
150
  | `install` / `update` | 上記「セットアップ」を参照 |
151
151
  | `usage` | Claude API 使用状況(5時間/7日間の利用率とリセット時刻)を表示し、Slack にも通知 |
152
+ | `pencil <args...>` | Pencil CLI をアセット URI 修正パッチ付きで実行するラッパー(下記参照) |
152
153
  | `version` | CLI のバージョンを表示(`--version` / `-v` も可) |
153
154
 
155
+ ### `pencil <args...>`
156
+
157
+ `@pen.dev/cli`(`pencil`)にはアセットのベース URI を絶対 URI として解決できないバグがあり、`.pen` を開くと `Base URI must be absolute!` で失敗する。本コマンドはその修正を Node の loader hook(`dist/pen-baseuri-fix.mjs`)として `NODE_OPTIONS` 経由で注入したうえで `pencil` を実行するラッパー。
158
+
159
+ ```bash
160
+ claude-task-worker pencil version
161
+ claude-task-worker pencil interactive -i designs/login.pen -o designs/login.pen <<'EOF'
162
+ ...
163
+ EOF
164
+ ```
165
+
166
+ 引数・stdin・stdout・stderr・終了コードはすべて素通しするため、使い方は `pencil` と同じ。`.pen` を扱うスキル・エージェント(`edit-pencil-design` / `inspect-pencil-node` / `resolve-pencil-conflict` / `pencil-design-updater` など)はすべてこのラッパー経由で `pencil` を呼ぶ。
167
+
154
168
  ### `--epic <issue-number>`
155
169
 
156
170
  指定したエピック Issue のサブ Issue のみを処理対象に絞る。`all` / `yolo` と Issue 系ワーカーで有効。複数指定するといずれかのエピックを親に持つサブ Issue が対象になる(OR)。
package/dist/index.js CHANGED
@@ -266,6 +266,7 @@ __export(herdr_exports, {
266
266
  HerdrError: () => HerdrError,
267
267
  HerdrUnavailableError: () => HerdrUnavailableError,
268
268
  agentGet: () => agentGet,
269
+ agentPrompt: () => agentPrompt,
269
270
  agentStart: () => agentStart,
270
271
  checkHerdrAvailable: () => checkHerdrAvailable,
271
272
  getCurrentWorkspaceId: () => getCurrentWorkspaceId,
@@ -452,6 +453,9 @@ async function agentStart(paneId, {
452
453
  }
453
454
  return toAgentInfo(agent);
454
455
  }
456
+ async function agentPrompt(paneId, text) {
457
+ await execHerdr(["agent", "prompt", paneId, text], { allowEmptyResult: true });
458
+ }
455
459
  async function agentGet(target) {
456
460
  const result = await execHerdr(["agent", "get", target]);
457
461
  const agent = result?.agent;
@@ -635,6 +639,7 @@ async function startHerdrTask({
635
639
  label,
636
640
  cwd,
637
641
  args,
642
+ prompt,
638
643
  env,
639
644
  workspaceId,
640
645
  herdr,
@@ -651,6 +656,7 @@ async function startHerdrTask({
651
656
  console.warn(`[herdr-runner] pane ${paneId} produced no prompt before the timeout, launching anyway`);
652
657
  }
653
658
  await mod.agentStart(paneId, { name: toAgentName(label), args, readyTimeoutMs: timing?.agentStartReadyTimeoutMs });
659
+ await mod.agentPrompt(paneId, prompt);
654
660
  } catch (err) {
655
661
  await mod.tabClose(tabId).catch(() => {
656
662
  });
@@ -1875,8 +1881,12 @@ function buildClaudeArgs({
1875
1881
  const advisor = advisorModel?.trim() ?? "";
1876
1882
  const permission = permissionMode ?? DEFAULT_PERMISSION_MODE;
1877
1883
  return [
1878
- ...mode === "herdr" ? [] : ["-p"],
1879
- prompt,
1884
+ // default モードはプロンプトを引数で渡す(print モード)。herdr モードでは渡さない:
1885
+ // 引数で渡すと claude が起動と同時に作業を始めてしまい、`herdr agent start` が
1886
+ // 「入力待ちになるまで」ブロックする仕様と噛み合わない(タスクが終わるまで返らず、
1887
+ // 2分を超えると timeout で落ちる)。プロンプトは起動後に `herdr agent prompt` で
1888
+ // 投入し、herdr にターンを追跡させる(herdr-runner.ts の startHerdrTask 参照)。
1889
+ ...mode === "herdr" ? [] : ["-p", prompt],
1880
1890
  "--permission-mode",
1881
1891
  permission,
1882
1892
  "--chrome",
@@ -1894,7 +1904,11 @@ function buildClaudeArgs({
1894
1904
  ];
1895
1905
  }
1896
1906
  function buildClaudeExecution(invocation) {
1897
- return { command: CLAUDE_COMMAND, args: buildClaudeArgs(invocation) };
1907
+ return {
1908
+ command: CLAUDE_COMMAND,
1909
+ args: buildClaudeArgs(invocation),
1910
+ ...invocation.mode === "herdr" ? { prompt: invocation.prompt } : {}
1911
+ };
1898
1912
  }
1899
1913
  function buildClaudeEnv(mode) {
1900
1914
  return mode === "herdr" ? { CLAUDE_CODE_DISABLE_BACKGROUND_TASKS: CLAUDE_SPAWN_ENV.CLAUDE_CODE_DISABLE_BACKGROUND_TASKS } : { ...CLAUDE_SPAWN_ENV };
@@ -2446,7 +2460,7 @@ function resolveProjectName(cwd = process.cwd()) {
2446
2460
  if (injected && injected.length > 0) return injected;
2447
2461
  return findProjectNameByPath(cwd) ?? basename(cwd);
2448
2462
  }
2449
- async function runViaHerdr(args, id, onComplete, cwd, env) {
2463
+ async function runViaHerdr(args, prompt, id, onComplete, cwd, env) {
2450
2464
  const { startHerdrTask: startHerdrTask2, stopHerdrTask: stopHerdrTask2, taskTabLabel: taskTabLabel2, waitForHerdrTask: waitForHerdrTask2 } = await Promise.resolve().then(() => (init_herdr_runner(), herdr_runner_exports));
2451
2465
  const { getCurrentWorkspaceId: getCurrentWorkspaceId2 } = await Promise.resolve().then(() => (init_herdr(), herdr_exports));
2452
2466
  const label = taskTabLabel2(resolveProjectName(), id);
@@ -2458,6 +2472,7 @@ async function runViaHerdr(args, id, onComplete, cwd, env) {
2458
2472
  label,
2459
2473
  cwd: cwd ?? process.cwd(),
2460
2474
  args,
2475
+ prompt,
2461
2476
  env,
2462
2477
  workspaceId: getCurrentWorkspaceId2()
2463
2478
  });
@@ -2481,7 +2496,7 @@ async function runViaHerdr(args, id, onComplete, cwd, env) {
2481
2496
  await finishTask(id, result, onComplete);
2482
2497
  herdrTasks.delete(id);
2483
2498
  }
2484
- function run(command, args, id, title, workerName, path2, onComplete, cwd, env) {
2499
+ function run(command, args, id, title, workerName, path2, onComplete, cwd, env, prompt) {
2485
2500
  tasks.delete(id);
2486
2501
  tasks.set(id, {
2487
2502
  id,
@@ -2494,7 +2509,7 @@ function run(command, args, id, title, workerName, path2, onComplete, cwd, env)
2494
2509
  ensureRenderInterval();
2495
2510
  renderTable();
2496
2511
  if (getRunMode() === "herdr") {
2497
- void runViaHerdr(args, id, onComplete, cwd, env);
2512
+ void runViaHerdr(args, prompt ?? "", id, onComplete, cwd, env);
2498
2513
  return;
2499
2514
  }
2500
2515
  const child = spawn(command, args, {
@@ -3287,7 +3302,7 @@ function createIssuePollingWorker(config) {
3287
3302
  }
3288
3303
  try {
3289
3304
  if (status === "completed") {
3290
- const verified = await config.onCompleted?.(issue.number, worktreeId) ?? true;
3305
+ const verified = await config.onCompleted?.(issue.number, worktreeId, output) ?? true;
3291
3306
  if (verified === false) {
3292
3307
  await notifyTaskFailed(config.name, name, issue.number, issue.title, issueUrl, output);
3293
3308
  } else {
@@ -3311,7 +3326,8 @@ function createIssuePollingWorker(config) {
3311
3326
  }
3312
3327
  },
3313
3328
  cwd,
3314
- buildClaudeEnv(mode)
3329
+ buildClaudeEnv(mode),
3330
+ execution.prompt
3315
3331
  );
3316
3332
  } catch (err) {
3317
3333
  console.error(`[${config.name}] setup error for #${issue.number}: ${err}`);
@@ -3333,11 +3349,22 @@ function createIssuePollingWorker(config) {
3333
3349
  }
3334
3350
 
3335
3351
  // src/workers/exec-issue.ts
3336
- function prMissingComment(worktreeId) {
3352
+ var REPORT_TAIL_LIMIT = 3e3;
3353
+ function formatSessionReport(output) {
3354
+ const trimmed = output.trim();
3355
+ if (trimmed === "") return "\uFF08\u30BB\u30C3\u30B7\u30E7\u30F3\u306E\u51FA\u529B\u306F\u3042\u308A\u307E\u305B\u3093\u3067\u3057\u305F\uFF09";
3356
+ const tail = trimmed.length > REPORT_TAIL_LIMIT ? `\u2026\uFF08\u5148\u982D\u3092\u7701\u7565\uFF09
3357
+ ${trimmed.slice(-REPORT_TAIL_LIMIT)}` : trimmed;
3358
+ return ["```", tail, "```"].join("\n");
3359
+ }
3360
+ function prMissingComment(worktreeId, output) {
3337
3361
  return [
3338
3362
  "## PR\u672A\u4F5C\u6210\u306E\u307E\u307E\u81EA\u52D5\u5B9F\u884C\u304C\u7D42\u4E86\u3057\u307E\u3057\u305F\uFF08\u8981\u4EBA\u624B\u78BA\u8A8D\uFF09",
3339
3363
  `exec-issue \u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306F\u6B63\u5E38\u7D42\u4E86\uFF08exit 0\uFF09\u3057\u307E\u3057\u305F\u304C\u3001\u3053\u306E\u5B9F\u884C\u306E\u4F5C\u696D\u30D6\u30E9\u30F3\u30C1\uFF08\`${worktreeId}\`\uFF09\u3092 head \u3068\u3059\u308BPR\u3082\u3001\u672CIssue\u3092 closing \u53C2\u7167\u3059\u308BPR\u3082\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002PR\u4F5C\u6210\u524D\u306B\u30BB\u30C3\u30B7\u30E7\u30F3\u304C\u7D42\u4E86\u3057\u305F\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002`,
3340
3364
  "",
3365
+ "## PR\u3092\u4F5C\u6210\u3057\u306A\u304B\u3063\u305F\u7406\u7531\uFF08\u30BB\u30C3\u30B7\u30E7\u30F3\u306E\u6700\u7D42\u5831\u544A\uFF09",
3366
+ formatSessionReport(output),
3367
+ "",
3341
3368
  "## \u72B6\u614B\u306E\u78BA\u8A8D",
3342
3369
  `- \u5909\u66F4\u304C push \u6E08\u307F\u306E\u5834\u5408\u306F\u30EA\u30E2\u30FC\u30C8\u30D6\u30E9\u30F3\u30C1 \`${worktreeId}\` \u304C\u6B8B\u3063\u3066\u3044\u307E\u3059\u3002\u5185\u5BB9\u3092\u78BA\u8A8D\u3057\u3001\u5FC5\u8981\u306A\u3089\u624B\u52D5\u3067PR\u3092\u4F5C\u6210\u3057\u3066\u304F\u3060\u3055\u3044`,
3343
3370
  "",
@@ -3352,7 +3379,7 @@ var execIssueWorker = (opts = {}) => createIssuePollingWorker({
3352
3379
  triggerLabels: ["cc-exec-issue"],
3353
3380
  epicFilters: opts.epicFilters,
3354
3381
  labelFilters: opts.labelFilters,
3355
- onCompleted: async (issueNumber, worktreeId) => {
3382
+ onCompleted: async (issueNumber, worktreeId, output) => {
3356
3383
  if (await hasLabel("issue", issueNumber, "cc-need-human-check")) {
3357
3384
  console.log(`[exec-issue] #${issueNumber}: cc-need-human-check present, skip cc-pr-created`);
3358
3385
  return false;
@@ -3370,7 +3397,7 @@ var execIssueWorker = (opts = {}) => createIssuePollingWorker({
3370
3397
  `[exec-issue] #${issueNumber}: session exited without a PR (branch: ${worktreeId}); marking cc-need-human-check`
3371
3398
  );
3372
3399
  await addLabel("issue", issueNumber, "cc-need-human-check");
3373
- await commentOnIssue(issueNumber, prMissingComment(worktreeId)).catch(
3400
+ await commentOnIssue(issueNumber, prMissingComment(worktreeId, output)).catch(
3374
3401
  (err) => console.error(`[exec-issue] commentOnIssue failed for #${issueNumber}: ${err}`)
3375
3402
  );
3376
3403
  return false;
@@ -3477,7 +3504,8 @@ function createPrPollingWorker(config) {
3477
3504
  }
3478
3505
  },
3479
3506
  cwd,
3480
- buildClaudeEnv(mode)
3507
+ buildClaudeEnv(mode),
3508
+ execution.prompt
3481
3509
  );
3482
3510
  } catch (err) {
3483
3511
  console.error(`[${config.name}] setup error for PR #${pr.number}: ${err}`);
@@ -4035,7 +4063,8 @@ function createScheduledWorker(config) {
4035
4063
  }
4036
4064
  },
4037
4065
  cwd,
4038
- buildClaudeEnv(mode)
4066
+ buildClaudeEnv(mode),
4067
+ execution.prompt
4039
4068
  );
4040
4069
  } catch (err) {
4041
4070
  console.error(`[${config.name}] setup error: ${err}`);
@@ -4078,7 +4107,7 @@ var updateDesignMdWorker = createScheduledWorker({
4078
4107
  init_table();
4079
4108
 
4080
4109
  // src/commands/init.ts
4081
- import { mkdir as mkdir2, writeFile as writeFile2, access } from "node:fs/promises";
4110
+ import { mkdir as mkdir2, writeFile as writeFile2, readFile as readFile2, access } from "node:fs/promises";
4082
4111
 
4083
4112
  // src/commands/codegraph.ts
4084
4113
  import { mkdir, readFile, writeFile } from "node:fs/promises";
@@ -4166,6 +4195,101 @@ async function ensureCodegraphGitIgnore(logPrefix) {
4166
4195
  }
4167
4196
  }
4168
4197
 
4198
+ // src/commands/design-md.ts
4199
+ async function loadRunCommand2() {
4200
+ return await Promise.resolve().then(() => (init_run_command(), run_command_exports));
4201
+ }
4202
+ var DESIGN_MD_PACKAGE = "@google/design.md";
4203
+ async function installDesignMdCli(logPrefix) {
4204
+ console.log(`[${logPrefix}] Installing DESIGN.md CLI (npm install -g ${DESIGN_MD_PACKAGE}@latest)...`);
4205
+ try {
4206
+ const { runCommand: runCommand2 } = await loadRunCommand2();
4207
+ await runCommand2("npm", ["install", "-g", `${DESIGN_MD_PACKAGE}@latest`]);
4208
+ console.log(`[${logPrefix}] DESIGN.md CLI installed.`);
4209
+ return true;
4210
+ } catch (err) {
4211
+ console.error(`[${logPrefix}] Failed to install DESIGN.md CLI: ${err.message}`);
4212
+ return false;
4213
+ }
4214
+ }
4215
+
4216
+ // src/commands/pen.ts
4217
+ async function loadRunCommand3() {
4218
+ return await Promise.resolve().then(() => (init_run_command(), run_command_exports));
4219
+ }
4220
+ var PEN_PACKAGE = "@pen.dev/cli";
4221
+ var LEGACY_PEN_PACKAGE = "@pencil.dev/cli";
4222
+ async function installPenCli(logPrefix) {
4223
+ console.log(`[${logPrefix}] Removing legacy Pen CLI (npm uninstall -g ${LEGACY_PEN_PACKAGE})...`);
4224
+ const { runCommand: runCommand2 } = await loadRunCommand3();
4225
+ try {
4226
+ await runCommand2("npm", ["uninstall", "-g", LEGACY_PEN_PACKAGE]);
4227
+ } catch (err) {
4228
+ console.error(`[${logPrefix}] Skipped removing legacy Pen CLI: ${err.message}`);
4229
+ }
4230
+ console.log(`[${logPrefix}] Installing Pen CLI (npm install -g ${PEN_PACKAGE}@latest)...`);
4231
+ try {
4232
+ await runCommand2("npm", ["install", "-g", `${PEN_PACKAGE}@latest`]);
4233
+ console.log(`[${logPrefix}] Pen CLI installed.`);
4234
+ return true;
4235
+ } catch (err) {
4236
+ console.error(`[${logPrefix}] Failed to install Pen CLI: ${err.message}`);
4237
+ return false;
4238
+ }
4239
+ }
4240
+
4241
+ // src/commands/install.ts
4242
+ init_run_command();
4243
+ var PLUGIN_NAME = "claude-task-worker";
4244
+ var MARKETPLACE_NAME = "claude-task-worker";
4245
+ var MARKETPLACE_SOURCE = "getty104/claude-task-worker";
4246
+ async function addMarketplace() {
4247
+ console.log(`[install] Adding marketplace: ${MARKETPLACE_SOURCE}...`);
4248
+ try {
4249
+ await runCommand("claude", ["plugin", "marketplace", "add", MARKETPLACE_SOURCE]);
4250
+ console.log("[install] Marketplace added.");
4251
+ } catch (err) {
4252
+ console.error(
4253
+ `[install] Failed to add marketplace (already added is expected and safe to ignore): ${err.message}`
4254
+ );
4255
+ }
4256
+ }
4257
+ async function installPlugin() {
4258
+ console.log(`[install] Installing plugin: ${PLUGIN_NAME}@${MARKETPLACE_NAME}...`);
4259
+ try {
4260
+ await runCommand("claude", ["plugin", "install", `${PLUGIN_NAME}@${MARKETPLACE_NAME}`]);
4261
+ console.log("[install] Plugin installed. Restart your Claude Code session to apply.");
4262
+ return true;
4263
+ } catch (err) {
4264
+ console.error(`[install] Failed to install plugin: ${err.message}`);
4265
+ return false;
4266
+ }
4267
+ }
4268
+ async function installCli() {
4269
+ console.log("[install] Installing claude-task-worker CLI (npm install -g claude-task-worker@latest)...");
4270
+ try {
4271
+ await runCommand("npm", ["install", "-g", "claude-task-worker@latest"]);
4272
+ console.log("[install] claude-task-worker CLI installed.");
4273
+ return true;
4274
+ } catch (err) {
4275
+ console.error(`[install] Failed to install claude-task-worker CLI: ${err.message}`);
4276
+ return false;
4277
+ }
4278
+ }
4279
+ async function install() {
4280
+ console.log("[install] Starting install...");
4281
+ await addMarketplace();
4282
+ const pluginOk = await installPlugin();
4283
+ const cliOk = await installCli();
4284
+ const codegraphOk = await installCodegraphCli("install");
4285
+ const designMdOk = await installDesignMdCli("install");
4286
+ const penOk = await installPenCli("install");
4287
+ if (!pluginOk || !cliOk || !codegraphOk || !designMdOk || !penOk) {
4288
+ process.exitCode = 1;
4289
+ }
4290
+ console.log("[install] Done.");
4291
+ }
4292
+
4169
4293
  // src/commands/init.ts
4170
4294
  var LABELS = [
4171
4295
  { name: "cc-need-human-check", color: "eb1700" },
@@ -4265,6 +4389,45 @@ async function createConfig(force) {
4265
4389
  const result = await writeFileWithMode(CONFIG_PATH, JSON.stringify(initialConfig, null, 2), force);
4266
4390
  logWriteResult(result, CONFIG_PATH);
4267
4391
  }
4392
+ var PROJECT_SETTINGS_PATH = ".claude/settings.json";
4393
+ function mergePluginSettings(current) {
4394
+ const marketplaces = { ...current.extraKnownMarketplaces ?? {} };
4395
+ marketplaces[MARKETPLACE_NAME] = { source: { source: "github", repo: MARKETPLACE_SOURCE } };
4396
+ const plugins = { ...current.enabledPlugins ?? {} };
4397
+ plugins[`${PLUGIN_NAME}@${MARKETPLACE_NAME}`] = true;
4398
+ return { ...current, extraKnownMarketplaces: marketplaces, enabledPlugins: plugins };
4399
+ }
4400
+ async function registerPluginInSettings() {
4401
+ let current = {};
4402
+ try {
4403
+ const raw = await readFile2(PROJECT_SETTINGS_PATH, "utf-8");
4404
+ const parsed = JSON.parse(raw);
4405
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
4406
+ console.log(`[init] Skipped: ${PROJECT_SETTINGS_PATH} is not a JSON object`);
4407
+ return;
4408
+ }
4409
+ current = parsed;
4410
+ } catch (err) {
4411
+ if (err.code !== "ENOENT") {
4412
+ console.log(`[init] Skipped: failed to read ${PROJECT_SETTINGS_PATH}: ${err.message}`);
4413
+ return;
4414
+ }
4415
+ }
4416
+ const merged = mergePluginSettings(current);
4417
+ if (JSON.stringify(merged) === JSON.stringify(current)) {
4418
+ console.log(`[init] Already registered: ${PLUGIN_NAME}@${MARKETPLACE_NAME} in ${PROJECT_SETTINGS_PATH}`);
4419
+ return;
4420
+ }
4421
+ try {
4422
+ await mkdir2(".claude", { recursive: true });
4423
+ await writeFile2(PROJECT_SETTINGS_PATH, `${JSON.stringify(merged, null, 2)}
4424
+ `, "utf-8");
4425
+ } catch (err) {
4426
+ console.log(`[init] Skipped: failed to write ${PROJECT_SETTINGS_PATH}: ${err.message}`);
4427
+ return;
4428
+ }
4429
+ console.log(`[init] Registered ${PLUGIN_NAME}@${MARKETPLACE_NAME} in ${PROJECT_SETTINGS_PATH}`);
4430
+ }
4268
4431
  async function init(options = {}) {
4269
4432
  const force = options.force ?? false;
4270
4433
  console.log(`[init] Creating labels...${force ? " (force mode)" : ""}`);
@@ -4284,6 +4447,8 @@ async function init(options = {}) {
4284
4447
  await mkdir2(".github/workflows", { recursive: true });
4285
4448
  const workflowPath = ".github/workflows/assign-creator-on-cc-triage-scope.yml";
4286
4449
  logWriteResult(await writeFileWithMode(workflowPath, ASSIGN_CREATOR_WORKFLOW, force), workflowPath);
4450
+ console.log("[init] Registering the plugin in project settings...");
4451
+ await registerPluginInSettings();
4287
4452
  console.log("[init] Creating config file...");
4288
4453
  await createConfig(force);
4289
4454
  console.log("[init] Setting up CodeGraph...");
@@ -4292,75 +4457,6 @@ async function init(options = {}) {
4292
4457
  console.log("[init] Done.");
4293
4458
  }
4294
4459
 
4295
- // src/commands/design-md.ts
4296
- async function loadRunCommand2() {
4297
- return await Promise.resolve().then(() => (init_run_command(), run_command_exports));
4298
- }
4299
- var DESIGN_MD_PACKAGE = "@google/design.md";
4300
- async function installDesignMdCli(logPrefix) {
4301
- console.log(`[${logPrefix}] Installing DESIGN.md CLI (npm install -g ${DESIGN_MD_PACKAGE}@latest)...`);
4302
- try {
4303
- const { runCommand: runCommand2 } = await loadRunCommand2();
4304
- await runCommand2("npm", ["install", "-g", `${DESIGN_MD_PACKAGE}@latest`]);
4305
- console.log(`[${logPrefix}] DESIGN.md CLI installed.`);
4306
- return true;
4307
- } catch (err) {
4308
- console.error(`[${logPrefix}] Failed to install DESIGN.md CLI: ${err.message}`);
4309
- return false;
4310
- }
4311
- }
4312
-
4313
- // src/commands/install.ts
4314
- init_run_command();
4315
- var PLUGIN_NAME = "claude-task-worker";
4316
- var MARKETPLACE_NAME = "claude-task-worker";
4317
- var MARKETPLACE_SOURCE = "getty104/claude-task-worker";
4318
- async function addMarketplace() {
4319
- console.log(`[install] Adding marketplace: ${MARKETPLACE_SOURCE}...`);
4320
- try {
4321
- await runCommand("claude", ["plugin", "marketplace", "add", MARKETPLACE_SOURCE]);
4322
- console.log("[install] Marketplace added.");
4323
- } catch (err) {
4324
- console.error(
4325
- `[install] Failed to add marketplace (already added is expected and safe to ignore): ${err.message}`
4326
- );
4327
- }
4328
- }
4329
- async function installPlugin() {
4330
- console.log(`[install] Installing plugin: ${PLUGIN_NAME}@${MARKETPLACE_NAME}...`);
4331
- try {
4332
- await runCommand("claude", ["plugin", "install", `${PLUGIN_NAME}@${MARKETPLACE_NAME}`]);
4333
- console.log("[install] Plugin installed. Restart your Claude Code session to apply.");
4334
- return true;
4335
- } catch (err) {
4336
- console.error(`[install] Failed to install plugin: ${err.message}`);
4337
- return false;
4338
- }
4339
- }
4340
- async function installCli() {
4341
- console.log("[install] Installing claude-task-worker CLI (npm install -g claude-task-worker@latest)...");
4342
- try {
4343
- await runCommand("npm", ["install", "-g", "claude-task-worker@latest"]);
4344
- console.log("[install] claude-task-worker CLI installed.");
4345
- return true;
4346
- } catch (err) {
4347
- console.error(`[install] Failed to install claude-task-worker CLI: ${err.message}`);
4348
- return false;
4349
- }
4350
- }
4351
- async function install() {
4352
- console.log("[install] Starting install...");
4353
- await addMarketplace();
4354
- const pluginOk = await installPlugin();
4355
- const cliOk = await installCli();
4356
- const codegraphOk = await installCodegraphCli("install");
4357
- const designMdOk = await installDesignMdCli("install");
4358
- if (!pluginOk || !cliOk || !codegraphOk || !designMdOk) {
4359
- process.exitCode = 1;
4360
- }
4361
- console.log("[install] Done.");
4362
- }
4363
-
4364
4460
  // src/commands/update.ts
4365
4461
  init_run_command();
4366
4462
  var PLUGIN_NAME2 = "claude-task-worker";
@@ -4405,7 +4501,8 @@ async function update() {
4405
4501
  const cliOk = await updateCli();
4406
4502
  const codegraphOk = await upgradeCodegraphCli("update");
4407
4503
  const designMdOk = await installDesignMdCli("update");
4408
- if (!marketplaceOk || !pluginOk || !cliOk || !codegraphOk || !designMdOk) {
4504
+ const penOk = await installPenCli("update");
4505
+ if (!marketplaceOk || !pluginOk || !cliOk || !codegraphOk || !designMdOk || !penOk) {
4409
4506
  process.exitCode = 1;
4410
4507
  }
4411
4508
  console.log("[update] Done.");
@@ -4427,8 +4524,34 @@ function version() {
4427
4524
  }
4428
4525
  }
4429
4526
 
4527
+ // src/commands/pencil.ts
4528
+ import { spawn as spawn3 } from "node:child_process";
4529
+ import { dirname as dirname4, join as join9 } from "node:path";
4530
+ import { fileURLToPath as fileURLToPath2, pathToFileURL } from "node:url";
4531
+ var HOOK_FILE = "pen-baseuri-fix.mjs";
4532
+ function buildPencilNodeOptions(existing, hookUrl) {
4533
+ return [`--import ${hookUrl}`, existing?.trim()].filter(Boolean).join(" ");
4534
+ }
4535
+ function pencil(args) {
4536
+ const hookPath = join9(dirname4(fileURLToPath2(import.meta.url)), HOOK_FILE);
4537
+ const child = spawn3("pencil", args, {
4538
+ stdio: "inherit",
4539
+ env: {
4540
+ ...process.env,
4541
+ NODE_OPTIONS: buildPencilNodeOptions(process.env.NODE_OPTIONS, pathToFileURL(hookPath).href)
4542
+ }
4543
+ });
4544
+ child.on("error", (err) => {
4545
+ console.error(`[pencil] Failed to run pencil: ${err.message}`);
4546
+ process.exit(127);
4547
+ });
4548
+ child.on("exit", (code, signal) => {
4549
+ process.exit(signal ? 1 : code ?? 1);
4550
+ });
4551
+ }
4552
+
4430
4553
  // src/dispatch-args.ts
4431
- var PROJECT_INCOMPATIBLE_COMMANDS = ["init", "install", "update", "usage", "version"];
4554
+ var PROJECT_INCOMPATIBLE_COMMANDS = ["init", "install", "update", "usage", "version", "pencil"];
4432
4555
  function collectFlagValues(argv, flag) {
4433
4556
  const values = [];
4434
4557
  for (let i = 0; i < argv.length; i++) {
@@ -4496,6 +4619,7 @@ Commands:
4496
4619
  install Add the claude-task-worker marketplace, install the plugin, and install/update the CLI
4497
4620
  update Update the claude-task-worker plugin/marketplace and the CLI itself
4498
4621
  usage Notify current usage to Slack
4622
+ pencil <args...> Run the Pencil CLI with the asset base-URI fix loaded (passes every argument and stdin through)
4499
4623
  version Print the installed claude-task-worker CLI version (aliases: --version, -v)
4500
4624
 
4501
4625
  Workers:
@@ -4543,7 +4667,7 @@ if (!workerType) {
4543
4667
  printUsage();
4544
4668
  process.exit(1);
4545
4669
  }
4546
- if (workerType !== "all" && workerType !== "yolo" && workerType !== "init" && workerType !== "install" && workerType !== "update" && workerType !== "usage" && !WORKERS[workerType]) {
4670
+ if (workerType !== "all" && workerType !== "yolo" && workerType !== "init" && workerType !== "install" && workerType !== "update" && workerType !== "usage" && workerType !== "pencil" && !WORKERS[workerType]) {
4547
4671
  console.error(`Unknown command: ${workerType}`);
4548
4672
  printUsage();
4549
4673
  process.exit(1);
@@ -4674,6 +4798,8 @@ if (hasProjectFilter()) {
4674
4798
  (async () => {
4675
4799
  await update();
4676
4800
  })();
4801
+ } else if (workerType === "pencil") {
4802
+ pencil(process.argv.slice(3));
4677
4803
  } else if (workerType === "usage") {
4678
4804
  (async () => {
4679
4805
  const text = await buildTokenLimitText();
@@ -0,0 +1,31 @@
1
+ // src/pen-baseuri-fix.ts
2
+ import { registerHooks } from "node:module";
3
+ import { resolve } from "node:path";
4
+ var BASE_URI_GETTER = /\[(_0x[0-9a-f]+)\((0x[0-9a-f]+)\)\]\(\)\{return this\[\1\((0x[0-9a-f]+)\)\]\|\|this\[\1\((0x[0-9a-f]+)\)\];\}/;
5
+ var PEN_CLI_MODULE = /@pen\.dev\/cli\/dist\/[^/]*\.mjs$/;
6
+ var ABSOLUTE_URI = /^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//;
7
+ function toAbsoluteUri(path) {
8
+ if (!path || ABSOLUTE_URI.test(path)) return path;
9
+ return `file://${resolve(path)}`;
10
+ }
11
+ globalThis.__penAbsURI = toAbsoluteUri;
12
+ registerHooks({
13
+ load(url, ctx, next) {
14
+ const loaded = next(url, ctx);
15
+ if (!PEN_CLI_MODULE.test(url) || !loaded.source) return loaded;
16
+ const source = String(loaded.source);
17
+ const match = BASE_URI_GETTER.exec(source);
18
+ if (!match) return loaded;
19
+ const [all, decode, methodKey, primaryKey, fallbackKey] = match;
20
+ return {
21
+ ...loaded,
22
+ source: source.replace(
23
+ all,
24
+ `[${decode}(${methodKey})](){return globalThis.__penAbsURI(this[${decode}(${primaryKey})]||this[${decode}(${fallbackKey})]);}`
25
+ )
26
+ };
27
+ }
28
+ });
29
+ export {
30
+ toAbsoluteUri
31
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-task-worker",
3
- "version": "0.83.0",
3
+ "version": "0.85.0",
4
4
  "description": "CLI tool that polls GitHub Issues/PRs and delegates work to Claude CLI",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -8,7 +8,7 @@
8
8
  "claude-task-worker": "dist/index.js"
9
9
  },
10
10
  "scripts": {
11
- "build": "tsc --noEmit && esbuild src/index.ts --bundle --platform=node --format=esm --outfile=dist/index.js",
11
+ "build": "tsc --noEmit && esbuild src/index.ts --bundle --platform=node --format=esm --outfile=dist/index.js && esbuild src/pen-baseuri-fix.ts --bundle --platform=node --format=esm --outfile=dist/pen-baseuri-fix.mjs",
12
12
  "dev": "tsc --noEmit --watch",
13
13
  "lint": "eslint .",
14
14
  "lint:fix": "eslint . --fix",