claude-yes 1.23.1 → 1.23.3
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/cli.ts +5 -1
- package/dist/claude-yes.js +19 -20
- package/dist/cli.js +19 -20
- package/dist/cli.js.map +4 -4
- package/dist/codex-yes.js +19 -20
- package/dist/copilot-yes.js +19 -20
- package/dist/cursor-yes.js +19 -20
- package/dist/gemini-yes.js +19 -20
- package/dist/grok-yes.js +19 -20
- package/dist/index.js +13 -16
- package/dist/index.js.map +3 -3
- package/index.ts +22 -15
- package/package.json +1 -1
package/cli.ts
CHANGED
|
@@ -16,6 +16,7 @@ const argv = yargs(hideBin(process.argv))
|
|
|
16
16
|
default: true,
|
|
17
17
|
description:
|
|
18
18
|
'spawn Claude with --continue if it crashes, only works for claude',
|
|
19
|
+
alias: 'c',
|
|
19
20
|
})
|
|
20
21
|
.option('log-file', {
|
|
21
22
|
type: 'string',
|
|
@@ -24,7 +25,7 @@ const argv = yargs(hideBin(process.argv))
|
|
|
24
25
|
.option('cli', {
|
|
25
26
|
type: 'string',
|
|
26
27
|
description:
|
|
27
|
-
'
|
|
28
|
+
'CLI command to run. Supports: claude, gemini, codex, copilot, cursor, grok. Defaults to the CLI inferred from the executable name or "claude".',
|
|
28
29
|
})
|
|
29
30
|
.option('prompt', {
|
|
30
31
|
type: 'string',
|
|
@@ -39,7 +40,10 @@ const argv = yargs(hideBin(process.argv))
|
|
|
39
40
|
.option('exit-on-idle', {
|
|
40
41
|
type: 'string',
|
|
41
42
|
description: 'Exit after a period of inactivity, e.g., "5s" or "1m"',
|
|
43
|
+
alias: 'e',
|
|
42
44
|
})
|
|
45
|
+
.help()
|
|
46
|
+
.version()
|
|
43
47
|
.parserConfiguration({
|
|
44
48
|
'unknown-options-as-args': true,
|
|
45
49
|
'halt-at-non-option': true,
|
package/dist/claude-yes.js
CHANGED
|
@@ -25,12 +25,11 @@ import { hideBin } from "yargs/helpers";
|
|
|
25
25
|
|
|
26
26
|
// dist/index.js
|
|
27
27
|
import { fromReadable, fromWritable } from "from-node-stream";
|
|
28
|
-
import {
|
|
28
|
+
import { mkdir, writeFile } from "fs/promises";
|
|
29
29
|
import path from "path";
|
|
30
30
|
import DIE from "phpdie";
|
|
31
31
|
import sflow from "sflow";
|
|
32
32
|
import { TerminalTextRender } from "terminal-render";
|
|
33
|
-
import tsaComposer from "tsa-composer";
|
|
34
33
|
class IdleWaiter {
|
|
35
34
|
lastActivityTime = Date.now();
|
|
36
35
|
checkInterval = 100;
|
|
@@ -94,7 +93,7 @@ var CLI_CONFIGURES = {
|
|
|
94
93
|
ready: [/⏎ send/],
|
|
95
94
|
enter: [
|
|
96
95
|
/> 1. Yes, allow Codex to work in this folder/,
|
|
97
|
-
|
|
96
|
+
/> 1. Approve and run now/
|
|
98
97
|
],
|
|
99
98
|
fatal: [/Error: The cursor position could not be read within/],
|
|
100
99
|
ensureArgs: (args) => {
|
|
@@ -129,11 +128,6 @@ async function claudeYes({
|
|
|
129
128
|
removeControlCharactersFromStdout = false,
|
|
130
129
|
verbose = false
|
|
131
130
|
} = {}) {
|
|
132
|
-
await rm("agent-yes.log").catch(() => null);
|
|
133
|
-
const yesLog = tsaComposer()(async function yesLog(msg) {
|
|
134
|
-
await appendFile("agent-yes.log", `${msg}
|
|
135
|
-
`).catch(() => null);
|
|
136
|
-
});
|
|
137
131
|
const continueArgs = {
|
|
138
132
|
codex: "resume --last".split(" "),
|
|
139
133
|
claude: "--continue".split(" "),
|
|
@@ -142,6 +136,7 @@ async function claudeYes({
|
|
|
142
136
|
process.stdin.setRawMode?.(true);
|
|
143
137
|
let isFatal = false;
|
|
144
138
|
const stdinReady = new ReadyManager;
|
|
139
|
+
const nextStdout = new ReadyManager;
|
|
145
140
|
const shellOutputStream = new TransformStream;
|
|
146
141
|
const outputWriter = shellOutputStream.writable.getWriter();
|
|
147
142
|
const pty = await import("node-pty").catch(async () => await import("bun-pty")).catch(async () => DIE("Please install node-pty or bun-pty, run this: bun install bun-pty"));
|
|
@@ -163,10 +158,12 @@ async function claudeYes({
|
|
|
163
158
|
const pendingExitCode = Promise.withResolvers();
|
|
164
159
|
let pendingExitCodeValue = null;
|
|
165
160
|
async function onData(data) {
|
|
161
|
+
nextStdout.ready();
|
|
166
162
|
await outputWriter.write(data);
|
|
167
163
|
}
|
|
168
164
|
shell.onData(onData);
|
|
169
165
|
shell.onExit(function onExit({ exitCode: exitCode2 }) {
|
|
166
|
+
nextStdout.ready();
|
|
170
167
|
stdinReady.unready();
|
|
171
168
|
const agentCrashed = exitCode2 !== 0;
|
|
172
169
|
const continueArg = continueArgs[cli];
|
|
@@ -216,25 +213,25 @@ async function claudeYes({
|
|
|
216
213
|
if (!text.includes("\x1B[6n"))
|
|
217
214
|
return;
|
|
218
215
|
const { col, row } = terminalRender.getCursorPosition();
|
|
219
|
-
console.log(`[${cli}-yes] Responding cursor position: row=${row}, col=${col}`);
|
|
220
216
|
shell.write(`\x1B[${row};${col}R`);
|
|
221
|
-
}).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll("\r", "")).
|
|
217
|
+
}).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll("\r", "")).by((s) => {
|
|
218
|
+
if (cli === "codex")
|
|
219
|
+
return s;
|
|
220
|
+
return s.lines({ EOL: "NONE" });
|
|
221
|
+
}).forEach(async (e2, i) => {
|
|
222
222
|
const conf = CLI_CONFIGURES[cli] || null;
|
|
223
223
|
if (!conf)
|
|
224
224
|
return;
|
|
225
225
|
if (conf.ready?.some((rx) => e2.match(rx))) {
|
|
226
|
-
await yesLog`ready |${e2}`;
|
|
227
226
|
if (cli === "gemini" && i <= 80)
|
|
228
227
|
return;
|
|
229
228
|
stdinReady.ready();
|
|
230
229
|
}
|
|
231
230
|
if (conf.enter?.some((rx) => e2.match(rx))) {
|
|
232
|
-
await yesLog`enter |${e2}`;
|
|
233
231
|
await sendEnter(300);
|
|
234
232
|
return;
|
|
235
233
|
}
|
|
236
234
|
if (conf.fatal?.some((rx) => e2.match(rx))) {
|
|
237
|
-
await yesLog`fatal |${e2}`;
|
|
238
235
|
isFatal = true;
|
|
239
236
|
await exitAgent();
|
|
240
237
|
}
|
|
@@ -256,14 +253,14 @@ async function claudeYes({
|
|
|
256
253
|
const st = Date.now();
|
|
257
254
|
await idleWaiter.wait(waitms);
|
|
258
255
|
const et = Date.now();
|
|
259
|
-
await yesLog`sendEn| idleWaiter.wait(${String(waitms)}) took ${String(et - st)}ms`;
|
|
260
256
|
shell.write("\r");
|
|
261
257
|
}
|
|
262
258
|
async function sendMessage(message) {
|
|
263
259
|
await stdinReady.wait();
|
|
264
|
-
await yesLog`send |${message}`;
|
|
265
260
|
shell.write(message);
|
|
261
|
+
nextStdout.unready();
|
|
266
262
|
idleWaiter.ping();
|
|
263
|
+
await nextStdout.wait();
|
|
267
264
|
await sendEnter();
|
|
268
265
|
}
|
|
269
266
|
async function exitAgent() {
|
|
@@ -301,13 +298,14 @@ function tryCatch(fn, catchFn) {
|
|
|
301
298
|
var argv = yargs(hideBin(process.argv)).usage("Usage: $0 [options] [claude args] [--] [prompts...]").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("continue-on-crash", {
|
|
302
299
|
type: "boolean",
|
|
303
300
|
default: true,
|
|
304
|
-
description: "spawn Claude with --continue if it crashes, only works for claude"
|
|
301
|
+
description: "spawn Claude with --continue if it crashes, only works for claude",
|
|
302
|
+
alias: "c"
|
|
305
303
|
}).option("log-file", {
|
|
306
304
|
type: "string",
|
|
307
305
|
description: "Log file to write to"
|
|
308
306
|
}).option("cli", {
|
|
309
307
|
type: "string",
|
|
310
|
-
description: '
|
|
308
|
+
description: 'CLI command to run. Supports: claude, gemini, codex, copilot, cursor, grok. Defaults to the CLI inferred from the executable name or "claude".'
|
|
311
309
|
}).option("prompt", {
|
|
312
310
|
type: "string",
|
|
313
311
|
description: "Prompt to send to Claude",
|
|
@@ -318,8 +316,9 @@ var argv = yargs(hideBin(process.argv)).usage("Usage: $0 [options] [claude args]
|
|
|
318
316
|
default: false
|
|
319
317
|
}).option("exit-on-idle", {
|
|
320
318
|
type: "string",
|
|
321
|
-
description: 'Exit after a period of inactivity, e.g., "5s" or "1m"'
|
|
322
|
-
|
|
319
|
+
description: 'Exit after a period of inactivity, e.g., "5s" or "1m"',
|
|
320
|
+
alias: "e"
|
|
321
|
+
}).help().version().parserConfiguration({
|
|
323
322
|
"unknown-options-as-args": true,
|
|
324
323
|
"halt-at-non-option": true
|
|
325
324
|
}).parseSync();
|
|
@@ -350,5 +349,5 @@ var { exitCode, logs } = await claudeYes({
|
|
|
350
349
|
});
|
|
351
350
|
process.exit(exitCode ?? 1);
|
|
352
351
|
|
|
353
|
-
//# debugId=
|
|
352
|
+
//# debugId=6A393A6E0B85E4C764756E2164756E21
|
|
354
353
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js
CHANGED
|
@@ -25,12 +25,11 @@ import { hideBin } from "yargs/helpers";
|
|
|
25
25
|
|
|
26
26
|
// dist/index.js
|
|
27
27
|
import { fromReadable, fromWritable } from "from-node-stream";
|
|
28
|
-
import {
|
|
28
|
+
import { mkdir, writeFile } from "fs/promises";
|
|
29
29
|
import path from "path";
|
|
30
30
|
import DIE from "phpdie";
|
|
31
31
|
import sflow from "sflow";
|
|
32
32
|
import { TerminalTextRender } from "terminal-render";
|
|
33
|
-
import tsaComposer from "tsa-composer";
|
|
34
33
|
class IdleWaiter {
|
|
35
34
|
lastActivityTime = Date.now();
|
|
36
35
|
checkInterval = 100;
|
|
@@ -94,7 +93,7 @@ var CLI_CONFIGURES = {
|
|
|
94
93
|
ready: [/⏎ send/],
|
|
95
94
|
enter: [
|
|
96
95
|
/> 1. Yes, allow Codex to work in this folder/,
|
|
97
|
-
|
|
96
|
+
/> 1. Approve and run now/
|
|
98
97
|
],
|
|
99
98
|
fatal: [/Error: The cursor position could not be read within/],
|
|
100
99
|
ensureArgs: (args) => {
|
|
@@ -129,11 +128,6 @@ async function claudeYes({
|
|
|
129
128
|
removeControlCharactersFromStdout = false,
|
|
130
129
|
verbose = false
|
|
131
130
|
} = {}) {
|
|
132
|
-
await rm("agent-yes.log").catch(() => null);
|
|
133
|
-
const yesLog = tsaComposer()(async function yesLog(msg) {
|
|
134
|
-
await appendFile("agent-yes.log", `${msg}
|
|
135
|
-
`).catch(() => null);
|
|
136
|
-
});
|
|
137
131
|
const continueArgs = {
|
|
138
132
|
codex: "resume --last".split(" "),
|
|
139
133
|
claude: "--continue".split(" "),
|
|
@@ -142,6 +136,7 @@ async function claudeYes({
|
|
|
142
136
|
process.stdin.setRawMode?.(true);
|
|
143
137
|
let isFatal = false;
|
|
144
138
|
const stdinReady = new ReadyManager;
|
|
139
|
+
const nextStdout = new ReadyManager;
|
|
145
140
|
const shellOutputStream = new TransformStream;
|
|
146
141
|
const outputWriter = shellOutputStream.writable.getWriter();
|
|
147
142
|
const pty = await import("node-pty").catch(async () => await import("bun-pty")).catch(async () => DIE("Please install node-pty or bun-pty, run this: bun install bun-pty"));
|
|
@@ -163,10 +158,12 @@ async function claudeYes({
|
|
|
163
158
|
const pendingExitCode = Promise.withResolvers();
|
|
164
159
|
let pendingExitCodeValue = null;
|
|
165
160
|
async function onData(data) {
|
|
161
|
+
nextStdout.ready();
|
|
166
162
|
await outputWriter.write(data);
|
|
167
163
|
}
|
|
168
164
|
shell.onData(onData);
|
|
169
165
|
shell.onExit(function onExit({ exitCode: exitCode2 }) {
|
|
166
|
+
nextStdout.ready();
|
|
170
167
|
stdinReady.unready();
|
|
171
168
|
const agentCrashed = exitCode2 !== 0;
|
|
172
169
|
const continueArg = continueArgs[cli];
|
|
@@ -216,25 +213,25 @@ async function claudeYes({
|
|
|
216
213
|
if (!text.includes("\x1B[6n"))
|
|
217
214
|
return;
|
|
218
215
|
const { col, row } = terminalRender.getCursorPosition();
|
|
219
|
-
console.log(`[${cli}-yes] Responding cursor position: row=${row}, col=${col}`);
|
|
220
216
|
shell.write(`\x1B[${row};${col}R`);
|
|
221
|
-
}).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll("\r", "")).
|
|
217
|
+
}).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll("\r", "")).by((s) => {
|
|
218
|
+
if (cli === "codex")
|
|
219
|
+
return s;
|
|
220
|
+
return s.lines({ EOL: "NONE" });
|
|
221
|
+
}).forEach(async (e2, i) => {
|
|
222
222
|
const conf = CLI_CONFIGURES[cli] || null;
|
|
223
223
|
if (!conf)
|
|
224
224
|
return;
|
|
225
225
|
if (conf.ready?.some((rx) => e2.match(rx))) {
|
|
226
|
-
await yesLog`ready |${e2}`;
|
|
227
226
|
if (cli === "gemini" && i <= 80)
|
|
228
227
|
return;
|
|
229
228
|
stdinReady.ready();
|
|
230
229
|
}
|
|
231
230
|
if (conf.enter?.some((rx) => e2.match(rx))) {
|
|
232
|
-
await yesLog`enter |${e2}`;
|
|
233
231
|
await sendEnter(300);
|
|
234
232
|
return;
|
|
235
233
|
}
|
|
236
234
|
if (conf.fatal?.some((rx) => e2.match(rx))) {
|
|
237
|
-
await yesLog`fatal |${e2}`;
|
|
238
235
|
isFatal = true;
|
|
239
236
|
await exitAgent();
|
|
240
237
|
}
|
|
@@ -256,14 +253,14 @@ async function claudeYes({
|
|
|
256
253
|
const st = Date.now();
|
|
257
254
|
await idleWaiter.wait(waitms);
|
|
258
255
|
const et = Date.now();
|
|
259
|
-
await yesLog`sendEn| idleWaiter.wait(${String(waitms)}) took ${String(et - st)}ms`;
|
|
260
256
|
shell.write("\r");
|
|
261
257
|
}
|
|
262
258
|
async function sendMessage(message) {
|
|
263
259
|
await stdinReady.wait();
|
|
264
|
-
await yesLog`send |${message}`;
|
|
265
260
|
shell.write(message);
|
|
261
|
+
nextStdout.unready();
|
|
266
262
|
idleWaiter.ping();
|
|
263
|
+
await nextStdout.wait();
|
|
267
264
|
await sendEnter();
|
|
268
265
|
}
|
|
269
266
|
async function exitAgent() {
|
|
@@ -301,13 +298,14 @@ function tryCatch(fn, catchFn) {
|
|
|
301
298
|
var argv = yargs(hideBin(process.argv)).usage("Usage: $0 [options] [claude args] [--] [prompts...]").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("continue-on-crash", {
|
|
302
299
|
type: "boolean",
|
|
303
300
|
default: true,
|
|
304
|
-
description: "spawn Claude with --continue if it crashes, only works for claude"
|
|
301
|
+
description: "spawn Claude with --continue if it crashes, only works for claude",
|
|
302
|
+
alias: "c"
|
|
305
303
|
}).option("log-file", {
|
|
306
304
|
type: "string",
|
|
307
305
|
description: "Log file to write to"
|
|
308
306
|
}).option("cli", {
|
|
309
307
|
type: "string",
|
|
310
|
-
description: '
|
|
308
|
+
description: 'CLI command to run. Supports: claude, gemini, codex, copilot, cursor, grok. Defaults to the CLI inferred from the executable name or "claude".'
|
|
311
309
|
}).option("prompt", {
|
|
312
310
|
type: "string",
|
|
313
311
|
description: "Prompt to send to Claude",
|
|
@@ -318,8 +316,9 @@ var argv = yargs(hideBin(process.argv)).usage("Usage: $0 [options] [claude args]
|
|
|
318
316
|
default: false
|
|
319
317
|
}).option("exit-on-idle", {
|
|
320
318
|
type: "string",
|
|
321
|
-
description: 'Exit after a period of inactivity, e.g., "5s" or "1m"'
|
|
322
|
-
|
|
319
|
+
description: 'Exit after a period of inactivity, e.g., "5s" or "1m"',
|
|
320
|
+
alias: "e"
|
|
321
|
+
}).help().version().parserConfiguration({
|
|
323
322
|
"unknown-options-as-args": true,
|
|
324
323
|
"halt-at-non-option": true
|
|
325
324
|
}).parseSync();
|
|
@@ -350,5 +349,5 @@ var { exitCode, logs } = await claudeYes({
|
|
|
350
349
|
});
|
|
351
350
|
process.exit(exitCode ?? 1);
|
|
352
351
|
|
|
353
|
-
//# debugId=
|
|
352
|
+
//# debugId=6A393A6E0B85E4C764756E2164756E21
|
|
354
353
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../cli.ts", "index.js"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"#!/usr/bin/env node\nimport enhancedMs from 'enhanced-ms';\nimport yargs from 'yargs';\nimport { hideBin } from 'yargs/helpers';\nimport claudeYes from '.';\n\n// cli entry point\nconst argv = yargs(hideBin(process.argv))\n .usage('Usage: $0 [options] [claude args] [--] [prompts...]')\n .example(\n '$0 --exit-on-idle=30s --continue-on-crash \"help me solve all todos in my codebase\"',\n 'Run Claude with a 30 seconds idle timeout and continue on crash',\n )\n .option('continue-on-crash', {\n type: 'boolean',\n default: true,\n description:\n 'spawn Claude with --continue if it crashes, only works for claude',\n })\n .option('log-file', {\n type: 'string',\n description: 'Log file to write to',\n })\n .option('cli', {\n type: 'string',\n description:\n '
|
|
6
|
-
"import { createRequire } from \"node:module\";\nvar __create = Object.create;\nvar __getProtoOf = Object.getPrototypeOf;\nvar __defProp = Object.defineProperty;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __toESM = (mod, isNodeMode, target) => {\n target = mod != null ? __create(__getProtoOf(mod)) : {};\n const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, \"default\", { value: mod, enumerable: true }) : target;\n for (let key of __getOwnPropNames(mod))\n if (!__hasOwnProp.call(to, key))\n __defProp(to, key, {\n get: () => mod[key],\n enumerable: true\n });\n return to;\n};\nvar __require = /* @__PURE__ */ createRequire(import.meta.url);\n\n// index.ts\nimport { fromReadable, fromWritable } from \"from-node-stream\";\nimport { appendFile, mkdir, rm, writeFile } from \"fs/promises\";\nimport path from \"path\";\nimport DIE from \"phpdie\";\nimport sflow from \"sflow\";\nimport { TerminalTextRender } from \"terminal-render\";\nimport tsaComposer from \"tsa-composer\";\n\n// idleWaiter.ts\nclass IdleWaiter {\n lastActivityTime = Date.now();\n checkInterval = 100;\n constructor() {\n this.ping();\n }\n ping() {\n this.lastActivityTime = Date.now();\n return this;\n }\n async wait(ms) {\n while (this.lastActivityTime >= Date.now() - ms)\n await new Promise((resolve) => setTimeout(resolve, this.checkInterval));\n }\n}\n\n// ReadyManager.ts\nclass ReadyManager {\n isReady = false;\n readyQueue = [];\n wait() {\n if (this.isReady)\n return;\n return new Promise((resolve) => this.readyQueue.push(resolve));\n }\n unready() {\n this.isReady = false;\n }\n ready() {\n this.isReady = true;\n if (!this.readyQueue.length)\n return;\n this.readyQueue.splice(0).map((resolve) => resolve());\n }\n}\n\n// removeControlCharacters.ts\nfunction removeControlCharacters(str) {\n return str.replace(/[\\u001b\\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, \"\");\n}\n\n// index.ts\nvar CLI_CONFIGURES = {\n grok: {\n install: \"npm install -g @vibe-kit/grok-cli\",\n ready: [/^ │ ❯ /],\n enter: [/^ 1. Yes/]\n },\n claude: {\n install: \"npm install -g @anthropic-ai/claude-code\",\n ready: [/\\? for shortcuts/],\n enter: [/❯ 1. Yes/, /❯ 1. Dark mode✔/, /Press Enter to continue…/],\n fatal: [\n /No conversation found to continue/,\n /⎿ Claude usage limit reached\\./\n ]\n },\n gemini: {\n install: \"npm install -g @google/gemini-cli\",\n ready: [/Type your message/],\n enter: [/│ ● 1. Yes, allow once/],\n fatal: []\n },\n codex: {\n install: \"npm install -g @openai/codex-cli\",\n ready: [/⏎ send/],\n enter: [\n /> 1. Yes, allow Codex to work in this folder/,\n /▌ > 1. Approve and run now/\n ],\n fatal: [/Error: The cursor position could not be read within/],\n ensureArgs: (args) => {\n if (!args.includes(\"--search\"))\n return [\"--search\", ...args];\n return args;\n }\n },\n copilot: {\n install: \"npm install -g @github/copilot\",\n ready: [/^ > /],\n enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/],\n fatal: []\n },\n cursor: {\n install: \"open https://cursor.com/ja/docs/cli/installation\",\n binary: \"cursor-agent\",\n ready: [/\\/ commands/],\n enter: [/→ Run \\(once\\) \\(y\\) \\(enter\\)/, /▶ \\[a\\] Trust this workspace/],\n fatal: [/^ Error: You've hit your usage limit/]\n }\n};\nasync function claudeYes({\n cli = \"claude\",\n cliArgs = [],\n prompt,\n continueOnCrash,\n cwd,\n env,\n exitOnIdle,\n logFile,\n removeControlCharactersFromStdout = false,\n verbose = false\n} = {}) {\n await rm(\"agent-yes.log\").catch(() => null);\n const yesLog = tsaComposer()(async function yesLog(msg) {\n await appendFile(\"agent-yes.log\", `${msg}\n`).catch(() => null);\n });\n const continueArgs = {\n codex: \"resume --last\".split(\" \"),\n claude: \"--continue\".split(\" \"),\n gemini: []\n };\n process.stdin.setRawMode?.(true);\n let isFatal = false;\n const stdinReady = new ReadyManager;\n const shellOutputStream = new TransformStream;\n const outputWriter = shellOutputStream.writable.getWriter();\n const pty = await import(\"node-pty\").catch(async () => await import(\"bun-pty\")).catch(async () => DIE(\"Please install node-pty or bun-pty, run this: bun install bun-pty\"));\n const getPtyOptions = () => ({\n name: \"xterm-color\",\n ...getTerminalDimensions(),\n cwd: cwd ?? process.cwd(),\n env: env ?? process.env\n });\n const cliConf = CLI_CONFIGURES[cli] || {};\n cliArgs = cliConf.ensureArgs?.(cliArgs) ?? cliArgs;\n const cliCommand = cliConf?.binary || cli;\n let shell = tryCatch(() => pty.spawn(cliCommand, cliArgs, getPtyOptions()), (error) => {\n console.error(`Fatal: Failed to start ${cliCommand}.`);\n if (cliConf?.install)\n console.error(`If you did not installed it yet, Please install it first: ${cliConf.install}`);\n throw error;\n });\n const pendingExitCode = Promise.withResolvers();\n let pendingExitCodeValue = null;\n async function onData(data) {\n await outputWriter.write(data);\n }\n shell.onData(onData);\n shell.onExit(function onExit({ exitCode: exitCode2 }) {\n stdinReady.unready();\n const agentCrashed = exitCode2 !== 0;\n const continueArg = continueArgs[cli];\n if (agentCrashed && continueOnCrash && continueArg) {\n if (!continueArg) {\n return console.warn(`continueOnCrash is only supported for ${Object.keys(continueArgs).join(\", \")} currently, not ${cli}`);\n }\n if (isFatal) {\n return pendingExitCode.resolve(pendingExitCodeValue = exitCode2);\n }\n console.log(`${cli} crashed, restarting...`);\n shell = pty.spawn(cli, continueArg, getPtyOptions());\n shell.onData(onData);\n shell.onExit(onExit);\n return;\n }\n return pendingExitCode.resolve(pendingExitCodeValue = exitCode2);\n });\n process.stdout.on(\"resize\", () => {\n const { cols, rows } = getTerminalDimensions();\n shell.resize(cols, rows);\n });\n const terminalRender = new TerminalTextRender;\n const isStillWorkingQ = () => terminalRender.render().replace(/\\s+/g, \" \").match(/esc to interrupt|to run in background/);\n const idleWaiter = new IdleWaiter;\n if (exitOnIdle)\n idleWaiter.wait(exitOnIdle).then(async () => {\n if (isStillWorkingQ()) {\n console.log(\"[${cli}-yes] ${cli} is idle, but seems still working, not exiting yet\");\n return;\n }\n console.log(\"[${cli}-yes] ${cli} is idle, exiting...\");\n await exitAgent();\n });\n sflow(fromReadable(process.stdin)).map((buffer) => buffer.toString()).by({\n writable: new WritableStream({\n write: async (data) => {\n await stdinReady.wait();\n shell.write(data);\n }\n }),\n readable: shellOutputStream.readable\n }).forEach(() => idleWaiter.ping()).forEach((text) => {\n terminalRender.write(text);\n if (process.stdin.isTTY)\n return;\n if (!text.includes(\"\\x1B[6n\"))\n return;\n const { col, row } = terminalRender.getCursorPosition();\n console.log(`[${cli}-yes] Responding cursor position: row=${row}, col=${col}`);\n shell.write(`\\x1B[${row};${col}R`);\n }).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll(\"\\r\", \"\")).lines({ EOL: \"NONE\" }).forEach((e2) => yesLog`output|${e2}`).forEach(async (e2, i) => {\n const conf = CLI_CONFIGURES[cli] || null;\n if (!conf)\n return;\n if (conf.ready?.some((rx) => e2.match(rx))) {\n await yesLog`ready |${e2}`;\n if (cli === \"gemini\" && i <= 80)\n return;\n stdinReady.ready();\n }\n if (conf.enter?.some((rx) => e2.match(rx))) {\n await yesLog`enter |${e2}`;\n await sendEnter(300);\n return;\n }\n if (conf.fatal?.some((rx) => e2.match(rx))) {\n await yesLog`fatal |${e2}`;\n isFatal = true;\n await exitAgent();\n }\n }).run()).map((e) => removeControlCharactersFromStdout ? removeControlCharacters(e) : e).to(fromWritable(process.stdout)).then(() => null);\n if (cli === \"codex\")\n shell.write(`\\x1B[1;1R`);\n if (prompt)\n await sendMessage(prompt);\n const exitCode = await pendingExitCode.promise;\n console.log(`[${cli}-yes] ${cli} exited with code ${exitCode}`);\n if (logFile) {\n verbose && console.log(`[${cli}-yes] Writing rendered logs to ${logFile}`);\n const logFilePath = path.resolve(logFile);\n await mkdir(path.dirname(logFilePath), { recursive: true }).catch(() => null);\n await writeFile(logFilePath, terminalRender.render());\n }\n return { exitCode, logs: terminalRender.render() };\n async function sendEnter(waitms = 1000) {\n const st = Date.now();\n await idleWaiter.wait(waitms);\n const et = Date.now();\n await yesLog`sendEn| idleWaiter.wait(${String(waitms)}) took ${String(et - st)}ms`;\n shell.write(\"\\r\");\n }\n async function sendMessage(message) {\n await stdinReady.wait();\n await yesLog`send |${message}`;\n shell.write(message);\n idleWaiter.ping();\n await sendEnter();\n }\n async function exitAgent() {\n continueOnCrash = false;\n await sendMessage(\"/exit\");\n let exited = false;\n await Promise.race([\n pendingExitCode.promise.then(() => exited = true),\n new Promise((resolve) => setTimeout(() => {\n if (exited)\n return;\n shell.kill();\n resolve();\n }, 5000))\n ]);\n }\n function getTerminalDimensions() {\n if (!process.stdout.isTTY)\n return { cols: 80, rows: 30 };\n return {\n cols: Math.min(Math.max(20, process.stdout.columns), 80),\n rows: process.stdout.rows\n };\n }\n}\nfunction tryCatch(fn, catchFn) {\n try {\n return fn();\n } catch (error) {\n return catchFn(error);\n }\n}\nexport {\n removeControlCharacters,\n claudeYes as default,\n CLI_CONFIGURES\n};\n\n//# debugId=D97240F2071C1DE564756E2164756E21\n//# sourceMappingURL=index.js.map\n"
|
|
5
|
+
"#!/usr/bin/env node\nimport enhancedMs from 'enhanced-ms';\nimport yargs from 'yargs';\nimport { hideBin } from 'yargs/helpers';\nimport claudeYes from '.';\n\n// cli entry point\nconst argv = yargs(hideBin(process.argv))\n .usage('Usage: $0 [options] [claude args] [--] [prompts...]')\n .example(\n '$0 --exit-on-idle=30s --continue-on-crash \"help me solve all todos in my codebase\"',\n 'Run Claude with a 30 seconds idle timeout and continue on crash',\n )\n .option('continue-on-crash', {\n type: 'boolean',\n default: true,\n description:\n 'spawn Claude with --continue if it crashes, only works for claude',\n alias: 'c',\n })\n .option('log-file', {\n type: 'string',\n description: 'Log file to write to',\n })\n .option('cli', {\n type: 'string',\n description:\n 'CLI command to run. Supports: claude, gemini, codex, copilot, cursor, grok. Defaults to the CLI inferred from the executable name or \"claude\".',\n })\n .option('prompt', {\n type: 'string',\n description: 'Prompt to send to Claude',\n alias: 'p',\n })\n .option('verbose', {\n type: 'boolean',\n description: 'Enable verbose logging',\n default: false,\n })\n .option('exit-on-idle', {\n type: 'string',\n description: 'Exit after a period of inactivity, e.g., \"5s\" or \"1m\"',\n alias: 'e',\n })\n .help()\n .version()\n .parserConfiguration({\n 'unknown-options-as-args': true,\n 'halt-at-non-option': true,\n })\n .parseSync();\n\n// detect cli name for cli, while package.json have multiple bin link: {\"claude-yes\": \"cli.js\", \"codex-yes\": \"cli.js\", \"gemini-yes\": \"cli.js\"}\nif (!argv.cli) {\n const cliName = process.argv[1]?.split('/').pop()?.split('-')[0];\n argv.cli = cliName || 'claude';\n}\n\n// Support: everything after a literal `--` is a prompt string. Example:\n// claude-yes --exit-on-idle=30s -- \"help me refactor this\"\n// In that example the prompt will be `help me refactor this` and won't be\n// passed as args to the underlying CLI binary.\nconst rawArgs = process.argv.slice(2);\nconst dashIndex = rawArgs.indexOf('--');\nlet promptFromDash: string | undefined = undefined;\nlet cliArgsForSpawn: string[] = [];\nif (dashIndex !== -1) {\n // join everything after `--` into a single prompt string\n const after = rawArgs.slice(dashIndex + 1);\n promptFromDash = after.join(' ');\n // use everything before `--` as the cli args\n cliArgsForSpawn = rawArgs.slice(0, dashIndex).map(String);\n} else {\n // fallback to yargs parsed positional args when `--` is not used\n cliArgsForSpawn = argv._.map((e) => String(e));\n}\n\nconsole.clear();\nconst { exitCode, logs } = await claudeYes({\n cli: argv.cli,\n // prefer explicit --prompt / -p; otherwise use the text after `--` if present\n prompt: argv.prompt || promptFromDash,\n exitOnIdle: argv.exitOnIdle ? enhancedMs(argv.exitOnIdle) : undefined,\n cliArgs: cliArgsForSpawn,\n continueOnCrash: argv.continueOnCrash,\n logFile: argv.logFile,\n verbose: argv.verbose,\n});\n\nprocess.exit(exitCode ?? 1);\n",
|
|
6
|
+
"import { createRequire } from \"node:module\";\nvar __create = Object.create;\nvar __getProtoOf = Object.getPrototypeOf;\nvar __defProp = Object.defineProperty;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __toESM = (mod, isNodeMode, target) => {\n target = mod != null ? __create(__getProtoOf(mod)) : {};\n const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, \"default\", { value: mod, enumerable: true }) : target;\n for (let key of __getOwnPropNames(mod))\n if (!__hasOwnProp.call(to, key))\n __defProp(to, key, {\n get: () => mod[key],\n enumerable: true\n });\n return to;\n};\nvar __require = /* @__PURE__ */ createRequire(import.meta.url);\n\n// index.ts\nimport { fromReadable, fromWritable } from \"from-node-stream\";\nimport { mkdir, writeFile } from \"fs/promises\";\nimport path from \"path\";\nimport DIE from \"phpdie\";\nimport sflow from \"sflow\";\nimport { TerminalTextRender } from \"terminal-render\";\n\n// idleWaiter.ts\nclass IdleWaiter {\n lastActivityTime = Date.now();\n checkInterval = 100;\n constructor() {\n this.ping();\n }\n ping() {\n this.lastActivityTime = Date.now();\n return this;\n }\n async wait(ms) {\n while (this.lastActivityTime >= Date.now() - ms)\n await new Promise((resolve) => setTimeout(resolve, this.checkInterval));\n }\n}\n\n// ReadyManager.ts\nclass ReadyManager {\n isReady = false;\n readyQueue = [];\n wait() {\n if (this.isReady)\n return;\n return new Promise((resolve) => this.readyQueue.push(resolve));\n }\n unready() {\n this.isReady = false;\n }\n ready() {\n this.isReady = true;\n if (!this.readyQueue.length)\n return;\n this.readyQueue.splice(0).map((resolve) => resolve());\n }\n}\n\n// removeControlCharacters.ts\nfunction removeControlCharacters(str) {\n return str.replace(/[\\u001b\\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, \"\");\n}\n\n// index.ts\nvar CLI_CONFIGURES = {\n grok: {\n install: \"npm install -g @vibe-kit/grok-cli\",\n ready: [/^ │ ❯ /],\n enter: [/^ 1. Yes/]\n },\n claude: {\n install: \"npm install -g @anthropic-ai/claude-code\",\n ready: [/\\? for shortcuts/],\n enter: [/❯ 1. Yes/, /❯ 1. Dark mode✔/, /Press Enter to continue…/],\n fatal: [\n /No conversation found to continue/,\n /⎿ Claude usage limit reached\\./\n ]\n },\n gemini: {\n install: \"npm install -g @google/gemini-cli\",\n ready: [/Type your message/],\n enter: [/│ ● 1. Yes, allow once/],\n fatal: []\n },\n codex: {\n install: \"npm install -g @openai/codex-cli\",\n ready: [/⏎ send/],\n enter: [\n /> 1. Yes, allow Codex to work in this folder/,\n /> 1. Approve and run now/\n ],\n fatal: [/Error: The cursor position could not be read within/],\n ensureArgs: (args) => {\n if (!args.includes(\"--search\"))\n return [\"--search\", ...args];\n return args;\n }\n },\n copilot: {\n install: \"npm install -g @github/copilot\",\n ready: [/^ > /],\n enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/],\n fatal: []\n },\n cursor: {\n install: \"open https://cursor.com/ja/docs/cli/installation\",\n binary: \"cursor-agent\",\n ready: [/\\/ commands/],\n enter: [/→ Run \\(once\\) \\(y\\) \\(enter\\)/, /▶ \\[a\\] Trust this workspace/],\n fatal: [/^ Error: You've hit your usage limit/]\n }\n};\nasync function claudeYes({\n cli = \"claude\",\n cliArgs = [],\n prompt,\n continueOnCrash,\n cwd,\n env,\n exitOnIdle,\n logFile,\n removeControlCharactersFromStdout = false,\n verbose = false\n} = {}) {\n const continueArgs = {\n codex: \"resume --last\".split(\" \"),\n claude: \"--continue\".split(\" \"),\n gemini: []\n };\n process.stdin.setRawMode?.(true);\n let isFatal = false;\n const stdinReady = new ReadyManager;\n const nextStdout = new ReadyManager;\n const shellOutputStream = new TransformStream;\n const outputWriter = shellOutputStream.writable.getWriter();\n const pty = await import(\"node-pty\").catch(async () => await import(\"bun-pty\")).catch(async () => DIE(\"Please install node-pty or bun-pty, run this: bun install bun-pty\"));\n const getPtyOptions = () => ({\n name: \"xterm-color\",\n ...getTerminalDimensions(),\n cwd: cwd ?? process.cwd(),\n env: env ?? process.env\n });\n const cliConf = CLI_CONFIGURES[cli] || {};\n cliArgs = cliConf.ensureArgs?.(cliArgs) ?? cliArgs;\n const cliCommand = cliConf?.binary || cli;\n let shell = tryCatch(() => pty.spawn(cliCommand, cliArgs, getPtyOptions()), (error) => {\n console.error(`Fatal: Failed to start ${cliCommand}.`);\n if (cliConf?.install)\n console.error(`If you did not installed it yet, Please install it first: ${cliConf.install}`);\n throw error;\n });\n const pendingExitCode = Promise.withResolvers();\n let pendingExitCodeValue = null;\n async function onData(data) {\n nextStdout.ready();\n await outputWriter.write(data);\n }\n shell.onData(onData);\n shell.onExit(function onExit({ exitCode: exitCode2 }) {\n nextStdout.ready();\n stdinReady.unready();\n const agentCrashed = exitCode2 !== 0;\n const continueArg = continueArgs[cli];\n if (agentCrashed && continueOnCrash && continueArg) {\n if (!continueArg) {\n return console.warn(`continueOnCrash is only supported for ${Object.keys(continueArgs).join(\", \")} currently, not ${cli}`);\n }\n if (isFatal) {\n return pendingExitCode.resolve(pendingExitCodeValue = exitCode2);\n }\n console.log(`${cli} crashed, restarting...`);\n shell = pty.spawn(cli, continueArg, getPtyOptions());\n shell.onData(onData);\n shell.onExit(onExit);\n return;\n }\n return pendingExitCode.resolve(pendingExitCodeValue = exitCode2);\n });\n process.stdout.on(\"resize\", () => {\n const { cols, rows } = getTerminalDimensions();\n shell.resize(cols, rows);\n });\n const terminalRender = new TerminalTextRender;\n const isStillWorkingQ = () => terminalRender.render().replace(/\\s+/g, \" \").match(/esc to interrupt|to run in background/);\n const idleWaiter = new IdleWaiter;\n if (exitOnIdle)\n idleWaiter.wait(exitOnIdle).then(async () => {\n if (isStillWorkingQ()) {\n console.log(\"[${cli}-yes] ${cli} is idle, but seems still working, not exiting yet\");\n return;\n }\n console.log(\"[${cli}-yes] ${cli} is idle, exiting...\");\n await exitAgent();\n });\n sflow(fromReadable(process.stdin)).map((buffer) => buffer.toString()).by({\n writable: new WritableStream({\n write: async (data) => {\n await stdinReady.wait();\n shell.write(data);\n }\n }),\n readable: shellOutputStream.readable\n }).forEach(() => idleWaiter.ping()).forEach((text) => {\n terminalRender.write(text);\n if (process.stdin.isTTY)\n return;\n if (!text.includes(\"\\x1B[6n\"))\n return;\n const { col, row } = terminalRender.getCursorPosition();\n shell.write(`\\x1B[${row};${col}R`);\n }).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll(\"\\r\", \"\")).by((s) => {\n if (cli === \"codex\")\n return s;\n return s.lines({ EOL: \"NONE\" });\n }).forEach(async (e2, i) => {\n const conf = CLI_CONFIGURES[cli] || null;\n if (!conf)\n return;\n if (conf.ready?.some((rx) => e2.match(rx))) {\n if (cli === \"gemini\" && i <= 80)\n return;\n stdinReady.ready();\n }\n if (conf.enter?.some((rx) => e2.match(rx))) {\n await sendEnter(300);\n return;\n }\n if (conf.fatal?.some((rx) => e2.match(rx))) {\n isFatal = true;\n await exitAgent();\n }\n }).run()).map((e) => removeControlCharactersFromStdout ? removeControlCharacters(e) : e).to(fromWritable(process.stdout)).then(() => null);\n if (cli === \"codex\")\n shell.write(`\\x1B[1;1R`);\n if (prompt)\n await sendMessage(prompt);\n const exitCode = await pendingExitCode.promise;\n console.log(`[${cli}-yes] ${cli} exited with code ${exitCode}`);\n if (logFile) {\n verbose && console.log(`[${cli}-yes] Writing rendered logs to ${logFile}`);\n const logFilePath = path.resolve(logFile);\n await mkdir(path.dirname(logFilePath), { recursive: true }).catch(() => null);\n await writeFile(logFilePath, terminalRender.render());\n }\n return { exitCode, logs: terminalRender.render() };\n async function sendEnter(waitms = 1000) {\n const st = Date.now();\n await idleWaiter.wait(waitms);\n const et = Date.now();\n shell.write(\"\\r\");\n }\n async function sendMessage(message) {\n await stdinReady.wait();\n shell.write(message);\n nextStdout.unready();\n idleWaiter.ping();\n await nextStdout.wait();\n await sendEnter();\n }\n async function exitAgent() {\n continueOnCrash = false;\n await sendMessage(\"/exit\");\n let exited = false;\n await Promise.race([\n pendingExitCode.promise.then(() => exited = true),\n new Promise((resolve) => setTimeout(() => {\n if (exited)\n return;\n shell.kill();\n resolve();\n }, 5000))\n ]);\n }\n function getTerminalDimensions() {\n if (!process.stdout.isTTY)\n return { cols: 80, rows: 30 };\n return {\n cols: Math.min(Math.max(20, process.stdout.columns), 80),\n rows: process.stdout.rows\n };\n }\n}\nfunction tryCatch(fn, catchFn) {\n try {\n return fn();\n } catch (error) {\n return catchFn(error);\n }\n}\nexport {\n removeControlCharacters,\n claudeYes as default,\n CLI_CONFIGURES\n};\n\n//# debugId=D43B551F287C778F64756E2164756E21\n//# sourceMappingURL=index.js.map\n"
|
|
7
7
|
],
|
|
8
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;AACA;AACA;AACA;;;ACiBA;AACA;AACA;AACA;AACA;AACA;
|
|
9
|
-
"debugId": "
|
|
8
|
+
"mappings": "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",
|
|
9
|
+
"debugId": "6A393A6E0B85E4C764756E2164756E21",
|
|
10
10
|
"names": []
|
|
11
11
|
}
|
package/dist/codex-yes.js
CHANGED
|
@@ -25,12 +25,11 @@ import { hideBin } from "yargs/helpers";
|
|
|
25
25
|
|
|
26
26
|
// dist/index.js
|
|
27
27
|
import { fromReadable, fromWritable } from "from-node-stream";
|
|
28
|
-
import {
|
|
28
|
+
import { mkdir, writeFile } from "fs/promises";
|
|
29
29
|
import path from "path";
|
|
30
30
|
import DIE from "phpdie";
|
|
31
31
|
import sflow from "sflow";
|
|
32
32
|
import { TerminalTextRender } from "terminal-render";
|
|
33
|
-
import tsaComposer from "tsa-composer";
|
|
34
33
|
class IdleWaiter {
|
|
35
34
|
lastActivityTime = Date.now();
|
|
36
35
|
checkInterval = 100;
|
|
@@ -94,7 +93,7 @@ var CLI_CONFIGURES = {
|
|
|
94
93
|
ready: [/⏎ send/],
|
|
95
94
|
enter: [
|
|
96
95
|
/> 1. Yes, allow Codex to work in this folder/,
|
|
97
|
-
|
|
96
|
+
/> 1. Approve and run now/
|
|
98
97
|
],
|
|
99
98
|
fatal: [/Error: The cursor position could not be read within/],
|
|
100
99
|
ensureArgs: (args) => {
|
|
@@ -129,11 +128,6 @@ async function claudeYes({
|
|
|
129
128
|
removeControlCharactersFromStdout = false,
|
|
130
129
|
verbose = false
|
|
131
130
|
} = {}) {
|
|
132
|
-
await rm("agent-yes.log").catch(() => null);
|
|
133
|
-
const yesLog = tsaComposer()(async function yesLog(msg) {
|
|
134
|
-
await appendFile("agent-yes.log", `${msg}
|
|
135
|
-
`).catch(() => null);
|
|
136
|
-
});
|
|
137
131
|
const continueArgs = {
|
|
138
132
|
codex: "resume --last".split(" "),
|
|
139
133
|
claude: "--continue".split(" "),
|
|
@@ -142,6 +136,7 @@ async function claudeYes({
|
|
|
142
136
|
process.stdin.setRawMode?.(true);
|
|
143
137
|
let isFatal = false;
|
|
144
138
|
const stdinReady = new ReadyManager;
|
|
139
|
+
const nextStdout = new ReadyManager;
|
|
145
140
|
const shellOutputStream = new TransformStream;
|
|
146
141
|
const outputWriter = shellOutputStream.writable.getWriter();
|
|
147
142
|
const pty = await import("node-pty").catch(async () => await import("bun-pty")).catch(async () => DIE("Please install node-pty or bun-pty, run this: bun install bun-pty"));
|
|
@@ -163,10 +158,12 @@ async function claudeYes({
|
|
|
163
158
|
const pendingExitCode = Promise.withResolvers();
|
|
164
159
|
let pendingExitCodeValue = null;
|
|
165
160
|
async function onData(data) {
|
|
161
|
+
nextStdout.ready();
|
|
166
162
|
await outputWriter.write(data);
|
|
167
163
|
}
|
|
168
164
|
shell.onData(onData);
|
|
169
165
|
shell.onExit(function onExit({ exitCode: exitCode2 }) {
|
|
166
|
+
nextStdout.ready();
|
|
170
167
|
stdinReady.unready();
|
|
171
168
|
const agentCrashed = exitCode2 !== 0;
|
|
172
169
|
const continueArg = continueArgs[cli];
|
|
@@ -216,25 +213,25 @@ async function claudeYes({
|
|
|
216
213
|
if (!text.includes("\x1B[6n"))
|
|
217
214
|
return;
|
|
218
215
|
const { col, row } = terminalRender.getCursorPosition();
|
|
219
|
-
console.log(`[${cli}-yes] Responding cursor position: row=${row}, col=${col}`);
|
|
220
216
|
shell.write(`\x1B[${row};${col}R`);
|
|
221
|
-
}).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll("\r", "")).
|
|
217
|
+
}).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll("\r", "")).by((s) => {
|
|
218
|
+
if (cli === "codex")
|
|
219
|
+
return s;
|
|
220
|
+
return s.lines({ EOL: "NONE" });
|
|
221
|
+
}).forEach(async (e2, i) => {
|
|
222
222
|
const conf = CLI_CONFIGURES[cli] || null;
|
|
223
223
|
if (!conf)
|
|
224
224
|
return;
|
|
225
225
|
if (conf.ready?.some((rx) => e2.match(rx))) {
|
|
226
|
-
await yesLog`ready |${e2}`;
|
|
227
226
|
if (cli === "gemini" && i <= 80)
|
|
228
227
|
return;
|
|
229
228
|
stdinReady.ready();
|
|
230
229
|
}
|
|
231
230
|
if (conf.enter?.some((rx) => e2.match(rx))) {
|
|
232
|
-
await yesLog`enter |${e2}`;
|
|
233
231
|
await sendEnter(300);
|
|
234
232
|
return;
|
|
235
233
|
}
|
|
236
234
|
if (conf.fatal?.some((rx) => e2.match(rx))) {
|
|
237
|
-
await yesLog`fatal |${e2}`;
|
|
238
235
|
isFatal = true;
|
|
239
236
|
await exitAgent();
|
|
240
237
|
}
|
|
@@ -256,14 +253,14 @@ async function claudeYes({
|
|
|
256
253
|
const st = Date.now();
|
|
257
254
|
await idleWaiter.wait(waitms);
|
|
258
255
|
const et = Date.now();
|
|
259
|
-
await yesLog`sendEn| idleWaiter.wait(${String(waitms)}) took ${String(et - st)}ms`;
|
|
260
256
|
shell.write("\r");
|
|
261
257
|
}
|
|
262
258
|
async function sendMessage(message) {
|
|
263
259
|
await stdinReady.wait();
|
|
264
|
-
await yesLog`send |${message}`;
|
|
265
260
|
shell.write(message);
|
|
261
|
+
nextStdout.unready();
|
|
266
262
|
idleWaiter.ping();
|
|
263
|
+
await nextStdout.wait();
|
|
267
264
|
await sendEnter();
|
|
268
265
|
}
|
|
269
266
|
async function exitAgent() {
|
|
@@ -301,13 +298,14 @@ function tryCatch(fn, catchFn) {
|
|
|
301
298
|
var argv = yargs(hideBin(process.argv)).usage("Usage: $0 [options] [claude args] [--] [prompts...]").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("continue-on-crash", {
|
|
302
299
|
type: "boolean",
|
|
303
300
|
default: true,
|
|
304
|
-
description: "spawn Claude with --continue if it crashes, only works for claude"
|
|
301
|
+
description: "spawn Claude with --continue if it crashes, only works for claude",
|
|
302
|
+
alias: "c"
|
|
305
303
|
}).option("log-file", {
|
|
306
304
|
type: "string",
|
|
307
305
|
description: "Log file to write to"
|
|
308
306
|
}).option("cli", {
|
|
309
307
|
type: "string",
|
|
310
|
-
description: '
|
|
308
|
+
description: 'CLI command to run. Supports: claude, gemini, codex, copilot, cursor, grok. Defaults to the CLI inferred from the executable name or "claude".'
|
|
311
309
|
}).option("prompt", {
|
|
312
310
|
type: "string",
|
|
313
311
|
description: "Prompt to send to Claude",
|
|
@@ -318,8 +316,9 @@ var argv = yargs(hideBin(process.argv)).usage("Usage: $0 [options] [claude args]
|
|
|
318
316
|
default: false
|
|
319
317
|
}).option("exit-on-idle", {
|
|
320
318
|
type: "string",
|
|
321
|
-
description: 'Exit after a period of inactivity, e.g., "5s" or "1m"'
|
|
322
|
-
|
|
319
|
+
description: 'Exit after a period of inactivity, e.g., "5s" or "1m"',
|
|
320
|
+
alias: "e"
|
|
321
|
+
}).help().version().parserConfiguration({
|
|
323
322
|
"unknown-options-as-args": true,
|
|
324
323
|
"halt-at-non-option": true
|
|
325
324
|
}).parseSync();
|
|
@@ -350,5 +349,5 @@ var { exitCode, logs } = await claudeYes({
|
|
|
350
349
|
});
|
|
351
350
|
process.exit(exitCode ?? 1);
|
|
352
351
|
|
|
353
|
-
//# debugId=
|
|
352
|
+
//# debugId=6A393A6E0B85E4C764756E2164756E21
|
|
354
353
|
//# sourceMappingURL=cli.js.map
|