claude-yes 1.16.1 → 1.17.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
@@ -8,7 +8,8 @@ A wrapper tool that automates interactions with the Claude CLI by automatically
8
8
 
9
9
  - Same as `claude` command
10
10
  - Automatically responds to common prompts like "Yes, proceed" and "Yes"
11
- - So, this will Let claude run until your task done, and wait for your next prompt.
11
+ - So, this will Let claude keep run until your task done, and wait for your next prompt.
12
+ - You can still Queue More Prompts or Cancel executing task by `ESC` or `Ctrl+C`
12
13
 
13
14
  ## Prerequirements
14
15
 
@@ -40,6 +41,9 @@ bunx claude-yes "Solve TODO.md"
40
41
 
41
42
  # Auto-exit when Claude becomes idle (useful for automation scripts)
42
43
  claude-yes --exit-on-idle=60s "run all tests and commit current changes"
44
+
45
+ # Alternative: use with claude-code-execute
46
+ claude-code-execute claude-yes "your task here"
43
47
  ```
44
48
 
45
49
  The tool will:
@@ -0,0 +1,18 @@
1
+ export class ReadyManager {
2
+ private isReady = false;
3
+ private readyQueue: (() => void)[] = [];
4
+ wait() {
5
+ return new Promise<void>((resolve) => {
6
+ if (this.isReady) return resolve();
7
+ this.readyQueue.push(resolve);
8
+ });
9
+ }
10
+ unready() {
11
+ this.isReady = false;
12
+ }
13
+ ready() {
14
+ this.isReady = true;
15
+ if (!this.readyQueue.length) return; // check len for performance
16
+ this.readyQueue.splice(0).map((resolve) => resolve());
17
+ }
18
+ }
package/cli.ts CHANGED
@@ -14,7 +14,8 @@ const argv = yargs(hideBin(process.argv))
14
14
  .option('exit-on-idle', {
15
15
  type: 'string',
16
16
  default: '60s',
17
- description: 'Exit after being idle for specified duration',
17
+ description:
18
+ 'Exit after being idle for specified duration, default 1min, set to 0 to disable this behaviour',
18
19
  })
19
20
  .option('continue-on-crash', {
20
21
  type: 'boolean',
package/dist/cli.js CHANGED
@@ -141,7 +141,7 @@ class PolyfillTextEncoderStream {
141
141
  });
142
142
  }
143
143
 
144
- // node_modules/rambda/dist/rambda.js
144
+ // node_modules/sflow/node_modules/rambda/dist/rambda.js
145
145
  var cloneList = (list) => Array.prototype.slice.call(list);
146
146
  function curry(fn, args = []) {
147
147
  return (..._args) => ((rest) => rest.length >= fn.length ? fn(...rest) : curry(fn, rest))([...args, ..._args]);
@@ -5119,12 +5119,36 @@ class TerminalTextRender {
5119
5119
  import { writeFile } from "fs/promises";
5120
5120
  import path2 from "path";
5121
5121
  import { mkdir } from "fs/promises";
5122
+
5123
+ // ReadyManager.ts
5124
+ class ReadyManager {
5125
+ isReady = false;
5126
+ readyQueue = [];
5127
+ wait() {
5128
+ return new Promise((resolve) => {
5129
+ if (this.isReady)
5130
+ return resolve();
5131
+ this.readyQueue.push(resolve);
5132
+ });
5133
+ }
5134
+ unready() {
5135
+ this.isReady = false;
5136
+ }
5137
+ ready() {
5138
+ this.isReady = true;
5139
+ if (!this.readyQueue.length)
5140
+ return;
5141
+ this.readyQueue.splice(0).map((resolve) => resolve());
5142
+ }
5143
+ }
5144
+
5145
+ // index.ts
5122
5146
  async function claudeYes({
5123
5147
  claudeArgs = [],
5124
5148
  continueOnCrash,
5125
- cwd = process.cwd(),
5126
- env = process.env,
5127
- exitOnIdle,
5149
+ cwd,
5150
+ env,
5151
+ exitOnIdle = 60000,
5128
5152
  logFile,
5129
5153
  removeControlCharactersFromStdout = false,
5130
5154
  verbose = false
@@ -5146,52 +5170,47 @@ async function claudeYes({
5146
5170
  const prefix = "";
5147
5171
  const PREFIXLENGTH = prefix.length;
5148
5172
  let errorNoConversation = false;
5173
+ const shellReady = new ReadyManager;
5149
5174
  const shellOutputStream = new TransformStream;
5150
5175
  const outputWriter = shellOutputStream.writable.getWriter();
5151
5176
  const pty = process.versions.bun ? await import("bun-pty") : await import("node-pty");
5152
- let shell = pty.spawn("claude", claudeArgs, {
5177
+ const getPtyOptions = () => ({
5153
5178
  name: "xterm-color",
5154
5179
  cols: process.stdout.columns - PREFIXLENGTH,
5155
5180
  rows: process.stdout.rows,
5156
- cwd,
5157
- env
5181
+ cwd: cwd ?? process.cwd(),
5182
+ env: env ?? process.env
5158
5183
  });
5184
+ let shell = pty.spawn("claude", claudeArgs, getPtyOptions());
5159
5185
  let pendingExitCode = Promise.withResolvers();
5186
+ let pendingExitCodeValue = null;
5160
5187
  async function onData(data) {
5161
5188
  await outputWriter.write(data);
5189
+ shellReady.ready();
5162
5190
  }
5163
5191
  shell.onData(onData);
5164
5192
  shell.onExit(function onExit({ exitCode: exitCode2 }) {
5165
- if (continueOnCrash && exitCode2 !== 0) {
5193
+ shellReady.unready();
5194
+ const claudeCrashed = exitCode2 !== 0;
5195
+ if (claudeCrashed && continueOnCrash) {
5166
5196
  if (errorNoConversation) {
5167
5197
  console.log('Claude crashed with "No conversation found to continue", exiting...');
5168
- return pendingExitCode.resolve(exitCode2);
5198
+ return pendingExitCode.resolve(pendingExitCodeValue = exitCode2);
5169
5199
  }
5170
5200
  console.log("Claude crashed, restarting...");
5171
- shell = pty.spawn("claude", ["--continue", "continue"], {
5172
- name: "xterm-color",
5173
- cols: process.stdout.columns - PREFIXLENGTH,
5174
- rows: process.stdout.rows,
5175
- cwd,
5176
- env
5177
- });
5201
+ shell = pty.spawn("claude", ["--continue", "continue"], getPtyOptions());
5178
5202
  shell.onData(onData);
5179
5203
  shell.onExit(onExit);
5180
5204
  return;
5181
5205
  }
5182
- return pendingExitCode.resolve(exitCode2);
5206
+ return pendingExitCode.resolve(pendingExitCodeValue = exitCode2);
5183
5207
  });
5184
5208
  const exitClaudeCode = async () => {
5185
- await src_default(["\r", "/exit", "\r"]).forEach(async (e) => {
5186
- await sleepms(200);
5187
- shell.write(e);
5188
- }).run();
5209
+ continueOnCrash = false;
5210
+ await src_default(["\r", "/exit", "\r"]).forEach(async () => await sleepms(200)).forEach(async (e) => shell.write(e)).run();
5189
5211
  let exited = false;
5190
5212
  await Promise.race([
5191
- new Promise((resolve) => shell.onExit(() => {
5192
- resolve();
5193
- exited = true;
5194
- })),
5213
+ pendingExitCode.promise.then(() => exited = true),
5195
5214
  new Promise((resolve) => setTimeout(() => {
5196
5215
  if (exited)
5197
5216
  return;
@@ -5204,16 +5223,9 @@ async function claudeYes({
5204
5223
  const { columns, rows } = process.stdout;
5205
5224
  shell.resize(columns - PREFIXLENGTH, rows);
5206
5225
  });
5207
- const shellStdio = {
5208
- writable: new WritableStream({
5209
- write: (data) => shell.write(data),
5210
- close: () => {}
5211
- }),
5212
- readable: shellOutputStream.readable
5213
- };
5214
- const ttr = new TerminalTextRender;
5226
+ const render = new TerminalTextRender;
5215
5227
  const idleWatcher = !exitOnIdle ? null : createIdleWatcher(async () => {
5216
- if (ttr.render().replace(/\s+/g, " ").match(/esc to interrupt|to run in background/)) {
5228
+ if (render.render().replace(/\s+/g, " ").match(/esc to interrupt|to run in background/)) {
5217
5229
  console.log("[claude-yes] Claude is idle, but seems still working, not exiting yet");
5218
5230
  } else {
5219
5231
  console.log("[claude-yes] Claude is idle, exiting...");
@@ -5224,7 +5236,15 @@ async function claudeYes({
5224
5236
  await sleepms(200);
5225
5237
  shell.write("\r");
5226
5238
  };
5227
- src_default(fromReadable(process.stdin)).map((buffer2) => buffer2.toString()).by(shellStdio).forEach((text) => ttr.write(text)).forEach(() => idleWatcher?.ping()).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll("\r", "")).forEach(async (e2) => {
5239
+ src_default(fromReadable(process.stdin)).map((buffer2) => buffer2.toString()).by({
5240
+ writable: new WritableStream({
5241
+ write: async (data) => {
5242
+ await shellReady.wait();
5243
+ shell.write(data);
5244
+ }
5245
+ }),
5246
+ readable: shellOutputStream.readable
5247
+ }).forEach((text) => render.write(text)).forEach(() => idleWatcher?.ping()).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll("\r", "")).forEach(async (e2) => {
5228
5248
  if (e2.match(/❯ 1. Yes/))
5229
5249
  return await confirm();
5230
5250
  if (e2.match(/❯ 1. Dark mode✔|Press Enter to continue…/))
@@ -5235,14 +5255,14 @@ async function claudeYes({
5235
5255
  }
5236
5256
  }).run()).replaceAll(/.*(?:\r\n?|\r?\n)/g, (line) => prefix + line).map((e) => removeControlCharactersFromStdout ? removeControlCharacters(e) : e).to(fromWritable(process.stdout));
5237
5257
  const exitCode = await pendingExitCode.promise;
5238
- verbose && console.log(`[claude-yes] claude exited with code ${exitCode}`);
5258
+ console.log(`[claude-yes] claude exited with code ${exitCode}`);
5239
5259
  if (logFile) {
5240
5260
  verbose && console.log(`[claude-yes] Writing rendered logs to ${logFile}`);
5241
5261
  const logFilePath = path2.resolve(logFile);
5242
5262
  await mkdir(path2.dirname(logFilePath), { recursive: true }).catch(() => null);
5243
- await writeFile(logFilePath, ttr.render());
5263
+ await writeFile(logFilePath, render.render());
5244
5264
  }
5245
- return { exitCode, logs: ttr.render() };
5265
+ return { exitCode, logs: render.render() };
5246
5266
  }
5247
5267
  // node_modules/enhanced-ms/dist/index.js
5248
5268
  var units = {
@@ -11395,7 +11415,7 @@ var yargs_default = Yargs;
11395
11415
  var argv = yargs_default(hideBin(process.argv)).usage("Usage: $0 [options] [--] [claude args]").example('$0 --exit-on-idle=30s --continue-on-crash "help me solve all todos in my codebase"', "Run Claude with a 30 seconds idle timeout and continue on crash").option("exit-on-idle", {
11396
11416
  type: "string",
11397
11417
  default: "60s",
11398
- description: "Exit after being idle for specified duration"
11418
+ description: "Exit after being idle for specified duration, default 1min, set to 0 to disable this behaviour"
11399
11419
  }).option("continue-on-crash", {
11400
11420
  type: "boolean",
11401
11421
  default: true,
@@ -11420,5 +11440,5 @@ var { exitCode, logs: logs2 } = await claudeYes({
11420
11440
  });
11421
11441
  process.exit(exitCode ?? 1);
11422
11442
 
11423
- //# debugId=60C91F29E6CD011A64756E2164756E21
11443
+ //# debugId=3E12815BE75077F764756E2164756E21
11424
11444
  //# sourceMappingURL=cli.js.map