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.
@@ -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 { appendFile, mkdir, rm, writeFile } from "fs/promises";
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
- /▌ > 1. Approve and run now/
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", "")).lines({ EOL: "NONE" }).forEach((e2) => yesLog`output|${e2}`).forEach(async (e2, i) => {
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: 'Claude CLI command, e.g. "claude,gemini,codex,cursor,copilot", default is "claude"'
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
- }).parserConfiguration({
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=FE903BBCCEA75D2B64756E2164756E21
352
+ //# debugId=6A393A6E0B85E4C764756E2164756E21
354
353
  //# sourceMappingURL=cli.js.map
@@ -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 { appendFile, mkdir, rm, writeFile } from "fs/promises";
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
- /▌ > 1. Approve and run now/
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", "")).lines({ EOL: "NONE" }).forEach((e2) => yesLog`output|${e2}`).forEach(async (e2, i) => {
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: 'Claude CLI command, e.g. "claude,gemini,codex,cursor,copilot", default is "claude"'
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
- }).parserConfiguration({
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=FE903BBCCEA75D2B64756E2164756E21
352
+ //# debugId=6A393A6E0B85E4C764756E2164756E21
354
353
  //# sourceMappingURL=cli.js.map
@@ -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 { appendFile, mkdir, rm, writeFile } from "fs/promises";
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
- /▌ > 1. Approve and run now/
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", "")).lines({ EOL: "NONE" }).forEach((e2) => yesLog`output|${e2}`).forEach(async (e2, i) => {
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: 'Claude CLI command, e.g. "claude,gemini,codex,cursor,copilot", default is "claude"'
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
- }).parserConfiguration({
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=FE903BBCCEA75D2B64756E2164756E21
352
+ //# debugId=6A393A6E0B85E4C764756E2164756E21
354
353
  //# sourceMappingURL=cli.js.map
package/dist/grok-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 { appendFile, mkdir, rm, writeFile } from "fs/promises";
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
- /▌ > 1. Approve and run now/
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", "")).lines({ EOL: "NONE" }).forEach((e2) => yesLog`output|${e2}`).forEach(async (e2, i) => {
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: 'Claude CLI command, e.g. "claude,gemini,codex,cursor,copilot", default is "claude"'
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
- }).parserConfiguration({
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=FE903BBCCEA75D2B64756E2164756E21
352
+ //# debugId=6A393A6E0B85E4C764756E2164756E21
354
353
  //# sourceMappingURL=cli.js.map
package/dist/index.js CHANGED
@@ -19,12 +19,11 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
19
19
 
20
20
  // index.ts
21
21
  import { fromReadable, fromWritable } from "from-node-stream";
22
- import { appendFile, mkdir, rm, writeFile } from "fs/promises";
22
+ import { mkdir, writeFile } from "fs/promises";
23
23
  import path from "path";
24
24
  import DIE from "phpdie";
25
25
  import sflow from "sflow";
26
26
  import { TerminalTextRender } from "terminal-render";
27
- import tsaComposer from "tsa-composer";
28
27
 
29
28
  // idleWaiter.ts
30
29
  class IdleWaiter {
@@ -95,7 +94,7 @@ var CLI_CONFIGURES = {
95
94
  ready: [/⏎ send/],
96
95
  enter: [
97
96
  /> 1. Yes, allow Codex to work in this folder/,
98
- /▌ > 1. Approve and run now/
97
+ /> 1. Approve and run now/
99
98
  ],
100
99
  fatal: [/Error: The cursor position could not be read within/],
101
100
  ensureArgs: (args) => {
@@ -130,11 +129,6 @@ async function claudeYes({
130
129
  removeControlCharactersFromStdout = false,
131
130
  verbose = false
132
131
  } = {}) {
133
- await rm("agent-yes.log").catch(() => null);
134
- const yesLog = tsaComposer()(async function yesLog(msg) {
135
- await appendFile("agent-yes.log", `${msg}
136
- `).catch(() => null);
137
- });
138
132
  const continueArgs = {
139
133
  codex: "resume --last".split(" "),
140
134
  claude: "--continue".split(" "),
@@ -143,6 +137,7 @@ async function claudeYes({
143
137
  process.stdin.setRawMode?.(true);
144
138
  let isFatal = false;
145
139
  const stdinReady = new ReadyManager;
140
+ const nextStdout = new ReadyManager;
146
141
  const shellOutputStream = new TransformStream;
147
142
  const outputWriter = shellOutputStream.writable.getWriter();
148
143
  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"));
@@ -164,10 +159,12 @@ async function claudeYes({
164
159
  const pendingExitCode = Promise.withResolvers();
165
160
  let pendingExitCodeValue = null;
166
161
  async function onData(data) {
162
+ nextStdout.ready();
167
163
  await outputWriter.write(data);
168
164
  }
169
165
  shell.onData(onData);
170
166
  shell.onExit(function onExit({ exitCode: exitCode2 }) {
167
+ nextStdout.ready();
171
168
  stdinReady.unready();
172
169
  const agentCrashed = exitCode2 !== 0;
173
170
  const continueArg = continueArgs[cli];
@@ -217,25 +214,25 @@ async function claudeYes({
217
214
  if (!text.includes("\x1B[6n"))
218
215
  return;
219
216
  const { col, row } = terminalRender.getCursorPosition();
220
- console.log(`[${cli}-yes] Responding cursor position: row=${row}, col=${col}`);
221
217
  shell.write(`\x1B[${row};${col}R`);
222
- }).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll("\r", "")).lines({ EOL: "NONE" }).forEach((e2) => yesLog`output|${e2}`).forEach(async (e2, i) => {
218
+ }).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll("\r", "")).by((s) => {
219
+ if (cli === "codex")
220
+ return s;
221
+ return s.lines({ EOL: "NONE" });
222
+ }).forEach(async (e2, i) => {
223
223
  const conf = CLI_CONFIGURES[cli] || null;
224
224
  if (!conf)
225
225
  return;
226
226
  if (conf.ready?.some((rx) => e2.match(rx))) {
227
- await yesLog`ready |${e2}`;
228
227
  if (cli === "gemini" && i <= 80)
229
228
  return;
230
229
  stdinReady.ready();
231
230
  }
232
231
  if (conf.enter?.some((rx) => e2.match(rx))) {
233
- await yesLog`enter |${e2}`;
234
232
  await sendEnter(300);
235
233
  return;
236
234
  }
237
235
  if (conf.fatal?.some((rx) => e2.match(rx))) {
238
- await yesLog`fatal |${e2}`;
239
236
  isFatal = true;
240
237
  await exitAgent();
241
238
  }
@@ -257,14 +254,14 @@ async function claudeYes({
257
254
  const st = Date.now();
258
255
  await idleWaiter.wait(waitms);
259
256
  const et = Date.now();
260
- await yesLog`sendEn| idleWaiter.wait(${String(waitms)}) took ${String(et - st)}ms`;
261
257
  shell.write("\r");
262
258
  }
263
259
  async function sendMessage(message) {
264
260
  await stdinReady.wait();
265
- await yesLog`send |${message}`;
266
261
  shell.write(message);
262
+ nextStdout.unready();
267
263
  idleWaiter.ping();
264
+ await nextStdout.wait();
268
265
  await sendEnter();
269
266
  }
270
267
  async function exitAgent() {
@@ -303,5 +300,5 @@ export {
303
300
  CLI_CONFIGURES
304
301
  };
305
302
 
306
- //# debugId=D97240F2071C1DE564756E2164756E21
303
+ //# debugId=D43B551F287C778F64756E2164756E21
307
304
  //# sourceMappingURL=index.js.map