claude-yes 1.10.0 → 1.11.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 +6 -6
- package/createIdleWatcher.spec.ts +2 -2
- package/dist/cli.js +204 -24
- package/dist/index.js +204 -24
- package/index.ts +154 -118
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -23,26 +23,26 @@ Learn more about Claude Code: https://www.anthropic.com/claude-code
|
|
|
23
23
|
Then install this project:
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
|
-
npm install yes
|
|
26
|
+
npm install claude-yes -g
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
## Usage
|
|
30
30
|
|
|
31
|
-
|
|
32
31
|
```bash
|
|
33
|
-
yes
|
|
32
|
+
claude-yes [command] [prompts] [--exit-on-idle]
|
|
34
33
|
# works exactly same as `claude` command, and automatically says "Yes" to all yes/no prompts
|
|
35
34
|
|
|
36
35
|
# e.g.
|
|
37
|
-
yes
|
|
38
|
-
bunx yes
|
|
36
|
+
claude-yes "run all tests and commit current changes"
|
|
37
|
+
bunx claude-yes "Solve TODO.md"
|
|
39
38
|
|
|
40
39
|
# Auto-exit when Claude becomes idle (useful for automation)
|
|
41
|
-
yes
|
|
40
|
+
claude-yes "run all tests and commit current changes" --exit-on-idle
|
|
42
41
|
|
|
43
42
|
```
|
|
44
43
|
|
|
45
44
|
The tool will:
|
|
45
|
+
|
|
46
46
|
1. run Claude Code
|
|
47
47
|
2. Whenever claude stucked on yes/no prompts, Automatically say YES, YES, YES, YES, YES to claude
|
|
48
48
|
3. When using `--exit-on-idle` flag, automatically exit when Claude becomes idle for 3 seconds (useful for automation scripts)
|
|
@@ -13,7 +13,7 @@ it('createIdleWatcher should trigger onIdle after timeout', async () => {
|
|
|
13
13
|
expect(idleTriggered).toBe(true);
|
|
14
14
|
}, 1000);
|
|
15
15
|
|
|
16
|
-
it
|
|
16
|
+
it('createIdleWatcher should reset timeout on ping', async () => {
|
|
17
17
|
let idleTriggered = false;
|
|
18
18
|
const watcher = createIdleWatcher(() => {
|
|
19
19
|
idleTriggered = true;
|
|
@@ -28,7 +28,7 @@ it.concurrent('createIdleWatcher should reset timeout on ping', async () => {
|
|
|
28
28
|
expect(idleTriggered).toBe(true);
|
|
29
29
|
}, 1000);
|
|
30
30
|
|
|
31
|
-
it
|
|
31
|
+
it('createIdleWatcher should update lastActiveTime on ping', async () => {
|
|
32
32
|
const watcher = createIdleWatcher(() => { }, 1000);
|
|
33
33
|
|
|
34
34
|
const initialTime = watcher.getLastActiveTime();
|
package/dist/cli.js
CHANGED
|
@@ -5046,8 +5046,172 @@ function fromWritable(i) {
|
|
|
5046
5046
|
});
|
|
5047
5047
|
}
|
|
5048
5048
|
|
|
5049
|
-
// index.
|
|
5050
|
-
import
|
|
5049
|
+
// node_modules/bun-pty/dist/index.js
|
|
5050
|
+
import { dlopen, FFIType, ptr } from "bun:ffi";
|
|
5051
|
+
import { Buffer } from "buffer";
|
|
5052
|
+
import { join as join2 } from "path";
|
|
5053
|
+
import { existsSync } from "fs";
|
|
5054
|
+
|
|
5055
|
+
class EventEmitter {
|
|
5056
|
+
listeners = [];
|
|
5057
|
+
event = (listener) => {
|
|
5058
|
+
this.listeners.push(listener);
|
|
5059
|
+
return {
|
|
5060
|
+
dispose: () => {
|
|
5061
|
+
const i = this.listeners.indexOf(listener);
|
|
5062
|
+
if (i !== -1) {
|
|
5063
|
+
this.listeners.splice(i, 1);
|
|
5064
|
+
}
|
|
5065
|
+
}
|
|
5066
|
+
};
|
|
5067
|
+
};
|
|
5068
|
+
fire(data) {
|
|
5069
|
+
for (const listener of this.listeners) {
|
|
5070
|
+
listener(data);
|
|
5071
|
+
}
|
|
5072
|
+
}
|
|
5073
|
+
}
|
|
5074
|
+
var DEFAULT_COLS = 80;
|
|
5075
|
+
var DEFAULT_ROWS = 24;
|
|
5076
|
+
var DEFAULT_FILE = "sh";
|
|
5077
|
+
var DEFAULT_NAME = "xterm";
|
|
5078
|
+
function resolveLibPath() {
|
|
5079
|
+
const env = process.env.BUN_PTY_LIB;
|
|
5080
|
+
if (env && existsSync(env))
|
|
5081
|
+
return env;
|
|
5082
|
+
const platform = process.platform;
|
|
5083
|
+
const arch = process.arch;
|
|
5084
|
+
const filename = platform === "darwin" ? arch === "arm64" ? "librust_pty_arm64.dylib" : "librust_pty.dylib" : platform === "win32" ? "rust_pty.dll" : arch === "arm64" ? "librust_pty_arm64.so" : "librust_pty.so";
|
|
5085
|
+
const base = Bun.fileURLToPath(import.meta.url);
|
|
5086
|
+
const here = base.replace(/\/dist\/.*$/, "");
|
|
5087
|
+
const fallbackPaths = [
|
|
5088
|
+
join2(here, "rust-pty", "target", "release", filename),
|
|
5089
|
+
join2(here, "..", "bun-pty", "rust-pty", "target", "release", filename),
|
|
5090
|
+
join2(process.cwd(), "node_modules", "bun-pty", "rust-pty", "target", "release", filename)
|
|
5091
|
+
];
|
|
5092
|
+
for (const path2 of fallbackPaths) {
|
|
5093
|
+
if (existsSync(path2))
|
|
5094
|
+
return path2;
|
|
5095
|
+
}
|
|
5096
|
+
throw new Error(`librust_pty shared library not found.
|
|
5097
|
+
Checked:
|
|
5098
|
+
- BUN_PTY_LIB=${env ?? "<unset>"}
|
|
5099
|
+
- ${fallbackPaths.join(`
|
|
5100
|
+
- `)}
|
|
5101
|
+
|
|
5102
|
+
Set BUN_PTY_LIB or ensure one of these paths contains the file.`);
|
|
5103
|
+
}
|
|
5104
|
+
var libPath = resolveLibPath();
|
|
5105
|
+
var lib;
|
|
5106
|
+
try {
|
|
5107
|
+
lib = dlopen(libPath, {
|
|
5108
|
+
bun_pty_spawn: {
|
|
5109
|
+
args: [FFIType.cstring, FFIType.cstring, FFIType.i32, FFIType.i32],
|
|
5110
|
+
returns: FFIType.i32
|
|
5111
|
+
},
|
|
5112
|
+
bun_pty_write: {
|
|
5113
|
+
args: [FFIType.i32, FFIType.pointer, FFIType.i32],
|
|
5114
|
+
returns: FFIType.i32
|
|
5115
|
+
},
|
|
5116
|
+
bun_pty_read: {
|
|
5117
|
+
args: [FFIType.i32, FFIType.pointer, FFIType.i32],
|
|
5118
|
+
returns: FFIType.i32
|
|
5119
|
+
},
|
|
5120
|
+
bun_pty_resize: {
|
|
5121
|
+
args: [FFIType.i32, FFIType.i32, FFIType.i32],
|
|
5122
|
+
returns: FFIType.i32
|
|
5123
|
+
},
|
|
5124
|
+
bun_pty_kill: { args: [FFIType.i32], returns: FFIType.i32 },
|
|
5125
|
+
bun_pty_get_pid: { args: [FFIType.i32], returns: FFIType.i32 },
|
|
5126
|
+
bun_pty_close: { args: [FFIType.i32], returns: FFIType.void }
|
|
5127
|
+
});
|
|
5128
|
+
} catch (error) {
|
|
5129
|
+
console.error("Failed to load lib", error);
|
|
5130
|
+
}
|
|
5131
|
+
|
|
5132
|
+
class Terminal {
|
|
5133
|
+
handle = -1;
|
|
5134
|
+
_pid = -1;
|
|
5135
|
+
_cols = DEFAULT_COLS;
|
|
5136
|
+
_rows = DEFAULT_ROWS;
|
|
5137
|
+
_name = DEFAULT_NAME;
|
|
5138
|
+
_readLoop = false;
|
|
5139
|
+
_closing = false;
|
|
5140
|
+
_onData = new EventEmitter;
|
|
5141
|
+
_onExit = new EventEmitter;
|
|
5142
|
+
constructor(file = DEFAULT_FILE, args = [], opts = { name: DEFAULT_NAME }) {
|
|
5143
|
+
this._cols = opts.cols ?? DEFAULT_COLS;
|
|
5144
|
+
this._rows = opts.rows ?? DEFAULT_ROWS;
|
|
5145
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
5146
|
+
const cmdline = [file, ...args].join(" ");
|
|
5147
|
+
this.handle = lib.symbols.bun_pty_spawn(Buffer.from(`${cmdline}\x00`, "utf8"), Buffer.from(`${cwd}\x00`, "utf8"), this._cols, this._rows);
|
|
5148
|
+
if (this.handle < 0)
|
|
5149
|
+
throw new Error("PTY spawn failed");
|
|
5150
|
+
this._pid = lib.symbols.bun_pty_get_pid(this.handle);
|
|
5151
|
+
this._startReadLoop();
|
|
5152
|
+
}
|
|
5153
|
+
get pid() {
|
|
5154
|
+
return this._pid;
|
|
5155
|
+
}
|
|
5156
|
+
get cols() {
|
|
5157
|
+
return this._cols;
|
|
5158
|
+
}
|
|
5159
|
+
get rows() {
|
|
5160
|
+
return this._rows;
|
|
5161
|
+
}
|
|
5162
|
+
get process() {
|
|
5163
|
+
return "shell";
|
|
5164
|
+
}
|
|
5165
|
+
get onData() {
|
|
5166
|
+
return this._onData.event;
|
|
5167
|
+
}
|
|
5168
|
+
get onExit() {
|
|
5169
|
+
return this._onExit.event;
|
|
5170
|
+
}
|
|
5171
|
+
write(data) {
|
|
5172
|
+
if (this._closing)
|
|
5173
|
+
return;
|
|
5174
|
+
const buf = Buffer.from(data, "utf8");
|
|
5175
|
+
lib.symbols.bun_pty_write(this.handle, ptr(buf), buf.length);
|
|
5176
|
+
}
|
|
5177
|
+
resize(cols, rows) {
|
|
5178
|
+
if (this._closing)
|
|
5179
|
+
return;
|
|
5180
|
+
this._cols = cols;
|
|
5181
|
+
this._rows = rows;
|
|
5182
|
+
lib.symbols.bun_pty_resize(this.handle, cols, rows);
|
|
5183
|
+
}
|
|
5184
|
+
kill(signal = "SIGTERM") {
|
|
5185
|
+
if (this._closing)
|
|
5186
|
+
return;
|
|
5187
|
+
this._closing = true;
|
|
5188
|
+
lib.symbols.bun_pty_kill(this.handle);
|
|
5189
|
+
lib.symbols.bun_pty_close(this.handle);
|
|
5190
|
+
this._onExit.fire({ exitCode: 0, signal });
|
|
5191
|
+
}
|
|
5192
|
+
async _startReadLoop() {
|
|
5193
|
+
if (this._readLoop)
|
|
5194
|
+
return;
|
|
5195
|
+
this._readLoop = true;
|
|
5196
|
+
const buf = Buffer.allocUnsafe(4096);
|
|
5197
|
+
while (this._readLoop && !this._closing) {
|
|
5198
|
+
const n = lib.symbols.bun_pty_read(this.handle, ptr(buf), buf.length);
|
|
5199
|
+
if (n > 0) {
|
|
5200
|
+
this._onData.fire(buf.subarray(0, n).toString("utf8"));
|
|
5201
|
+
} else if (n === -2) {
|
|
5202
|
+
this._onExit.fire({ exitCode: 0 });
|
|
5203
|
+
break;
|
|
5204
|
+
} else if (n < 0) {
|
|
5205
|
+
break;
|
|
5206
|
+
} else {
|
|
5207
|
+
await new Promise((r) => setTimeout(r, 8));
|
|
5208
|
+
}
|
|
5209
|
+
}
|
|
5210
|
+
}
|
|
5211
|
+
}
|
|
5212
|
+
function spawn(file, args, options) {
|
|
5213
|
+
return new Terminal(file, args, options);
|
|
5214
|
+
}
|
|
5051
5215
|
|
|
5052
5216
|
// createIdleWatcher.ts
|
|
5053
5217
|
function createIdleWatcher(onIdle, idleTimeout) {
|
|
@@ -5082,7 +5246,11 @@ function sleepms(ms) {
|
|
|
5082
5246
|
if (__require.main == __require.module)
|
|
5083
5247
|
await main();
|
|
5084
5248
|
async function main() {}
|
|
5085
|
-
async function claudeYes({
|
|
5249
|
+
async function claudeYes({
|
|
5250
|
+
continueOnCrash,
|
|
5251
|
+
exitOnIdle,
|
|
5252
|
+
claudeArgs = []
|
|
5253
|
+
} = {}) {
|
|
5086
5254
|
const defaultTimeout = 5000;
|
|
5087
5255
|
const idleTimeout = typeof exitOnIdle === "number" ? exitOnIdle : defaultTimeout;
|
|
5088
5256
|
console.log("⭐ Starting claude, automatically responding to yes/no prompts...");
|
|
@@ -5090,9 +5258,11 @@ async function claudeYes({ continueOnCrash, exitOnIdle, claudeArgs = [] } = {})
|
|
|
5090
5258
|
process.stdin.setRawMode?.(true);
|
|
5091
5259
|
const prefix = "";
|
|
5092
5260
|
const PREFIXLENGTH = prefix.length;
|
|
5261
|
+
let errorNoConversation = false;
|
|
5093
5262
|
const shellOutputStream = new TransformStream;
|
|
5094
5263
|
const outputWriter = shellOutputStream.writable.getWriter();
|
|
5095
|
-
let shell =
|
|
5264
|
+
let shell = spawn("claude", claudeArgs, {
|
|
5265
|
+
name: "xterm-color",
|
|
5096
5266
|
cols: process.stdout.columns - PREFIXLENGTH,
|
|
5097
5267
|
rows: process.stdout.rows,
|
|
5098
5268
|
cwd: process.cwd(),
|
|
@@ -5103,18 +5273,22 @@ async function claudeYes({ continueOnCrash, exitOnIdle, claudeArgs = [] } = {})
|
|
|
5103
5273
|
}
|
|
5104
5274
|
shell.onData(onData);
|
|
5105
5275
|
shell.onExit(function onExit({ exitCode }) {
|
|
5106
|
-
if (continueOnCrash) {
|
|
5107
|
-
if (
|
|
5108
|
-
console.log(
|
|
5109
|
-
|
|
5110
|
-
cols: process.stdout.columns - PREFIXLENGTH,
|
|
5111
|
-
rows: process.stdout.rows,
|
|
5112
|
-
cwd: process.cwd(),
|
|
5113
|
-
env: process.env
|
|
5114
|
-
});
|
|
5115
|
-
shell.onData(onData);
|
|
5116
|
-
shell.onExit(onExit);
|
|
5276
|
+
if (continueOnCrash && exitCode !== 0) {
|
|
5277
|
+
if (errorNoConversation) {
|
|
5278
|
+
console.log('Claude crashed with "No conversation found to continue", exiting...');
|
|
5279
|
+
process.exit(exitCode);
|
|
5117
5280
|
}
|
|
5281
|
+
console.log("Claude crashed, restarting...");
|
|
5282
|
+
shell = spawn("claude", ["continue", "--continue"], {
|
|
5283
|
+
name: "xterm-color",
|
|
5284
|
+
cols: process.stdout.columns - PREFIXLENGTH,
|
|
5285
|
+
rows: process.stdout.rows,
|
|
5286
|
+
cwd: process.cwd(),
|
|
5287
|
+
env: process.env
|
|
5288
|
+
});
|
|
5289
|
+
shell.onData(onData);
|
|
5290
|
+
shell.onExit(onExit);
|
|
5291
|
+
return;
|
|
5118
5292
|
}
|
|
5119
5293
|
process.exit(exitCode);
|
|
5120
5294
|
});
|
|
@@ -5142,7 +5316,10 @@ async function claudeYes({ continueOnCrash, exitOnIdle, claudeArgs = [] } = {})
|
|
|
5142
5316
|
shell.resize(columns - PREFIXLENGTH, rows);
|
|
5143
5317
|
});
|
|
5144
5318
|
const shellStdio = {
|
|
5145
|
-
writable: new WritableStream({
|
|
5319
|
+
writable: new WritableStream({
|
|
5320
|
+
write: (data) => shell.write(data),
|
|
5321
|
+
close: () => {}
|
|
5322
|
+
}),
|
|
5146
5323
|
readable: shellOutputStream.readable
|
|
5147
5324
|
};
|
|
5148
5325
|
const idleWatcher = createIdleWatcher(async () => {
|
|
@@ -5151,15 +5328,18 @@ async function claudeYes({ continueOnCrash, exitOnIdle, claudeArgs = [] } = {})
|
|
|
5151
5328
|
await exitClaudeCode();
|
|
5152
5329
|
}
|
|
5153
5330
|
}, idleTimeout);
|
|
5331
|
+
const confirm = async () => {
|
|
5332
|
+
await sleepms(200);
|
|
5333
|
+
shell.write("\r");
|
|
5334
|
+
};
|
|
5154
5335
|
await src_default(fromReadable(process.stdin)).map((buffer2) => buffer2.toString()).by(shellStdio).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll("\r", "")).forEach(async (e2) => {
|
|
5155
|
-
if (e2.match(/❯ 1. Yes/))
|
|
5156
|
-
await
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
shell.write("\r");
|
|
5336
|
+
if (e2.match(/❯ 1. Yes/))
|
|
5337
|
+
return await confirm();
|
|
5338
|
+
if (e2.match(/❯ 1. Dark mode✔|Press Enter to continue…/))
|
|
5339
|
+
return await confirm();
|
|
5340
|
+
if (e2.match(/No conversation found to continue/)) {
|
|
5341
|
+
errorNoConversation = true;
|
|
5342
|
+
return;
|
|
5163
5343
|
}
|
|
5164
5344
|
}).run()).replaceAll(/.*(?:\r\n?|\r?\n)/g, (line) => prefix + line).forEach(() => idleWatcher.ping()).map((e) => !process.stdout.isTTY ? removeControlCharacters(e) : e).to(fromWritable(process.stdout));
|
|
5165
5345
|
}
|
package/dist/index.js
CHANGED
|
@@ -4826,8 +4826,172 @@ function fromWritable(i) {
|
|
|
4826
4826
|
});
|
|
4827
4827
|
}
|
|
4828
4828
|
|
|
4829
|
-
// index.
|
|
4830
|
-
import
|
|
4829
|
+
// node_modules/bun-pty/dist/index.js
|
|
4830
|
+
import { dlopen, FFIType, ptr } from "bun:ffi";
|
|
4831
|
+
import { Buffer } from "buffer";
|
|
4832
|
+
import { join as join2 } from "path";
|
|
4833
|
+
import { existsSync } from "fs";
|
|
4834
|
+
|
|
4835
|
+
class EventEmitter {
|
|
4836
|
+
listeners = [];
|
|
4837
|
+
event = (listener) => {
|
|
4838
|
+
this.listeners.push(listener);
|
|
4839
|
+
return {
|
|
4840
|
+
dispose: () => {
|
|
4841
|
+
const i = this.listeners.indexOf(listener);
|
|
4842
|
+
if (i !== -1) {
|
|
4843
|
+
this.listeners.splice(i, 1);
|
|
4844
|
+
}
|
|
4845
|
+
}
|
|
4846
|
+
};
|
|
4847
|
+
};
|
|
4848
|
+
fire(data) {
|
|
4849
|
+
for (const listener of this.listeners) {
|
|
4850
|
+
listener(data);
|
|
4851
|
+
}
|
|
4852
|
+
}
|
|
4853
|
+
}
|
|
4854
|
+
var DEFAULT_COLS = 80;
|
|
4855
|
+
var DEFAULT_ROWS = 24;
|
|
4856
|
+
var DEFAULT_FILE = "sh";
|
|
4857
|
+
var DEFAULT_NAME = "xterm";
|
|
4858
|
+
function resolveLibPath() {
|
|
4859
|
+
const env = process.env.BUN_PTY_LIB;
|
|
4860
|
+
if (env && existsSync(env))
|
|
4861
|
+
return env;
|
|
4862
|
+
const platform = process.platform;
|
|
4863
|
+
const arch = process.arch;
|
|
4864
|
+
const filename = platform === "darwin" ? arch === "arm64" ? "librust_pty_arm64.dylib" : "librust_pty.dylib" : platform === "win32" ? "rust_pty.dll" : arch === "arm64" ? "librust_pty_arm64.so" : "librust_pty.so";
|
|
4865
|
+
const base = Bun.fileURLToPath(import.meta.url);
|
|
4866
|
+
const here = base.replace(/\/dist\/.*$/, "");
|
|
4867
|
+
const fallbackPaths = [
|
|
4868
|
+
join2(here, "rust-pty", "target", "release", filename),
|
|
4869
|
+
join2(here, "..", "bun-pty", "rust-pty", "target", "release", filename),
|
|
4870
|
+
join2(process.cwd(), "node_modules", "bun-pty", "rust-pty", "target", "release", filename)
|
|
4871
|
+
];
|
|
4872
|
+
for (const path2 of fallbackPaths) {
|
|
4873
|
+
if (existsSync(path2))
|
|
4874
|
+
return path2;
|
|
4875
|
+
}
|
|
4876
|
+
throw new Error(`librust_pty shared library not found.
|
|
4877
|
+
Checked:
|
|
4878
|
+
- BUN_PTY_LIB=${env ?? "<unset>"}
|
|
4879
|
+
- ${fallbackPaths.join(`
|
|
4880
|
+
- `)}
|
|
4881
|
+
|
|
4882
|
+
Set BUN_PTY_LIB or ensure one of these paths contains the file.`);
|
|
4883
|
+
}
|
|
4884
|
+
var libPath = resolveLibPath();
|
|
4885
|
+
var lib;
|
|
4886
|
+
try {
|
|
4887
|
+
lib = dlopen(libPath, {
|
|
4888
|
+
bun_pty_spawn: {
|
|
4889
|
+
args: [FFIType.cstring, FFIType.cstring, FFIType.i32, FFIType.i32],
|
|
4890
|
+
returns: FFIType.i32
|
|
4891
|
+
},
|
|
4892
|
+
bun_pty_write: {
|
|
4893
|
+
args: [FFIType.i32, FFIType.pointer, FFIType.i32],
|
|
4894
|
+
returns: FFIType.i32
|
|
4895
|
+
},
|
|
4896
|
+
bun_pty_read: {
|
|
4897
|
+
args: [FFIType.i32, FFIType.pointer, FFIType.i32],
|
|
4898
|
+
returns: FFIType.i32
|
|
4899
|
+
},
|
|
4900
|
+
bun_pty_resize: {
|
|
4901
|
+
args: [FFIType.i32, FFIType.i32, FFIType.i32],
|
|
4902
|
+
returns: FFIType.i32
|
|
4903
|
+
},
|
|
4904
|
+
bun_pty_kill: { args: [FFIType.i32], returns: FFIType.i32 },
|
|
4905
|
+
bun_pty_get_pid: { args: [FFIType.i32], returns: FFIType.i32 },
|
|
4906
|
+
bun_pty_close: { args: [FFIType.i32], returns: FFIType.void }
|
|
4907
|
+
});
|
|
4908
|
+
} catch (error) {
|
|
4909
|
+
console.error("Failed to load lib", error);
|
|
4910
|
+
}
|
|
4911
|
+
|
|
4912
|
+
class Terminal {
|
|
4913
|
+
handle = -1;
|
|
4914
|
+
_pid = -1;
|
|
4915
|
+
_cols = DEFAULT_COLS;
|
|
4916
|
+
_rows = DEFAULT_ROWS;
|
|
4917
|
+
_name = DEFAULT_NAME;
|
|
4918
|
+
_readLoop = false;
|
|
4919
|
+
_closing = false;
|
|
4920
|
+
_onData = new EventEmitter;
|
|
4921
|
+
_onExit = new EventEmitter;
|
|
4922
|
+
constructor(file = DEFAULT_FILE, args = [], opts = { name: DEFAULT_NAME }) {
|
|
4923
|
+
this._cols = opts.cols ?? DEFAULT_COLS;
|
|
4924
|
+
this._rows = opts.rows ?? DEFAULT_ROWS;
|
|
4925
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
4926
|
+
const cmdline = [file, ...args].join(" ");
|
|
4927
|
+
this.handle = lib.symbols.bun_pty_spawn(Buffer.from(`${cmdline}\x00`, "utf8"), Buffer.from(`${cwd}\x00`, "utf8"), this._cols, this._rows);
|
|
4928
|
+
if (this.handle < 0)
|
|
4929
|
+
throw new Error("PTY spawn failed");
|
|
4930
|
+
this._pid = lib.symbols.bun_pty_get_pid(this.handle);
|
|
4931
|
+
this._startReadLoop();
|
|
4932
|
+
}
|
|
4933
|
+
get pid() {
|
|
4934
|
+
return this._pid;
|
|
4935
|
+
}
|
|
4936
|
+
get cols() {
|
|
4937
|
+
return this._cols;
|
|
4938
|
+
}
|
|
4939
|
+
get rows() {
|
|
4940
|
+
return this._rows;
|
|
4941
|
+
}
|
|
4942
|
+
get process() {
|
|
4943
|
+
return "shell";
|
|
4944
|
+
}
|
|
4945
|
+
get onData() {
|
|
4946
|
+
return this._onData.event;
|
|
4947
|
+
}
|
|
4948
|
+
get onExit() {
|
|
4949
|
+
return this._onExit.event;
|
|
4950
|
+
}
|
|
4951
|
+
write(data) {
|
|
4952
|
+
if (this._closing)
|
|
4953
|
+
return;
|
|
4954
|
+
const buf = Buffer.from(data, "utf8");
|
|
4955
|
+
lib.symbols.bun_pty_write(this.handle, ptr(buf), buf.length);
|
|
4956
|
+
}
|
|
4957
|
+
resize(cols, rows) {
|
|
4958
|
+
if (this._closing)
|
|
4959
|
+
return;
|
|
4960
|
+
this._cols = cols;
|
|
4961
|
+
this._rows = rows;
|
|
4962
|
+
lib.symbols.bun_pty_resize(this.handle, cols, rows);
|
|
4963
|
+
}
|
|
4964
|
+
kill(signal = "SIGTERM") {
|
|
4965
|
+
if (this._closing)
|
|
4966
|
+
return;
|
|
4967
|
+
this._closing = true;
|
|
4968
|
+
lib.symbols.bun_pty_kill(this.handle);
|
|
4969
|
+
lib.symbols.bun_pty_close(this.handle);
|
|
4970
|
+
this._onExit.fire({ exitCode: 0, signal });
|
|
4971
|
+
}
|
|
4972
|
+
async _startReadLoop() {
|
|
4973
|
+
if (this._readLoop)
|
|
4974
|
+
return;
|
|
4975
|
+
this._readLoop = true;
|
|
4976
|
+
const buf = Buffer.allocUnsafe(4096);
|
|
4977
|
+
while (this._readLoop && !this._closing) {
|
|
4978
|
+
const n = lib.symbols.bun_pty_read(this.handle, ptr(buf), buf.length);
|
|
4979
|
+
if (n > 0) {
|
|
4980
|
+
this._onData.fire(buf.subarray(0, n).toString("utf8"));
|
|
4981
|
+
} else if (n === -2) {
|
|
4982
|
+
this._onExit.fire({ exitCode: 0 });
|
|
4983
|
+
break;
|
|
4984
|
+
} else if (n < 0) {
|
|
4985
|
+
break;
|
|
4986
|
+
} else {
|
|
4987
|
+
await new Promise((r) => setTimeout(r, 8));
|
|
4988
|
+
}
|
|
4989
|
+
}
|
|
4990
|
+
}
|
|
4991
|
+
}
|
|
4992
|
+
function spawn(file, args, options) {
|
|
4993
|
+
return new Terminal(file, args, options);
|
|
4994
|
+
}
|
|
4831
4995
|
|
|
4832
4996
|
// createIdleWatcher.ts
|
|
4833
4997
|
function createIdleWatcher(onIdle, idleTimeout) {
|
|
@@ -4862,7 +5026,11 @@ function sleepms(ms) {
|
|
|
4862
5026
|
if (__require.main == __require.module)
|
|
4863
5027
|
await main();
|
|
4864
5028
|
async function main() {}
|
|
4865
|
-
async function claudeYes({
|
|
5029
|
+
async function claudeYes({
|
|
5030
|
+
continueOnCrash,
|
|
5031
|
+
exitOnIdle,
|
|
5032
|
+
claudeArgs = []
|
|
5033
|
+
} = {}) {
|
|
4866
5034
|
const defaultTimeout = 5000;
|
|
4867
5035
|
const idleTimeout = typeof exitOnIdle === "number" ? exitOnIdle : defaultTimeout;
|
|
4868
5036
|
console.log("⭐ Starting claude, automatically responding to yes/no prompts...");
|
|
@@ -4870,9 +5038,11 @@ async function claudeYes({ continueOnCrash, exitOnIdle, claudeArgs = [] } = {})
|
|
|
4870
5038
|
process.stdin.setRawMode?.(true);
|
|
4871
5039
|
const prefix = "";
|
|
4872
5040
|
const PREFIXLENGTH = prefix.length;
|
|
5041
|
+
let errorNoConversation = false;
|
|
4873
5042
|
const shellOutputStream = new TransformStream;
|
|
4874
5043
|
const outputWriter = shellOutputStream.writable.getWriter();
|
|
4875
|
-
let shell =
|
|
5044
|
+
let shell = spawn("claude", claudeArgs, {
|
|
5045
|
+
name: "xterm-color",
|
|
4876
5046
|
cols: process.stdout.columns - PREFIXLENGTH,
|
|
4877
5047
|
rows: process.stdout.rows,
|
|
4878
5048
|
cwd: process.cwd(),
|
|
@@ -4883,18 +5053,22 @@ async function claudeYes({ continueOnCrash, exitOnIdle, claudeArgs = [] } = {})
|
|
|
4883
5053
|
}
|
|
4884
5054
|
shell.onData(onData);
|
|
4885
5055
|
shell.onExit(function onExit({ exitCode }) {
|
|
4886
|
-
if (continueOnCrash) {
|
|
4887
|
-
if (
|
|
4888
|
-
console.log(
|
|
4889
|
-
|
|
4890
|
-
cols: process.stdout.columns - PREFIXLENGTH,
|
|
4891
|
-
rows: process.stdout.rows,
|
|
4892
|
-
cwd: process.cwd(),
|
|
4893
|
-
env: process.env
|
|
4894
|
-
});
|
|
4895
|
-
shell.onData(onData);
|
|
4896
|
-
shell.onExit(onExit);
|
|
5056
|
+
if (continueOnCrash && exitCode !== 0) {
|
|
5057
|
+
if (errorNoConversation) {
|
|
5058
|
+
console.log('Claude crashed with "No conversation found to continue", exiting...');
|
|
5059
|
+
process.exit(exitCode);
|
|
4897
5060
|
}
|
|
5061
|
+
console.log("Claude crashed, restarting...");
|
|
5062
|
+
shell = spawn("claude", ["continue", "--continue"], {
|
|
5063
|
+
name: "xterm-color",
|
|
5064
|
+
cols: process.stdout.columns - PREFIXLENGTH,
|
|
5065
|
+
rows: process.stdout.rows,
|
|
5066
|
+
cwd: process.cwd(),
|
|
5067
|
+
env: process.env
|
|
5068
|
+
});
|
|
5069
|
+
shell.onData(onData);
|
|
5070
|
+
shell.onExit(onExit);
|
|
5071
|
+
return;
|
|
4898
5072
|
}
|
|
4899
5073
|
process.exit(exitCode);
|
|
4900
5074
|
});
|
|
@@ -4922,7 +5096,10 @@ async function claudeYes({ continueOnCrash, exitOnIdle, claudeArgs = [] } = {})
|
|
|
4922
5096
|
shell.resize(columns - PREFIXLENGTH, rows);
|
|
4923
5097
|
});
|
|
4924
5098
|
const shellStdio = {
|
|
4925
|
-
writable: new WritableStream({
|
|
5099
|
+
writable: new WritableStream({
|
|
5100
|
+
write: (data) => shell.write(data),
|
|
5101
|
+
close: () => {}
|
|
5102
|
+
}),
|
|
4926
5103
|
readable: shellOutputStream.readable
|
|
4927
5104
|
};
|
|
4928
5105
|
const idleWatcher = createIdleWatcher(async () => {
|
|
@@ -4931,15 +5108,18 @@ async function claudeYes({ continueOnCrash, exitOnIdle, claudeArgs = [] } = {})
|
|
|
4931
5108
|
await exitClaudeCode();
|
|
4932
5109
|
}
|
|
4933
5110
|
}, idleTimeout);
|
|
5111
|
+
const confirm = async () => {
|
|
5112
|
+
await sleepms(200);
|
|
5113
|
+
shell.write("\r");
|
|
5114
|
+
};
|
|
4934
5115
|
await src_default(fromReadable(process.stdin)).map((buffer2) => buffer2.toString()).by(shellStdio).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll("\r", "")).forEach(async (e2) => {
|
|
4935
|
-
if (e2.match(/❯ 1. Yes/))
|
|
4936
|
-
await
|
|
4937
|
-
|
|
4938
|
-
|
|
4939
|
-
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
shell.write("\r");
|
|
5116
|
+
if (e2.match(/❯ 1. Yes/))
|
|
5117
|
+
return await confirm();
|
|
5118
|
+
if (e2.match(/❯ 1. Dark mode✔|Press Enter to continue…/))
|
|
5119
|
+
return await confirm();
|
|
5120
|
+
if (e2.match(/No conversation found to continue/)) {
|
|
5121
|
+
errorNoConversation = true;
|
|
5122
|
+
return;
|
|
4943
5123
|
}
|
|
4944
5124
|
}).run()).replaceAll(/.*(?:\r\n?|\r?\n)/g, (line) => prefix + line).forEach(() => idleWatcher.ping()).map((e) => !process.stdout.isTTY ? removeControlCharacters(e) : e).to(fromWritable(process.stdout));
|
|
4945
5125
|
}
|
package/index.ts
CHANGED
|
@@ -1,136 +1,172 @@
|
|
|
1
|
-
|
|
2
1
|
import { fromReadable, fromWritable } from "from-node-stream";
|
|
3
|
-
import * as pty from "
|
|
2
|
+
import * as pty from "bun-pty";
|
|
4
3
|
import sflow from "sflow";
|
|
5
4
|
import { createIdleWatcher } from "./createIdleWatcher";
|
|
6
5
|
import { removeControlCharacters } from "./removeControlCharacters";
|
|
7
6
|
import { sleepms } from "./utils";
|
|
8
7
|
|
|
9
|
-
|
|
10
8
|
if (import.meta.main) await main();
|
|
11
9
|
async function main() {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
// this script not support bun yet, so use node js to run.
|
|
11
|
+
// Note: Attempted migration to bun-pty but reverted due to GLIBC compatibility issues (requires GLIBC 2.39)
|
|
12
|
+
// bun-pty is not compatible with this environment, using node-pty instead
|
|
15
13
|
}
|
|
16
14
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Main function to run Claude with automatic yes/no responses
|
|
17
|
+
* @param options Configuration options
|
|
18
|
+
* @param options.continueOnCrash - If true, automatically restart Claude when it crashes:
|
|
19
|
+
* 1. Shows message 'Claude crashed, restarting..'
|
|
20
|
+
* 2. Spawns a new 'claude --continue' process
|
|
21
|
+
* 3. Re-attaches the new process to the shell stdio (pipes new process stdin/stdout)
|
|
22
|
+
* 4. If it crashes with "No conversation found to continue", exits the process
|
|
23
|
+
* @param options.exitOnIdle - Exit when Claude is idle. Boolean or timeout in milliseconds
|
|
24
|
+
* @param options.claudeArgs - Additional arguments to pass to the Claude CLI
|
|
25
|
+
*/
|
|
26
|
+
export default async function claudeYes({
|
|
27
|
+
continueOnCrash,
|
|
28
|
+
exitOnIdle,
|
|
29
|
+
claudeArgs = [],
|
|
30
|
+
}: {
|
|
31
|
+
continueOnCrash?: boolean;
|
|
32
|
+
exitOnIdle?: boolean | number;
|
|
33
|
+
claudeArgs?: string[];
|
|
34
|
+
} = {}) {
|
|
35
|
+
const defaultTimeout = 5e3; // 5 seconds idle timeout
|
|
36
|
+
const idleTimeout =
|
|
37
|
+
typeof exitOnIdle === "number" ? exitOnIdle : defaultTimeout;
|
|
38
|
+
|
|
39
|
+
console.log(
|
|
40
|
+
"⭐ Starting claude, automatically responding to yes/no prompts..."
|
|
41
|
+
);
|
|
42
|
+
console.log(
|
|
43
|
+
"⚠️ Important Security Warning: Only run this on trusted repositories. This tool automatically responds to prompts and can execute commands without user confirmation. Be aware of potential prompt injection attacks where malicious code or instructions could be embedded in files or user inputs to manipulate the automated responses."
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
process.stdin.setRawMode?.(true); //must be called any stdout/stdin usage
|
|
47
|
+
const prefix = ""; // "YESC|"
|
|
48
|
+
const PREFIXLENGTH = prefix.length;
|
|
49
|
+
let errorNoConversation = false; // match 'No conversation found to continue'
|
|
50
|
+
|
|
51
|
+
const shellOutputStream = new TransformStream<string, string>();
|
|
52
|
+
const outputWriter = shellOutputStream.writable.getWriter();
|
|
53
|
+
|
|
54
|
+
let shell = pty.spawn("claude", claudeArgs, {
|
|
55
|
+
name: "xterm-color", // use xterm color mode
|
|
56
|
+
cols: process.stdout.columns - PREFIXLENGTH,
|
|
57
|
+
rows: process.stdout.rows,
|
|
58
|
+
cwd: process.cwd(),
|
|
59
|
+
env: process.env as Record<string, string>,
|
|
60
|
+
});
|
|
61
|
+
// TODO handle error if claude is not installed, show msg:
|
|
62
|
+
// npm install -g @anthropic-ai/claude-code
|
|
63
|
+
|
|
64
|
+
async function onData(data: string) {
|
|
65
|
+
// append data to the buffer, so we can process it later
|
|
66
|
+
await outputWriter.write(data);
|
|
67
|
+
}
|
|
68
|
+
shell.onData(onData);
|
|
69
|
+
// when claude process exits, exit the main process with the same exit code
|
|
70
|
+
shell.onExit(function onExit({ exitCode }) {
|
|
71
|
+
if (continueOnCrash && exitCode !== 0) {
|
|
72
|
+
if (errorNoConversation) {
|
|
73
|
+
console.log(
|
|
74
|
+
'Claude crashed with "No conversation found to continue", exiting...'
|
|
75
|
+
);
|
|
76
|
+
void process.exit(exitCode);
|
|
77
|
+
}
|
|
78
|
+
console.log("Claude crashed, restarting...");
|
|
79
|
+
shell = pty.spawn("claude", ["continue", "--continue"], {
|
|
80
|
+
name: "xterm-color", // use xterm color mode
|
|
39
81
|
cols: process.stdout.columns - PREFIXLENGTH,
|
|
40
82
|
rows: process.stdout.rows,
|
|
41
83
|
cwd: process.cwd(),
|
|
42
|
-
env: process.env,
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
async function onData(data: string) {
|
|
48
|
-
// append data to the buffer, so we can process it later
|
|
49
|
-
await outputWriter.write(data);
|
|
84
|
+
env: process.env as Record<string, string>,
|
|
85
|
+
});
|
|
86
|
+
shell.onData(onData);
|
|
87
|
+
shell.onExit(onExit);
|
|
88
|
+
return;
|
|
50
89
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
90
|
+
void process.exit(exitCode);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
const exitClaudeCode = async () => {
|
|
94
|
+
// send exit command to the shell, must sleep a bit to avoid claude treat it as pasted input
|
|
95
|
+
await sflow(["\r", "/exit", "\r"])
|
|
96
|
+
.forEach(async (e) => {
|
|
97
|
+
await sleepms(200);
|
|
98
|
+
shell.write(e);
|
|
99
|
+
})
|
|
100
|
+
.run();
|
|
101
|
+
|
|
102
|
+
// wait for shell to exit or kill it with a timeout
|
|
103
|
+
let exited = false;
|
|
104
|
+
await Promise.race([
|
|
105
|
+
new Promise<void>((resolve) =>
|
|
106
|
+
shell.onExit(() => {
|
|
107
|
+
resolve();
|
|
108
|
+
exited = true;
|
|
109
|
+
})
|
|
110
|
+
), // resolve when shell exits
|
|
111
|
+
// if shell doesn't exit in 5 seconds, kill it
|
|
112
|
+
new Promise<void>((resolve) =>
|
|
113
|
+
setTimeout(() => {
|
|
114
|
+
if (exited) return; // if shell already exited, do nothing
|
|
115
|
+
shell.kill(); // kill the shell process if it doesn't exit in time
|
|
116
|
+
resolve();
|
|
117
|
+
}, 5000)
|
|
118
|
+
), // 5 seconds timeout
|
|
119
|
+
]);
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
// when current tty resized, resize the pty
|
|
123
|
+
process.stdout.on("resize", () => {
|
|
124
|
+
const { columns, rows } = process.stdout;
|
|
125
|
+
shell.resize(columns - PREFIXLENGTH, rows);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
const shellStdio = {
|
|
129
|
+
writable: new WritableStream<string>({
|
|
130
|
+
write: (data) => shell.write(data),
|
|
131
|
+
close: () => {},
|
|
132
|
+
}),
|
|
133
|
+
readable: shellOutputStream.readable,
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const idleWatcher = createIdleWatcher(async () => {
|
|
137
|
+
if (exitOnIdle) {
|
|
138
|
+
console.log("Claude is idle, exiting...");
|
|
139
|
+
await exitClaudeCode();
|
|
88
140
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
.
|
|
112
|
-
.
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
shell.write("\r")
|
|
119
|
-
}
|
|
120
|
-
})
|
|
121
|
-
.forEach(async e => {
|
|
122
|
-
if (e.match(/❯ 1. Dark mode✔|Press Enter to continue…/)) {
|
|
123
|
-
await sleepms(200)
|
|
124
|
-
shell.write("\r")
|
|
125
|
-
}
|
|
126
|
-
})
|
|
127
|
-
// .forEach(e => appendFile('.cache/io.log', "output|" + JSON.stringify(e) + '\n')) // for debugging
|
|
128
|
-
.run()
|
|
129
|
-
)
|
|
130
|
-
.replaceAll(/.*(?:\r\n?|\r?\n)/g, (line) => prefix + line) // add prefix
|
|
131
|
-
.forEach(() => idleWatcher.ping()) // ping the idle watcher on output for last active time to keep track of claude status
|
|
132
|
-
.map(e => !process.stdout.isTTY ? removeControlCharacters(e) : (e)) // remove control characters if output is not a TTY
|
|
133
|
-
.to(fromWritable(process.stdout));
|
|
141
|
+
}, idleTimeout);
|
|
142
|
+
const confirm = async () => {
|
|
143
|
+
await sleepms(200);
|
|
144
|
+
shell.write("\r");
|
|
145
|
+
};
|
|
146
|
+
await sflow(fromReadable<Buffer>(process.stdin))
|
|
147
|
+
.map((buffer) => buffer.toString())
|
|
148
|
+
// .forEach(e => appendFile('.cache/io.log', "input |" + JSON.stringify(e) + '\n')) // for debugging
|
|
149
|
+
.by(shellStdio)
|
|
150
|
+
.forkTo((e) =>
|
|
151
|
+
e
|
|
152
|
+
.map((e) => removeControlCharacters(e as string))
|
|
153
|
+
.map((e) => e.replaceAll("\r", "")) // remove carriage return
|
|
154
|
+
.forEach(async (e) => {
|
|
155
|
+
if (e.match(/❯ 1. Yes/)) return await confirm();
|
|
156
|
+
if (e.match(/❯ 1. Dark mode✔|Press Enter to continue…/))
|
|
157
|
+
return await confirm();
|
|
158
|
+
if (e.match(/No conversation found to continue/)) {
|
|
159
|
+
errorNoConversation = true; // set flag to true if error message is found
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
})
|
|
163
|
+
// .forEach(e => appendFile('.cache/io.log', "output|" + JSON.stringify(e) + '\n')) // for debugging
|
|
164
|
+
.run()
|
|
165
|
+
)
|
|
166
|
+
.replaceAll(/.*(?:\r\n?|\r?\n)/g, (line) => prefix + line) // add prefix
|
|
167
|
+
.forEach(() => idleWatcher.ping()) // ping the idle watcher on output for last active time to keep track of claude status
|
|
168
|
+
.map((e) => (!process.stdout.isTTY ? removeControlCharacters(e) : e)) // remove control characters if output is not a TTY
|
|
169
|
+
.to(fromWritable(process.stdout));
|
|
134
170
|
}
|
|
135
171
|
|
|
136
172
|
export { removeControlCharacters };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-yes",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.0",
|
|
4
4
|
"homepage": "https://github.com/snomiao/claude-yes#readme",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "snomiao <snomiao@gmail.com>",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"module": "index.ts",
|
|
61
61
|
"types": "./index.ts",
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"
|
|
63
|
+
"bun-pty": "^0.3.2"
|
|
64
64
|
},
|
|
65
65
|
"description": "A wrapper tool that automates interactions with the Claude CLI by automatically handling common prompts and responses.",
|
|
66
66
|
"main": "index.js",
|