claude-yes 1.24.1 → 1.24.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-yes",
3
- "version": "1.24.1",
3
+ "version": "1.24.2",
4
4
  "description": "A wrapper tool that automates interactions with various AI CLI tools by automatically handling common prompts and responses.",
5
5
  "keywords": [
6
6
  "claude",
@@ -25,11 +25,11 @@
25
25
  "type": "module",
26
26
  "exports": {
27
27
  "import": "./dist/index.js",
28
- "types": "./index.ts"
28
+ "types": "./ts/index.ts"
29
29
  },
30
30
  "main": "dist/index.js",
31
- "module": "index.ts",
32
- "types": "./index.ts",
31
+ "module": "ts/index.ts",
32
+ "types": "./ts/index.ts",
33
33
  "bin": {
34
34
  "claude-yes": "dist/claude-yes.js",
35
35
  "codex-yes": "dist/codex-yes.js",
@@ -42,13 +42,13 @@
42
42
  "doc": "docs"
43
43
  },
44
44
  "files": [
45
- "*.ts",
45
+ "ts/*.ts",
46
46
  "dist"
47
47
  ],
48
48
  "scripts": {
49
- "build": "bun build index.ts cli.ts --outdir=dist --target=node --sourcemap --external=bun-pty --external=node-pty",
50
- "postbuild": "bun ./postbuild.ts",
51
- "dev": "tsx index.ts",
49
+ "build": "bun build ts/index.ts ts/cli.ts --outdir=dist --target=node --sourcemap --external=bun-pty --external=node-pty",
50
+ "postbuild": "bun ./ts/postbuild.ts",
51
+ "dev": "tsx ts/index.ts",
52
52
  "fmt": "bunx @biomejs/biome check --fix && bunx sort-package-json",
53
53
  "prepack": "bun run build",
54
54
  "prepare": "bunx husky",
@@ -6,27 +6,22 @@ import claudeYes from '.';
6
6
 
7
7
  // cli entry point
8
8
  const argv = yargs(hideBin(process.argv))
9
- .usage('Usage: $0 [options] [claude args] [--] [prompts...]')
9
+ .usage('Usage: $0 [options] [agent-cli args] [--] [prompts...]')
10
10
  .example(
11
11
  '$0 --exit-on-idle=30s --continue-on-crash "help me solve all todos in my codebase"',
12
12
  'Run Claude with a 30 seconds idle timeout and continue on crash',
13
13
  )
14
- .option('continue-on-crash', {
15
- type: 'boolean',
16
- default: true,
17
- description:
18
- 'spawn Claude with --continue if it crashes, only works for claude',
19
- alias: 'c',
20
- })
14
+ // .option('continue-on-crash', {
15
+ // type: 'boolean',
16
+ // default: true,
17
+ // description:
18
+ // 'spawn Claude with --continue if it crashes, only works for claude',
19
+ // alias: 'c',
20
+ // })
21
21
  .option('log-file', {
22
22
  type: 'string',
23
23
  description: 'Log file to write to',
24
24
  })
25
- .option('cli', {
26
- type: 'string',
27
- description:
28
- 'CLI command to run. Supports: claude, gemini, codex, copilot, cursor, grok. Defaults to the CLI inferred from the executable name or "claude".',
29
- })
30
25
  .option('prompt', {
31
26
  type: 'string',
32
27
  description: 'Prompt to send to Claude',
@@ -56,39 +51,37 @@ const argv = yargs(hideBin(process.argv))
56
51
  })
57
52
  .parseSync();
58
53
 
54
+ console.log(argv);
55
+
59
56
  // detect cli name for cli, while package.json have multiple bin link: {"claude-yes": "cli.js", "codex-yes": "cli.js", "gemini-yes": "cli.js"}
60
- if (!argv.cli) {
61
- const cliName = process.argv[1]?.split('/').pop()?.split('-')[0];
62
- argv.cli = cliName || 'claude';
63
- }
57
+ const cliName = process.argv[1]?.split('/').pop()?.split('-')[0];
58
+
59
+ const rawArgs = process.argv.slice(2);
60
+ const cliArgIndex = rawArgs.indexOf(String(argv._[0]));
61
+ const dashIndex = rawArgs.indexOf('--');
64
62
 
65
63
  // Support: everything after a literal `--` is a prompt string. Example:
66
64
  // claude-yes --exit-on-idle=30s -- "help me refactor this"
67
65
  // In that example the prompt will be `help me refactor this` and won't be
68
66
  // passed as args to the underlying CLI binary.
69
- const rawArgs = process.argv.slice(2);
70
- const dashIndex = rawArgs.indexOf('--');
71
- let promptFromDash: string | undefined = undefined;
72
- let cliArgsForSpawn: string[] = [];
73
- if (dashIndex !== -1) {
74
- // join everything after `--` into a single prompt string
75
- const after = rawArgs.slice(dashIndex + 1);
76
- promptFromDash = after.join(' ');
77
- // use everything before `--` as the cli args
78
- cliArgsForSpawn = rawArgs.slice(0, dashIndex).map(String);
79
- } else {
80
- // fallback to yargs parsed positional args when `--` is not used
81
- cliArgsForSpawn = argv._.map((e) => String(e));
82
- }
83
67
 
68
+ const cliArgsForSpawn = rawArgs.slice(
69
+ cliArgIndex === -1 ? 0 : cliArgIndex,
70
+ dashIndex === -1 ? undefined : dashIndex,
71
+ ); // default to all args
72
+ const promptFromDash: string | undefined = rawArgs
73
+ .slice(dashIndex + 1)
74
+ .join(' ');
75
+
76
+ console.log({ rawArgs, cliArgsForSpawn, promptFromDash });
84
77
  console.clear();
85
- const { exitCode, logs } = await claudeYes({
86
- cli: argv.cli,
78
+ const { exitCode } = await claudeYes({
79
+ cli: cliName,
87
80
  // prefer explicit --prompt / -p; otherwise use the text after `--` if present
88
81
  prompt: argv.prompt || promptFromDash,
89
82
  exitOnIdle: argv.exitOnIdle ? enhancedMs(argv.exitOnIdle) : undefined,
90
83
  cliArgs: cliArgsForSpawn,
91
- continueOnCrash: argv.continueOnCrash,
84
+ // continueOnCrash: argv.continueOnCrash,
92
85
  logFile: argv.logFile,
93
86
  verbose: argv.verbose,
94
87
  disableLock: argv.disableLock,
@@ -14,7 +14,6 @@ import {
14
14
  shouldUseLock,
15
15
  updateCurrentTaskStatus,
16
16
  } from './runningLock';
17
-
18
17
  // const yesLog = tsaComposer()(async function yesLog(msg: string) {
19
18
  // // await rm('agent-yes.log').catch(() => null); // ignore error if file doesn't exist
20
19
  // await appendFile("agent-yes.log", `${msg}\n`).catch(() => null);
@@ -115,7 +114,7 @@ export default async function claudeYes({
115
114
  cli = 'claude',
116
115
  cliArgs = [],
117
116
  prompt,
118
- continueOnCrash,
117
+ // continueOnCrash,
119
118
  cwd,
120
119
  env,
121
120
  exitOnIdle,
@@ -127,7 +126,7 @@ export default async function claudeYes({
127
126
  cli?: (string & {}) | keyof typeof CLI_CONFIGURES;
128
127
  cliArgs?: string[];
129
128
  prompt?: string;
130
- continueOnCrash?: boolean;
129
+ // continueOnCrash?: boolean;
131
130
  cwd?: string;
132
131
  env?: Record<string, string>;
133
132
  exitOnIdle?: number;
@@ -227,23 +226,23 @@ export default async function claudeYes({
227
226
  const agentCrashed = exitCode !== 0;
228
227
  const continueArg = (continueArgs as Record<string, string[]>)[cli];
229
228
 
230
- if (agentCrashed && continueOnCrash && continueArg) {
231
- if (!continueArg) {
232
- return console.warn(
233
- `continueOnCrash is only supported for ${Object.keys(continueArgs).join(', ')} currently, not ${cli}`,
234
- );
235
- }
236
- if (isFatal) {
237
- return pendingExitCode.resolve((pendingExitCodeValue = exitCode));
238
- }
239
-
240
- console.log(`${cli} crashed, restarting...`);
241
-
242
- shell = pty.spawn(cli, continueArg, getPtyOptions());
243
- shell.onData(onData);
244
- shell.onExit(onExit);
245
- return;
246
- }
229
+ // if (agentCrashed && continueOnCrash && continueArg) {
230
+ // if (!continueArg) {
231
+ // return console.warn(
232
+ // `continueOnCrash is only supported for ${Object.keys(continueArgs).join(", ")} currently, not ${cli}`
233
+ // );
234
+ // }
235
+ // if (isFatal) {
236
+ // return pendingExitCode.resolve((pendingExitCodeValue = exitCode));
237
+ // }
238
+
239
+ // console.log(`${cli} crashed, restarting...`);
240
+
241
+ // shell = pty.spawn(cli, continueArg, getPtyOptions());
242
+ // shell.onData(onData);
243
+ // shell.onExit(onExit);
244
+ // return;
245
+ // }
247
246
  return pendingExitCode.resolve((pendingExitCodeValue = exitCode));
248
247
  });
249
248
 
@@ -406,7 +405,7 @@ export default async function claudeYes({
406
405
  }
407
406
 
408
407
  async function exitAgent() {
409
- continueOnCrash = false;
408
+ // continueOnCrash = false;
410
409
  // send exit command to the shell, must sleep a bit to avoid claude treat it as pasted input
411
410
  await sendMessage('/exit');
412
411
 
@@ -1,8 +1,8 @@
1
1
  #! /usr/bin/env bun
2
2
  import { execaCommand } from 'execa';
3
3
  import { copyFile } from 'fs/promises';
4
+ import * as pkg from '../package.json';
4
5
  import { CLI_CONFIGURES } from '.';
5
- import * as pkg from './package.json';
6
6
 
7
7
  const src = 'dist/cli.js';
8
8
  await Promise.all(
@@ -11,5 +11,6 @@ await Promise.all(
11
11
  if (!pkg.bin?.[cli as keyof typeof pkg.bin])
12
12
  await execaCommand(`npm pkg set bin.${cli}-yes=${dst}`);
13
13
  await copyFile(src, dst);
14
+ console.log(`Created ${dst}`);
14
15
  }),
15
16
  );
@@ -221,13 +221,57 @@ async function waitForUnlock(
221
221
  currentTask: Task,
222
222
  ): Promise<void> {
223
223
  const blockingTask = blockingTasks[0];
224
+ if (!blockingTask) return;
224
225
  console.log(`⏳ Queueing for unlock of: ${blockingTask.task}`);
226
+ console.log(` Press 'b' to bypass queue, 'k' to kill previous instance`);
225
227
 
226
228
  // Add current task as 'queued'
227
229
  await addTask({ ...currentTask, status: 'queued' });
228
230
 
231
+ // Set up keyboard input handling
232
+ const stdin = process.stdin;
233
+ const wasRaw = stdin.isRaw;
234
+ stdin.setRawMode?.(true);
235
+ stdin.resume();
236
+
237
+ let bypassed = false;
238
+ let killed = false;
239
+
240
+ const keyHandler = (key: Buffer) => {
241
+ const char = key.toString();
242
+ if (char === 'b' || char === 'B') {
243
+ console.log('\n⚡ Bypassing queue...');
244
+ bypassed = true;
245
+ } else if (char === 'k' || char === 'K') {
246
+ console.log('\n🔪 Killing previous instance...');
247
+ killed = true;
248
+ }
249
+ };
250
+
251
+ stdin.on('data', keyHandler);
252
+
229
253
  let dots = 0;
230
254
  while (true) {
255
+ if (bypassed) {
256
+ // Force bypass - update status to running immediately
257
+ await updateTaskStatus(currentTask.pid, 'running');
258
+ console.log('✓ Queue bypassed, starting task...');
259
+ break;
260
+ }
261
+
262
+ if (killed && blockingTask) {
263
+ // Kill the blocking task's process
264
+ try {
265
+ process.kill(blockingTask.pid, 'SIGTERM');
266
+ console.log(`✓ Killed process ${blockingTask.pid}`);
267
+ // Wait a bit for the process to be killed
268
+ await sleep(1000);
269
+ } catch (err) {
270
+ console.log(`⚠️ Could not kill process ${blockingTask.pid}: ${err}`);
271
+ }
272
+ killed = false; // Reset flag after attempting kill
273
+ }
274
+
231
275
  await sleep(POLL_INTERVAL);
232
276
 
233
277
  const lockCheck = await checkLock(currentTask.cwd, currentTask.task);
@@ -245,6 +289,11 @@ async function waitForUnlock(
245
289
  `\r⏳ Queueing${'.'.repeat(dots)}${' '.repeat(3 - dots)}`,
246
290
  );
247
291
  }
292
+
293
+ // Clean up keyboard handler
294
+ stdin.off('data', keyHandler);
295
+ stdin.setRawMode?.(wasRaw);
296
+ if (!wasRaw) stdin.pause();
248
297
  }
249
298
 
250
299
  /**
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes