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 +5 -1
- package/ReadyManager.ts +18 -0
- package/cli.ts +2 -1
- package/dist/cli.js +60 -40
- package/dist/cli.js.map +6 -5
- package/dist/index.js +59 -39
- package/dist/index.js.map +5 -4
- package/index.ts +42 -43
- package/package.json +6 -5
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:
|
package/ReadyManager.ts
ADDED
|
@@ -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:
|
|
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
|
|
5126
|
-
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
5186
|
-
|
|
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
|
-
|
|
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
|
|
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 (
|
|
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(
|
|
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
|
-
|
|
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,
|
|
5263
|
+
await writeFile(logFilePath, render.render());
|
|
5244
5264
|
}
|
|
5245
|
-
return { exitCode, logs:
|
|
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=
|
|
11443
|
+
//# debugId=3E12815BE75077F764756E2164756E21
|
|
11424
11444
|
//# sourceMappingURL=cli.js.map
|