claude-yes 1.20.0 → 1.21.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.
@@ -68,8 +68,13 @@ function removeControlCharacters(str) {
68
68
  return str.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, "");
69
69
  }
70
70
  var CLI_CONFIGURES = {
71
+ grok: {
72
+ install: "npm install -g @vibe-kit/grok-cli",
73
+ ready: [/^ +│ ❯ /]
74
+ },
71
75
  claude: {
72
- ready: /^> /,
76
+ install: "npm install -g @anthropic-ai/claude-code",
77
+ ready: [/^> /],
73
78
  enter: [/❯ 1. Yes/, /❯ 1. Dark mode✔/, /Press Enter to continue…/],
74
79
  fatal: [
75
80
  /No conversation found to continue/,
@@ -77,12 +82,14 @@ var CLI_CONFIGURES = {
77
82
  ]
78
83
  },
79
84
  gemini: {
80
- ready: /Type your message/,
85
+ install: "npm install -g @google/gemini-cli",
86
+ ready: [/Type your message/],
81
87
  enter: [/│ ● 1. Yes, allow once/],
82
88
  fatal: []
83
89
  },
84
90
  codex: {
85
- ready: /⏎ send/,
91
+ install: "npm install -g @openai/codex-cli",
92
+ ready: [/⏎ send/],
86
93
  enter: [/ > 1. Approve/, /> 1. Yes, allow Codex to work in this folder/],
87
94
  fatal: [/Error: The cursor position could not be read within/],
88
95
  ensureArgs: (args) => {
@@ -92,13 +99,15 @@ var CLI_CONFIGURES = {
92
99
  }
93
100
  },
94
101
  copilot: {
95
- ready: /^ > /,
102
+ install: "npm install -g @github/copilot",
103
+ ready: [/^ > /],
96
104
  enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/],
97
105
  fatal: []
98
106
  },
99
107
  cursor: {
108
+ install: "open https://cursor.com/ja/docs/cli/installation",
100
109
  binary: "cursor-agent",
101
- ready: /\/ commands/,
110
+ ready: [/\/ commands/],
102
111
  enter: [/→ Run \(once\) \(y\) \(enter\)/, /▶ \[a\] Trust this workspace/],
103
112
  fatal: []
104
113
  }
@@ -135,7 +144,12 @@ async function claudeYes({
135
144
  const cliConf = CLI_CONFIGURES[cli] || {};
136
145
  cliArgs = cliConf.ensureArgs?.(cliArgs) ?? cliArgs;
137
146
  const cliCommand = cliConf?.binary || cli;
138
- let shell = pty.spawn(cliCommand, cliArgs, getPtyOptions());
147
+ let shell = tryCatch(() => pty.spawn(cliCommand, cliArgs, getPtyOptions()), (error) => {
148
+ console.error(`Fatal: Failed to start ${cliCommand}.`);
149
+ if (cliConf?.install)
150
+ console.error(`If you did not installed it yet, Please install it first: ${cliConf.install}`);
151
+ throw error;
152
+ });
139
153
  const pendingExitCode = Promise.withResolvers();
140
154
  let pendingExitCodeValue = null;
141
155
  async function onData(data) {
@@ -202,30 +216,15 @@ async function claudeYes({
202
216
  const conf = CLI_CONFIGURES[cli] || null;
203
217
  if (!conf)
204
218
  return;
205
- try {
206
- if (conf.ready) {
207
- if (cli === "gemini" && conf.ready instanceof RegExp) {
208
- if (e2.match(conf.ready) && i > 80)
209
- return stdinReady.ready();
210
- } else if (e2.match(conf.ready)) {
211
- return stdinReady.ready();
212
- }
213
- }
214
- if (conf.enter && Array.isArray(conf.enter)) {
215
- for (const rx of conf.enter) {
216
- if (e2.match(rx))
217
- return await sendEnter();
218
- }
219
- }
220
- if (conf.fatal && Array.isArray(conf.fatal)) {
221
- for (const rx of conf.fatal) {
222
- if (e2.match(rx))
223
- return isFatal = true;
224
- }
225
- }
226
- } catch (err) {
227
- return;
219
+ if (conf.ready?.some((rx) => e2.match(rx))) {
220
+ if (cli === "gemini" && i <= 80)
221
+ return;
222
+ stdinReady.ready();
228
223
  }
224
+ if (conf.enter?.some((rx) => e2.match(rx)))
225
+ await sendEnter(300);
226
+ if (conf.fatal?.some((rx) => e2.match(rx)))
227
+ isFatal = true;
229
228
  }).run()).map((e) => removeControlCharactersFromStdout ? removeControlCharacters(e) : e).to(fromWritable(process.stdout)).then(() => null);
230
229
  if (prompt)
231
230
  (async () => {
@@ -274,6 +273,13 @@ async function claudeYes({
274
273
  };
275
274
  }
276
275
  }
276
+ function tryCatch(fn, catchFn) {
277
+ try {
278
+ return fn();
279
+ } catch (error) {
280
+ return catchFn(error);
281
+ }
282
+ }
277
283
 
278
284
  // cli.ts
279
285
  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", {
@@ -328,5 +334,5 @@ var { exitCode, logs } = await claudeYes({
328
334
  });
329
335
  process.exit(exitCode ?? 1);
330
336
 
331
- //# debugId=0E9D5C1D34AAD47764756E2164756E21
337
+ //# debugId=6A4CE059DEBD884464756E2164756E21
332
338
  //# sourceMappingURL=cli.js.map
package/dist/cli.js CHANGED
@@ -68,8 +68,13 @@ function removeControlCharacters(str) {
68
68
  return str.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, "");
69
69
  }
70
70
  var CLI_CONFIGURES = {
71
+ grok: {
72
+ install: "npm install -g @vibe-kit/grok-cli",
73
+ ready: [/^ +│ ❯ /]
74
+ },
71
75
  claude: {
72
- ready: /^> /,
76
+ install: "npm install -g @anthropic-ai/claude-code",
77
+ ready: [/^> /],
73
78
  enter: [/❯ 1. Yes/, /❯ 1. Dark mode✔/, /Press Enter to continue…/],
74
79
  fatal: [
75
80
  /No conversation found to continue/,
@@ -77,12 +82,14 @@ var CLI_CONFIGURES = {
77
82
  ]
78
83
  },
79
84
  gemini: {
80
- ready: /Type your message/,
85
+ install: "npm install -g @google/gemini-cli",
86
+ ready: [/Type your message/],
81
87
  enter: [/│ ● 1. Yes, allow once/],
82
88
  fatal: []
83
89
  },
84
90
  codex: {
85
- ready: /⏎ send/,
91
+ install: "npm install -g @openai/codex-cli",
92
+ ready: [/⏎ send/],
86
93
  enter: [/ > 1. Approve/, /> 1. Yes, allow Codex to work in this folder/],
87
94
  fatal: [/Error: The cursor position could not be read within/],
88
95
  ensureArgs: (args) => {
@@ -92,13 +99,15 @@ var CLI_CONFIGURES = {
92
99
  }
93
100
  },
94
101
  copilot: {
95
- ready: /^ > /,
102
+ install: "npm install -g @github/copilot",
103
+ ready: [/^ > /],
96
104
  enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/],
97
105
  fatal: []
98
106
  },
99
107
  cursor: {
108
+ install: "open https://cursor.com/ja/docs/cli/installation",
100
109
  binary: "cursor-agent",
101
- ready: /\/ commands/,
110
+ ready: [/\/ commands/],
102
111
  enter: [/→ Run \(once\) \(y\) \(enter\)/, /▶ \[a\] Trust this workspace/],
103
112
  fatal: []
104
113
  }
@@ -135,7 +144,12 @@ async function claudeYes({
135
144
  const cliConf = CLI_CONFIGURES[cli] || {};
136
145
  cliArgs = cliConf.ensureArgs?.(cliArgs) ?? cliArgs;
137
146
  const cliCommand = cliConf?.binary || cli;
138
- let shell = pty.spawn(cliCommand, cliArgs, getPtyOptions());
147
+ let shell = tryCatch(() => pty.spawn(cliCommand, cliArgs, getPtyOptions()), (error) => {
148
+ console.error(`Fatal: Failed to start ${cliCommand}.`);
149
+ if (cliConf?.install)
150
+ console.error(`If you did not installed it yet, Please install it first: ${cliConf.install}`);
151
+ throw error;
152
+ });
139
153
  const pendingExitCode = Promise.withResolvers();
140
154
  let pendingExitCodeValue = null;
141
155
  async function onData(data) {
@@ -202,30 +216,15 @@ async function claudeYes({
202
216
  const conf = CLI_CONFIGURES[cli] || null;
203
217
  if (!conf)
204
218
  return;
205
- try {
206
- if (conf.ready) {
207
- if (cli === "gemini" && conf.ready instanceof RegExp) {
208
- if (e2.match(conf.ready) && i > 80)
209
- return stdinReady.ready();
210
- } else if (e2.match(conf.ready)) {
211
- return stdinReady.ready();
212
- }
213
- }
214
- if (conf.enter && Array.isArray(conf.enter)) {
215
- for (const rx of conf.enter) {
216
- if (e2.match(rx))
217
- return await sendEnter();
218
- }
219
- }
220
- if (conf.fatal && Array.isArray(conf.fatal)) {
221
- for (const rx of conf.fatal) {
222
- if (e2.match(rx))
223
- return isFatal = true;
224
- }
225
- }
226
- } catch (err) {
227
- return;
219
+ if (conf.ready?.some((rx) => e2.match(rx))) {
220
+ if (cli === "gemini" && i <= 80)
221
+ return;
222
+ stdinReady.ready();
228
223
  }
224
+ if (conf.enter?.some((rx) => e2.match(rx)))
225
+ await sendEnter(300);
226
+ if (conf.fatal?.some((rx) => e2.match(rx)))
227
+ isFatal = true;
229
228
  }).run()).map((e) => removeControlCharactersFromStdout ? removeControlCharacters(e) : e).to(fromWritable(process.stdout)).then(() => null);
230
229
  if (prompt)
231
230
  (async () => {
@@ -274,6 +273,13 @@ async function claudeYes({
274
273
  };
275
274
  }
276
275
  }
276
+ function tryCatch(fn, catchFn) {
277
+ try {
278
+ return fn();
279
+ } catch (error) {
280
+ return catchFn(error);
281
+ }
282
+ }
277
283
 
278
284
  // cli.ts
279
285
  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", {
@@ -328,5 +334,5 @@ var { exitCode, logs } = await claudeYes({
328
334
  });
329
335
  process.exit(exitCode ?? 1);
330
336
 
331
- //# debugId=0E9D5C1D34AAD47764756E2164756E21
337
+ //# debugId=6A4CE059DEBD884464756E2164756E21
332
338
  //# sourceMappingURL=cli.js.map
package/dist/cli.js.map CHANGED
@@ -3,9 +3,9 @@
3
3
  "sources": ["../cli.ts", "index.js"],
4
4
  "sourcesContent": [
5
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 'Claude CLI command, e.g. \"claude,gemini,codex,cursor,copilot\", default is \"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 })\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 claude: {\n ready: /^> /,\n enter: [/❯ 1. Yes/, /❯ 1. Dark mode✔/, /Press Enter to continue…/],\n fatal: [\n /No conversation found to continue/,\n /⎿ {2}Claude usage limit reached\\./\n ]\n },\n gemini: {\n ready: /Type your message/,\n enter: [/│ ● 1. Yes, allow once/],\n fatal: []\n },\n codex: {\n ready: /⏎ send/,\n enter: [/ > 1. Approve/, /> 1. Yes, allow Codex to work in this folder/],\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 ready: /^ > /,\n enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/],\n fatal: []\n },\n cursor: {\n binary: \"cursor-agent\",\n ready: /\\/ commands/,\n enter: [/→ Run \\(once\\) \\(y\\) \\(enter\\)/, /▶ \\[a\\] Trust this workspace/],\n fatal: []\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 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 = pty.spawn(cliCommand, cliArgs, getPtyOptions());\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 console.log(`${cli} crashed with \"No conversation found to continue\", exiting...`);\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 rendered = terminalRender.render();\n const row = rendered.split(`\n`).length + 1;\n const col = (rendered.split(`\n`).slice(-1)[0]?.length || 0) + 1;\n shell.write(`\\x1B[${row};${col}R`);\n }).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll(\"\\r\", \"\")).lines({ EOL: \"NONE\" }).forEach(async (e2, i) => {\n const conf = CLI_CONFIGURES[cli] || null;\n if (!conf)\n return;\n try {\n if (conf.ready) {\n if (cli === \"gemini\" && conf.ready instanceof RegExp) {\n if (e2.match(conf.ready) && i > 80)\n return stdinReady.ready();\n } else if (e2.match(conf.ready)) {\n return stdinReady.ready();\n }\n }\n if (conf.enter && Array.isArray(conf.enter)) {\n for (const rx of conf.enter) {\n if (e2.match(rx))\n return await sendEnter();\n }\n }\n if (conf.fatal && Array.isArray(conf.fatal)) {\n for (const rx of conf.fatal) {\n if (e2.match(rx))\n return isFatal = true;\n }\n }\n } catch (err) {\n return;\n }\n }).run()).map((e) => removeControlCharactersFromStdout ? removeControlCharacters(e) : e).to(fromWritable(process.stdout)).then(() => null);\n if (prompt)\n (async () => {\n await sendMessage(prompt);\n })();\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 process.stdout.write(`\\ridleWaiter.wait(${waitms}) took ${et - st}ms\\r`);\n shell.write(\"\\r\");\n }\n async function sendMessage(message) {\n await stdinReady.wait();\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 return {\n cols: Math.max(process.stdout.columns, 80),\n rows: process.stdout.rows\n };\n }\n}\nexport {\n removeControlCharacters,\n claudeYes as default,\n CLI_CONFIGURES\n};\n\n//# debugId=095427732AFAFB1F64756E2164756E21\n//# sourceMappingURL=index.js.map\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 },\n claude: {\n install: \"npm install -g @anthropic-ai/claude-code\",\n ready: [/^> /],\n enter: [/❯ 1. Yes/, /❯ 1. Dark mode✔/, /Press Enter to continue…/],\n fatal: [\n /No conversation found to continue/,\n /⎿ {2}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: [/ > 1. Approve/, /> 1. Yes, allow Codex to work in this folder/],\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: []\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 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 console.log(`${cli} crashed with \"No conversation found to continue\", exiting...`);\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 rendered = terminalRender.render();\n const row = rendered.split(`\n`).length + 1;\n const col = (rendered.split(`\n`).slice(-1)[0]?.length || 0) + 1;\n shell.write(`\\x1B[${row};${col}R`);\n }).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll(\"\\r\", \"\")).lines({ EOL: \"NONE\" }).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 if (conf.fatal?.some((rx) => e2.match(rx)))\n isFatal = true;\n }).run()).map((e) => removeControlCharactersFromStdout ? removeControlCharacters(e) : e).to(fromWritable(process.stdout)).then(() => null);\n if (prompt)\n (async () => {\n await sendMessage(prompt);\n })();\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 process.stdout.write(`\\ridleWaiter.wait(${waitms}) took ${et - st}ms\\r`);\n shell.write(\"\\r\");\n }\n async function sendMessage(message) {\n await stdinReady.wait();\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 return {\n cols: Math.max(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=69E33BC2DDEE744C64756E2164756E21\n//# sourceMappingURL=index.js.map\n"
7
7
  ],
8
- "mappings": "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",
9
- "debugId": "0E9D5C1D34AAD47764756E2164756E21",
8
+ "mappings": "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",
9
+ "debugId": "6A4CE059DEBD884464756E2164756E21",
10
10
  "names": []
11
11
  }
package/dist/codex-yes.js CHANGED
@@ -68,8 +68,13 @@ function removeControlCharacters(str) {
68
68
  return str.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, "");
69
69
  }
70
70
  var CLI_CONFIGURES = {
71
+ grok: {
72
+ install: "npm install -g @vibe-kit/grok-cli",
73
+ ready: [/^ +│ ❯ /]
74
+ },
71
75
  claude: {
72
- ready: /^> /,
76
+ install: "npm install -g @anthropic-ai/claude-code",
77
+ ready: [/^> /],
73
78
  enter: [/❯ 1. Yes/, /❯ 1. Dark mode✔/, /Press Enter to continue…/],
74
79
  fatal: [
75
80
  /No conversation found to continue/,
@@ -77,12 +82,14 @@ var CLI_CONFIGURES = {
77
82
  ]
78
83
  },
79
84
  gemini: {
80
- ready: /Type your message/,
85
+ install: "npm install -g @google/gemini-cli",
86
+ ready: [/Type your message/],
81
87
  enter: [/│ ● 1. Yes, allow once/],
82
88
  fatal: []
83
89
  },
84
90
  codex: {
85
- ready: /⏎ send/,
91
+ install: "npm install -g @openai/codex-cli",
92
+ ready: [/⏎ send/],
86
93
  enter: [/ > 1. Approve/, /> 1. Yes, allow Codex to work in this folder/],
87
94
  fatal: [/Error: The cursor position could not be read within/],
88
95
  ensureArgs: (args) => {
@@ -92,13 +99,15 @@ var CLI_CONFIGURES = {
92
99
  }
93
100
  },
94
101
  copilot: {
95
- ready: /^ > /,
102
+ install: "npm install -g @github/copilot",
103
+ ready: [/^ > /],
96
104
  enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/],
97
105
  fatal: []
98
106
  },
99
107
  cursor: {
108
+ install: "open https://cursor.com/ja/docs/cli/installation",
100
109
  binary: "cursor-agent",
101
- ready: /\/ commands/,
110
+ ready: [/\/ commands/],
102
111
  enter: [/→ Run \(once\) \(y\) \(enter\)/, /▶ \[a\] Trust this workspace/],
103
112
  fatal: []
104
113
  }
@@ -135,7 +144,12 @@ async function claudeYes({
135
144
  const cliConf = CLI_CONFIGURES[cli] || {};
136
145
  cliArgs = cliConf.ensureArgs?.(cliArgs) ?? cliArgs;
137
146
  const cliCommand = cliConf?.binary || cli;
138
- let shell = pty.spawn(cliCommand, cliArgs, getPtyOptions());
147
+ let shell = tryCatch(() => pty.spawn(cliCommand, cliArgs, getPtyOptions()), (error) => {
148
+ console.error(`Fatal: Failed to start ${cliCommand}.`);
149
+ if (cliConf?.install)
150
+ console.error(`If you did not installed it yet, Please install it first: ${cliConf.install}`);
151
+ throw error;
152
+ });
139
153
  const pendingExitCode = Promise.withResolvers();
140
154
  let pendingExitCodeValue = null;
141
155
  async function onData(data) {
@@ -202,30 +216,15 @@ async function claudeYes({
202
216
  const conf = CLI_CONFIGURES[cli] || null;
203
217
  if (!conf)
204
218
  return;
205
- try {
206
- if (conf.ready) {
207
- if (cli === "gemini" && conf.ready instanceof RegExp) {
208
- if (e2.match(conf.ready) && i > 80)
209
- return stdinReady.ready();
210
- } else if (e2.match(conf.ready)) {
211
- return stdinReady.ready();
212
- }
213
- }
214
- if (conf.enter && Array.isArray(conf.enter)) {
215
- for (const rx of conf.enter) {
216
- if (e2.match(rx))
217
- return await sendEnter();
218
- }
219
- }
220
- if (conf.fatal && Array.isArray(conf.fatal)) {
221
- for (const rx of conf.fatal) {
222
- if (e2.match(rx))
223
- return isFatal = true;
224
- }
225
- }
226
- } catch (err) {
227
- return;
219
+ if (conf.ready?.some((rx) => e2.match(rx))) {
220
+ if (cli === "gemini" && i <= 80)
221
+ return;
222
+ stdinReady.ready();
228
223
  }
224
+ if (conf.enter?.some((rx) => e2.match(rx)))
225
+ await sendEnter(300);
226
+ if (conf.fatal?.some((rx) => e2.match(rx)))
227
+ isFatal = true;
229
228
  }).run()).map((e) => removeControlCharactersFromStdout ? removeControlCharacters(e) : e).to(fromWritable(process.stdout)).then(() => null);
230
229
  if (prompt)
231
230
  (async () => {
@@ -274,6 +273,13 @@ async function claudeYes({
274
273
  };
275
274
  }
276
275
  }
276
+ function tryCatch(fn, catchFn) {
277
+ try {
278
+ return fn();
279
+ } catch (error) {
280
+ return catchFn(error);
281
+ }
282
+ }
277
283
 
278
284
  // cli.ts
279
285
  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", {
@@ -328,5 +334,5 @@ var { exitCode, logs } = await claudeYes({
328
334
  });
329
335
  process.exit(exitCode ?? 1);
330
336
 
331
- //# debugId=0E9D5C1D34AAD47764756E2164756E21
337
+ //# debugId=6A4CE059DEBD884464756E2164756E21
332
338
  //# sourceMappingURL=cli.js.map
@@ -68,8 +68,13 @@ function removeControlCharacters(str) {
68
68
  return str.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, "");
69
69
  }
70
70
  var CLI_CONFIGURES = {
71
+ grok: {
72
+ install: "npm install -g @vibe-kit/grok-cli",
73
+ ready: [/^ +│ ❯ /]
74
+ },
71
75
  claude: {
72
- ready: /^> /,
76
+ install: "npm install -g @anthropic-ai/claude-code",
77
+ ready: [/^> /],
73
78
  enter: [/❯ 1. Yes/, /❯ 1. Dark mode✔/, /Press Enter to continue…/],
74
79
  fatal: [
75
80
  /No conversation found to continue/,
@@ -77,12 +82,14 @@ var CLI_CONFIGURES = {
77
82
  ]
78
83
  },
79
84
  gemini: {
80
- ready: /Type your message/,
85
+ install: "npm install -g @google/gemini-cli",
86
+ ready: [/Type your message/],
81
87
  enter: [/│ ● 1. Yes, allow once/],
82
88
  fatal: []
83
89
  },
84
90
  codex: {
85
- ready: /⏎ send/,
91
+ install: "npm install -g @openai/codex-cli",
92
+ ready: [/⏎ send/],
86
93
  enter: [/ > 1. Approve/, /> 1. Yes, allow Codex to work in this folder/],
87
94
  fatal: [/Error: The cursor position could not be read within/],
88
95
  ensureArgs: (args) => {
@@ -92,13 +99,15 @@ var CLI_CONFIGURES = {
92
99
  }
93
100
  },
94
101
  copilot: {
95
- ready: /^ > /,
102
+ install: "npm install -g @github/copilot",
103
+ ready: [/^ > /],
96
104
  enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/],
97
105
  fatal: []
98
106
  },
99
107
  cursor: {
108
+ install: "open https://cursor.com/ja/docs/cli/installation",
100
109
  binary: "cursor-agent",
101
- ready: /\/ commands/,
110
+ ready: [/\/ commands/],
102
111
  enter: [/→ Run \(once\) \(y\) \(enter\)/, /▶ \[a\] Trust this workspace/],
103
112
  fatal: []
104
113
  }
@@ -135,7 +144,12 @@ async function claudeYes({
135
144
  const cliConf = CLI_CONFIGURES[cli] || {};
136
145
  cliArgs = cliConf.ensureArgs?.(cliArgs) ?? cliArgs;
137
146
  const cliCommand = cliConf?.binary || cli;
138
- let shell = pty.spawn(cliCommand, cliArgs, getPtyOptions());
147
+ let shell = tryCatch(() => pty.spawn(cliCommand, cliArgs, getPtyOptions()), (error) => {
148
+ console.error(`Fatal: Failed to start ${cliCommand}.`);
149
+ if (cliConf?.install)
150
+ console.error(`If you did not installed it yet, Please install it first: ${cliConf.install}`);
151
+ throw error;
152
+ });
139
153
  const pendingExitCode = Promise.withResolvers();
140
154
  let pendingExitCodeValue = null;
141
155
  async function onData(data) {
@@ -202,30 +216,15 @@ async function claudeYes({
202
216
  const conf = CLI_CONFIGURES[cli] || null;
203
217
  if (!conf)
204
218
  return;
205
- try {
206
- if (conf.ready) {
207
- if (cli === "gemini" && conf.ready instanceof RegExp) {
208
- if (e2.match(conf.ready) && i > 80)
209
- return stdinReady.ready();
210
- } else if (e2.match(conf.ready)) {
211
- return stdinReady.ready();
212
- }
213
- }
214
- if (conf.enter && Array.isArray(conf.enter)) {
215
- for (const rx of conf.enter) {
216
- if (e2.match(rx))
217
- return await sendEnter();
218
- }
219
- }
220
- if (conf.fatal && Array.isArray(conf.fatal)) {
221
- for (const rx of conf.fatal) {
222
- if (e2.match(rx))
223
- return isFatal = true;
224
- }
225
- }
226
- } catch (err) {
227
- return;
219
+ if (conf.ready?.some((rx) => e2.match(rx))) {
220
+ if (cli === "gemini" && i <= 80)
221
+ return;
222
+ stdinReady.ready();
228
223
  }
224
+ if (conf.enter?.some((rx) => e2.match(rx)))
225
+ await sendEnter(300);
226
+ if (conf.fatal?.some((rx) => e2.match(rx)))
227
+ isFatal = true;
229
228
  }).run()).map((e) => removeControlCharactersFromStdout ? removeControlCharacters(e) : e).to(fromWritable(process.stdout)).then(() => null);
230
229
  if (prompt)
231
230
  (async () => {
@@ -274,6 +273,13 @@ async function claudeYes({
274
273
  };
275
274
  }
276
275
  }
276
+ function tryCatch(fn, catchFn) {
277
+ try {
278
+ return fn();
279
+ } catch (error) {
280
+ return catchFn(error);
281
+ }
282
+ }
277
283
 
278
284
  // cli.ts
279
285
  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", {
@@ -328,5 +334,5 @@ var { exitCode, logs } = await claudeYes({
328
334
  });
329
335
  process.exit(exitCode ?? 1);
330
336
 
331
- //# debugId=0E9D5C1D34AAD47764756E2164756E21
337
+ //# debugId=6A4CE059DEBD884464756E2164756E21
332
338
  //# sourceMappingURL=cli.js.map
@@ -68,8 +68,13 @@ function removeControlCharacters(str) {
68
68
  return str.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, "");
69
69
  }
70
70
  var CLI_CONFIGURES = {
71
+ grok: {
72
+ install: "npm install -g @vibe-kit/grok-cli",
73
+ ready: [/^ +│ ❯ /]
74
+ },
71
75
  claude: {
72
- ready: /^> /,
76
+ install: "npm install -g @anthropic-ai/claude-code",
77
+ ready: [/^> /],
73
78
  enter: [/❯ 1. Yes/, /❯ 1. Dark mode✔/, /Press Enter to continue…/],
74
79
  fatal: [
75
80
  /No conversation found to continue/,
@@ -77,12 +82,14 @@ var CLI_CONFIGURES = {
77
82
  ]
78
83
  },
79
84
  gemini: {
80
- ready: /Type your message/,
85
+ install: "npm install -g @google/gemini-cli",
86
+ ready: [/Type your message/],
81
87
  enter: [/│ ● 1. Yes, allow once/],
82
88
  fatal: []
83
89
  },
84
90
  codex: {
85
- ready: /⏎ send/,
91
+ install: "npm install -g @openai/codex-cli",
92
+ ready: [/⏎ send/],
86
93
  enter: [/ > 1. Approve/, /> 1. Yes, allow Codex to work in this folder/],
87
94
  fatal: [/Error: The cursor position could not be read within/],
88
95
  ensureArgs: (args) => {
@@ -92,13 +99,15 @@ var CLI_CONFIGURES = {
92
99
  }
93
100
  },
94
101
  copilot: {
95
- ready: /^ > /,
102
+ install: "npm install -g @github/copilot",
103
+ ready: [/^ > /],
96
104
  enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/],
97
105
  fatal: []
98
106
  },
99
107
  cursor: {
108
+ install: "open https://cursor.com/ja/docs/cli/installation",
100
109
  binary: "cursor-agent",
101
- ready: /\/ commands/,
110
+ ready: [/\/ commands/],
102
111
  enter: [/→ Run \(once\) \(y\) \(enter\)/, /▶ \[a\] Trust this workspace/],
103
112
  fatal: []
104
113
  }
@@ -135,7 +144,12 @@ async function claudeYes({
135
144
  const cliConf = CLI_CONFIGURES[cli] || {};
136
145
  cliArgs = cliConf.ensureArgs?.(cliArgs) ?? cliArgs;
137
146
  const cliCommand = cliConf?.binary || cli;
138
- let shell = pty.spawn(cliCommand, cliArgs, getPtyOptions());
147
+ let shell = tryCatch(() => pty.spawn(cliCommand, cliArgs, getPtyOptions()), (error) => {
148
+ console.error(`Fatal: Failed to start ${cliCommand}.`);
149
+ if (cliConf?.install)
150
+ console.error(`If you did not installed it yet, Please install it first: ${cliConf.install}`);
151
+ throw error;
152
+ });
139
153
  const pendingExitCode = Promise.withResolvers();
140
154
  let pendingExitCodeValue = null;
141
155
  async function onData(data) {
@@ -202,30 +216,15 @@ async function claudeYes({
202
216
  const conf = CLI_CONFIGURES[cli] || null;
203
217
  if (!conf)
204
218
  return;
205
- try {
206
- if (conf.ready) {
207
- if (cli === "gemini" && conf.ready instanceof RegExp) {
208
- if (e2.match(conf.ready) && i > 80)
209
- return stdinReady.ready();
210
- } else if (e2.match(conf.ready)) {
211
- return stdinReady.ready();
212
- }
213
- }
214
- if (conf.enter && Array.isArray(conf.enter)) {
215
- for (const rx of conf.enter) {
216
- if (e2.match(rx))
217
- return await sendEnter();
218
- }
219
- }
220
- if (conf.fatal && Array.isArray(conf.fatal)) {
221
- for (const rx of conf.fatal) {
222
- if (e2.match(rx))
223
- return isFatal = true;
224
- }
225
- }
226
- } catch (err) {
227
- return;
219
+ if (conf.ready?.some((rx) => e2.match(rx))) {
220
+ if (cli === "gemini" && i <= 80)
221
+ return;
222
+ stdinReady.ready();
228
223
  }
224
+ if (conf.enter?.some((rx) => e2.match(rx)))
225
+ await sendEnter(300);
226
+ if (conf.fatal?.some((rx) => e2.match(rx)))
227
+ isFatal = true;
229
228
  }).run()).map((e) => removeControlCharactersFromStdout ? removeControlCharacters(e) : e).to(fromWritable(process.stdout)).then(() => null);
230
229
  if (prompt)
231
230
  (async () => {
@@ -274,6 +273,13 @@ async function claudeYes({
274
273
  };
275
274
  }
276
275
  }
276
+ function tryCatch(fn, catchFn) {
277
+ try {
278
+ return fn();
279
+ } catch (error) {
280
+ return catchFn(error);
281
+ }
282
+ }
277
283
 
278
284
  // cli.ts
279
285
  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", {
@@ -328,5 +334,5 @@ var { exitCode, logs } = await claudeYes({
328
334
  });
329
335
  process.exit(exitCode ?? 1);
330
336
 
331
- //# debugId=0E9D5C1D34AAD47764756E2164756E21
337
+ //# debugId=6A4CE059DEBD884464756E2164756E21
332
338
  //# sourceMappingURL=cli.js.map
@@ -68,8 +68,13 @@ function removeControlCharacters(str) {
68
68
  return str.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, "");
69
69
  }
70
70
  var CLI_CONFIGURES = {
71
+ grok: {
72
+ install: "npm install -g @vibe-kit/grok-cli",
73
+ ready: [/^ +│ ❯ /]
74
+ },
71
75
  claude: {
72
- ready: /^> /,
76
+ install: "npm install -g @anthropic-ai/claude-code",
77
+ ready: [/^> /],
73
78
  enter: [/❯ 1. Yes/, /❯ 1. Dark mode✔/, /Press Enter to continue…/],
74
79
  fatal: [
75
80
  /No conversation found to continue/,
@@ -77,12 +82,14 @@ var CLI_CONFIGURES = {
77
82
  ]
78
83
  },
79
84
  gemini: {
80
- ready: /Type your message/,
85
+ install: "npm install -g @google/gemini-cli",
86
+ ready: [/Type your message/],
81
87
  enter: [/│ ● 1. Yes, allow once/],
82
88
  fatal: []
83
89
  },
84
90
  codex: {
85
- ready: /⏎ send/,
91
+ install: "npm install -g @openai/codex-cli",
92
+ ready: [/⏎ send/],
86
93
  enter: [/ > 1. Approve/, /> 1. Yes, allow Codex to work in this folder/],
87
94
  fatal: [/Error: The cursor position could not be read within/],
88
95
  ensureArgs: (args) => {
@@ -92,13 +99,15 @@ var CLI_CONFIGURES = {
92
99
  }
93
100
  },
94
101
  copilot: {
95
- ready: /^ > /,
102
+ install: "npm install -g @github/copilot",
103
+ ready: [/^ > /],
96
104
  enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/],
97
105
  fatal: []
98
106
  },
99
107
  cursor: {
108
+ install: "open https://cursor.com/ja/docs/cli/installation",
100
109
  binary: "cursor-agent",
101
- ready: /\/ commands/,
110
+ ready: [/\/ commands/],
102
111
  enter: [/→ Run \(once\) \(y\) \(enter\)/, /▶ \[a\] Trust this workspace/],
103
112
  fatal: []
104
113
  }
@@ -135,7 +144,12 @@ async function claudeYes({
135
144
  const cliConf = CLI_CONFIGURES[cli] || {};
136
145
  cliArgs = cliConf.ensureArgs?.(cliArgs) ?? cliArgs;
137
146
  const cliCommand = cliConf?.binary || cli;
138
- let shell = pty.spawn(cliCommand, cliArgs, getPtyOptions());
147
+ let shell = tryCatch(() => pty.spawn(cliCommand, cliArgs, getPtyOptions()), (error) => {
148
+ console.error(`Fatal: Failed to start ${cliCommand}.`);
149
+ if (cliConf?.install)
150
+ console.error(`If you did not installed it yet, Please install it first: ${cliConf.install}`);
151
+ throw error;
152
+ });
139
153
  const pendingExitCode = Promise.withResolvers();
140
154
  let pendingExitCodeValue = null;
141
155
  async function onData(data) {
@@ -202,30 +216,15 @@ async function claudeYes({
202
216
  const conf = CLI_CONFIGURES[cli] || null;
203
217
  if (!conf)
204
218
  return;
205
- try {
206
- if (conf.ready) {
207
- if (cli === "gemini" && conf.ready instanceof RegExp) {
208
- if (e2.match(conf.ready) && i > 80)
209
- return stdinReady.ready();
210
- } else if (e2.match(conf.ready)) {
211
- return stdinReady.ready();
212
- }
213
- }
214
- if (conf.enter && Array.isArray(conf.enter)) {
215
- for (const rx of conf.enter) {
216
- if (e2.match(rx))
217
- return await sendEnter();
218
- }
219
- }
220
- if (conf.fatal && Array.isArray(conf.fatal)) {
221
- for (const rx of conf.fatal) {
222
- if (e2.match(rx))
223
- return isFatal = true;
224
- }
225
- }
226
- } catch (err) {
227
- return;
219
+ if (conf.ready?.some((rx) => e2.match(rx))) {
220
+ if (cli === "gemini" && i <= 80)
221
+ return;
222
+ stdinReady.ready();
228
223
  }
224
+ if (conf.enter?.some((rx) => e2.match(rx)))
225
+ await sendEnter(300);
226
+ if (conf.fatal?.some((rx) => e2.match(rx)))
227
+ isFatal = true;
229
228
  }).run()).map((e) => removeControlCharactersFromStdout ? removeControlCharacters(e) : e).to(fromWritable(process.stdout)).then(() => null);
230
229
  if (prompt)
231
230
  (async () => {
@@ -274,6 +273,13 @@ async function claudeYes({
274
273
  };
275
274
  }
276
275
  }
276
+ function tryCatch(fn, catchFn) {
277
+ try {
278
+ return fn();
279
+ } catch (error) {
280
+ return catchFn(error);
281
+ }
282
+ }
277
283
 
278
284
  // cli.ts
279
285
  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", {
@@ -328,5 +334,5 @@ var { exitCode, logs } = await claudeYes({
328
334
  });
329
335
  process.exit(exitCode ?? 1);
330
336
 
331
- //# debugId=0E9D5C1D34AAD47764756E2164756E21
337
+ //# debugId=6A4CE059DEBD884464756E2164756E21
332
338
  //# sourceMappingURL=cli.js.map
package/dist/index.js CHANGED
@@ -69,8 +69,13 @@ function removeControlCharacters(str) {
69
69
 
70
70
  // index.ts
71
71
  var CLI_CONFIGURES = {
72
+ grok: {
73
+ install: "npm install -g @vibe-kit/grok-cli",
74
+ ready: [/^ +│ ❯ /]
75
+ },
72
76
  claude: {
73
- ready: /^> /,
77
+ install: "npm install -g @anthropic-ai/claude-code",
78
+ ready: [/^> /],
74
79
  enter: [/❯ 1. Yes/, /❯ 1. Dark mode✔/, /Press Enter to continue…/],
75
80
  fatal: [
76
81
  /No conversation found to continue/,
@@ -78,12 +83,14 @@ var CLI_CONFIGURES = {
78
83
  ]
79
84
  },
80
85
  gemini: {
81
- ready: /Type your message/,
86
+ install: "npm install -g @google/gemini-cli",
87
+ ready: [/Type your message/],
82
88
  enter: [/│ ● 1. Yes, allow once/],
83
89
  fatal: []
84
90
  },
85
91
  codex: {
86
- ready: /⏎ send/,
92
+ install: "npm install -g @openai/codex-cli",
93
+ ready: [/⏎ send/],
87
94
  enter: [/ > 1. Approve/, /> 1. Yes, allow Codex to work in this folder/],
88
95
  fatal: [/Error: The cursor position could not be read within/],
89
96
  ensureArgs: (args) => {
@@ -93,13 +100,15 @@ var CLI_CONFIGURES = {
93
100
  }
94
101
  },
95
102
  copilot: {
96
- ready: /^ > /,
103
+ install: "npm install -g @github/copilot",
104
+ ready: [/^ > /],
97
105
  enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/],
98
106
  fatal: []
99
107
  },
100
108
  cursor: {
109
+ install: "open https://cursor.com/ja/docs/cli/installation",
101
110
  binary: "cursor-agent",
102
- ready: /\/ commands/,
111
+ ready: [/\/ commands/],
103
112
  enter: [/→ Run \(once\) \(y\) \(enter\)/, /▶ \[a\] Trust this workspace/],
104
113
  fatal: []
105
114
  }
@@ -136,7 +145,12 @@ async function claudeYes({
136
145
  const cliConf = CLI_CONFIGURES[cli] || {};
137
146
  cliArgs = cliConf.ensureArgs?.(cliArgs) ?? cliArgs;
138
147
  const cliCommand = cliConf?.binary || cli;
139
- let shell = pty.spawn(cliCommand, cliArgs, getPtyOptions());
148
+ let shell = tryCatch(() => pty.spawn(cliCommand, cliArgs, getPtyOptions()), (error) => {
149
+ console.error(`Fatal: Failed to start ${cliCommand}.`);
150
+ if (cliConf?.install)
151
+ console.error(`If you did not installed it yet, Please install it first: ${cliConf.install}`);
152
+ throw error;
153
+ });
140
154
  const pendingExitCode = Promise.withResolvers();
141
155
  let pendingExitCodeValue = null;
142
156
  async function onData(data) {
@@ -203,30 +217,15 @@ async function claudeYes({
203
217
  const conf = CLI_CONFIGURES[cli] || null;
204
218
  if (!conf)
205
219
  return;
206
- try {
207
- if (conf.ready) {
208
- if (cli === "gemini" && conf.ready instanceof RegExp) {
209
- if (e2.match(conf.ready) && i > 80)
210
- return stdinReady.ready();
211
- } else if (e2.match(conf.ready)) {
212
- return stdinReady.ready();
213
- }
214
- }
215
- if (conf.enter && Array.isArray(conf.enter)) {
216
- for (const rx of conf.enter) {
217
- if (e2.match(rx))
218
- return await sendEnter();
219
- }
220
- }
221
- if (conf.fatal && Array.isArray(conf.fatal)) {
222
- for (const rx of conf.fatal) {
223
- if (e2.match(rx))
224
- return isFatal = true;
225
- }
226
- }
227
- } catch (err) {
228
- return;
220
+ if (conf.ready?.some((rx) => e2.match(rx))) {
221
+ if (cli === "gemini" && i <= 80)
222
+ return;
223
+ stdinReady.ready();
229
224
  }
225
+ if (conf.enter?.some((rx) => e2.match(rx)))
226
+ await sendEnter(300);
227
+ if (conf.fatal?.some((rx) => e2.match(rx)))
228
+ isFatal = true;
230
229
  }).run()).map((e) => removeControlCharactersFromStdout ? removeControlCharacters(e) : e).to(fromWritable(process.stdout)).then(() => null);
231
230
  if (prompt)
232
231
  (async () => {
@@ -275,11 +274,18 @@ async function claudeYes({
275
274
  };
276
275
  }
277
276
  }
277
+ function tryCatch(fn, catchFn) {
278
+ try {
279
+ return fn();
280
+ } catch (error) {
281
+ return catchFn(error);
282
+ }
283
+ }
278
284
  export {
279
285
  removeControlCharacters,
280
286
  claudeYes as default,
281
287
  CLI_CONFIGURES
282
288
  };
283
289
 
284
- //# debugId=095427732AFAFB1F64756E2164756E21
290
+ //# debugId=69E33BC2DDEE744C64756E2164756E21
285
291
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -2,12 +2,12 @@
2
2
  "version": 3,
3
3
  "sources": ["../index.ts", "../idleWaiter.ts", "../ReadyManager.ts", "../removeControlCharacters.ts"],
4
4
  "sourcesContent": [
5
- "import { 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';\nimport { IdleWaiter } from './idleWaiter';\nimport { ReadyManager } from './ReadyManager';\nimport { removeControlCharacters } from './removeControlCharacters';\n\nexport const CLI_CONFIGURES: Record<\n string,\n {\n binary?: string; // actual binary name if different from cli\n ready?: RegExp; // regex matcher for stdin ready, or line index for gemini\n enter?: RegExp[]; // array of regex to match for sending Enter\n fatal?: RegExp[]; // array of regex to match for fatal errors\n ensureArgs?: (args: string[]) => string[]; // function to ensure certain args are present\n }\n> = {\n claude: {\n ready: /^> /, // regex matcher for stdin ready,\n enter: [/❯ 1. Yes/, /❯ 1. Dark mode✔/, /Press Enter to continue…/],\n fatal: [\n /No conversation found to continue/,\n /⎿ {2}Claude usage limit reached\\./,\n ],\n },\n gemini: {\n // match the agent prompt after initial lines; handled by index logic using line index\n ready: /Type your message/, // used with line index check\n enter: [/│ ● 1. Yes, allow once/],\n fatal: [],\n },\n codex: {\n ready: /⏎ send/,\n enter: [/ > 1. Approve/, /> 1. Yes, allow Codex to work in this folder/],\n fatal: [/Error: The cursor position could not be read within/],\n // add to codex --search by default when not provided by the user\n ensureArgs: (args: string[]) => {\n if (!args.includes('--search')) return ['--search', ...args];\n return args;\n },\n },\n copilot: {\n ready: /^ > /,\n enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/],\n fatal: [],\n },\n cursor: {\n // map logical \"cursor\" cli name to actual binary name\n binary: 'cursor-agent',\n ready: /\\/ commands/,\n enter: [/→ Run \\(once\\) \\(y\\) \\(enter\\)/, /▶ \\[a\\] Trust this workspace/],\n fatal: [],\n },\n};\n/**\n * Main function to run Claude with automatic yes/no responses\n * @param options Configuration options\n * @param options.continueOnCrash - If true, automatically restart Claude when it crashes:\n * 1. Shows message 'Claude crashed, restarting..'\n * 2. Spawns a new 'claude --continue' process\n * 3. Re-attaches the new process to the shell stdio (pipes new process stdin/stdout)\n * 4. If it crashes with \"No conversation found to continue\", exits the process\n * @param options.exitOnIdle - Exit when Claude is idle. Boolean or timeout in milliseconds, recommended 5000 - 60000, default is false\n * @param options.claudeArgs - Additional arguments to pass to the Claude CLI\n * @param options.removeControlCharactersFromStdout - Remove ANSI control characters from stdout. Defaults to !process.stdout.isTTY\n *\n * @example\n * ```typescript\n * import claudeYes from 'claude-yes';\n * await claudeYes({\n * prompt: 'help me solve all todos in my codebase',\n *\n * // optional\n * cli: 'claude',\n * cliArgs: ['--verbose'], // additional args to pass to claude\n * exitOnIdle: 30000, // exit after 30 seconds of idle\n * continueOnCrash: true, // restart if claude crashes, default is true\n * logFile: 'claude.log', // save logs to file\n * });\n * ```\n */\nexport default async function claudeYes({\n cli = 'claude',\n cliArgs = [],\n prompt,\n continueOnCrash,\n cwd,\n env,\n exitOnIdle,\n logFile,\n removeControlCharactersFromStdout = false, // = !process.stdout.isTTY,\n verbose = false,\n}: {\n cli?: (string & {}) | keyof typeof CLI_CONFIGURES;\n cliArgs?: string[];\n prompt?: string;\n continueOnCrash?: boolean;\n cwd?: string;\n env?: Record<string, string>;\n exitOnIdle?: number;\n logFile?: string;\n removeControlCharactersFromStdout?: boolean;\n verbose?: boolean;\n} = {}) {\n const continueArgs = {\n codex: 'resume --last'.split(' '),\n claude: '--continue'.split(' '),\n gemini: [], // not possible yet\n };\n\n // if (verbose) {\n // console.log('calling claudeYes: ', {\n // cli,\n // continueOnCrash,\n // exitOnIdle,\n // cliArgs,\n // cwd,\n // removeControlCharactersFromStdout,\n // logFile,\n // verbose,\n // });\n // }\n // console.log(\n // `⭐ Starting ${cli}, automatically responding to yes/no prompts...`\n // );\n // console.log(\n // '⚠️ 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.'\n // );\n\n process.stdin.setRawMode?.(true); // must be called any stdout/stdin usage\n let isFatal = false; // match 'No conversation found to continue'\n const stdinReady = new ReadyManager();\n\n const shellOutputStream = new TransformStream<string, string>();\n const outputWriter = shellOutputStream.writable.getWriter();\n // const pty = await import('node-pty');\n\n // its recommened to use bun-pty in windows\n const pty = await import('node-pty')\n .catch(async () => await import('bun-pty'))\n .catch(async () =>\n DIE('Please install node-pty or bun-pty, run this: bun install bun-pty'),\n );\n\n const getPtyOptions = () => ({\n name: 'xterm-color',\n ...getTerminalDimensions(),\n cwd: cwd ?? process.cwd(),\n env: env ?? (process.env as Record<string, string>),\n });\n\n // Apply CLI specific configurations (moved to CLI_CONFIGURES)\n const cliConf = (CLI_CONFIGURES as Record<string, any>)[cli] || {};\n cliArgs = cliConf.ensureArgs?.(cliArgs) ?? cliArgs;\n const cliCommand = cliConf?.binary || cli;\n\n let shell = pty.spawn(cliCommand, cliArgs, getPtyOptions());\n const pendingExitCode = Promise.withResolvers<number | null>();\n let pendingExitCodeValue = null;\n\n // TODO handle error if claude is not installed, show msg:\n // npm install -g @anthropic-ai/claude-code\n\n async function onData(data: string) {\n // append data to the buffer, so we can process it later\n await outputWriter.write(data);\n }\n\n shell.onData(onData);\n shell.onExit(function onExit({ exitCode }) {\n stdinReady.unready(); // start buffer stdin\n const agentCrashed = exitCode !== 0;\n const continueArg = (continueArgs as Record<string, string[]>)[cli];\n\n if (agentCrashed && continueOnCrash && continueArg) {\n if (!continueArg) {\n return console.warn(\n `continueOnCrash is only supported for ${Object.keys(continueArgs).join(', ')} currently, not ${cli}`,\n );\n }\n if (isFatal) {\n console.log(\n `${cli} crashed with \"No conversation found to continue\", exiting...`,\n );\n return pendingExitCode.resolve((pendingExitCodeValue = exitCode));\n }\n console.log(`${cli} crashed, restarting...`);\n\n shell = pty.spawn(cli, continueArg, getPtyOptions());\n shell.onData(onData);\n shell.onExit(onExit);\n return;\n }\n return pendingExitCode.resolve((pendingExitCodeValue = exitCode));\n });\n\n // when current tty resized, resize the pty\n process.stdout.on('resize', () => {\n const { cols, rows } = getTerminalDimensions(); // minimum 80 columns to avoid layout issues\n shell.resize(cols, rows); // minimum 80 columns to avoid layout issues\n });\n\n const terminalRender = new TerminalTextRender();\n const isStillWorkingQ = () =>\n terminalRender\n .render()\n .replace(/\\s+/g, ' ')\n .match(/esc to interrupt|to run in background/);\n\n const idleWaiter = new IdleWaiter();\n if (exitOnIdle)\n idleWaiter.wait(exitOnIdle).then(async () => {\n if (isStillWorkingQ()) {\n console.log(\n '[${cli}-yes] ${cli} is idle, but seems still working, not exiting yet',\n );\n return;\n }\n\n console.log('[${cli}-yes] ${cli} is idle, exiting...');\n await exitAgent();\n });\n\n // Message streaming\n sflow(fromReadable<Buffer>(process.stdin))\n .map((buffer) => buffer.toString())\n // .map((e) => e.replaceAll('\\x1a', '')) // remove ctrl+z from user's input (seems bug)\n // .forEach(e => appendFile('.cache/io.log', \"input |\" + JSON.stringify(e) + '\\n')) // for debugging\n // pipe\n .by({\n writable: new WritableStream<string>({\n write: async (data) => {\n await stdinReady.wait();\n // await idleWaiter.wait(20); // wait for idle for 200ms to avoid messing up claude's input\n shell.write(data);\n },\n }),\n readable: shellOutputStream.readable,\n })\n .forEach(() => idleWaiter.ping())\n .forEach((text) => {\n terminalRender.write(text);\n // todo: .onStatus((msg)=> shell.write(msg))\n if (process.stdin.isTTY) return; // only handle it when stdin is not tty\n if (text.includes('\\u001b[6n')) return; // only asked\n\n // todo: use terminalRender API to get cursor position when new version is available\n // xterm replies CSI row; column R if asked cursor position\n // https://en.wikipedia.org/wiki/ANSI_escape_code#:~:text=citation%20needed%5D-,xterm%20replies,-CSI%20row%C2%A0%3B\n // when agent asking position, respond with row; col\n const rendered = terminalRender.render();\n const row = rendered.split('\\n').length + 1;\n const col = (rendered.split('\\n').slice(-1)[0]?.length || 0) + 1;\n shell.write(`\\u001b[${row};${col}R`);\n })\n\n // auto-response\n .forkTo((e) =>\n e\n .map((e) => removeControlCharacters(e))\n .map((e) => e.replaceAll('\\r', '')) // remove carriage return\n .lines({ EOL: 'NONE' })\n // Generic auto-response handler driven by CLI_CONFIGURES\n .forEach(async (e, i) => {\n const conf =\n CLI_CONFIGURES[cli as keyof typeof CLI_CONFIGURES] || null;\n if (!conf) return;\n\n try {\n // ready matcher: if matched, mark stdin ready\n if (conf.ready) {\n // special-case gemini to avoid initial prompt noise: only after many lines\n if (cli === 'gemini' && conf.ready instanceof RegExp) {\n if (e.match(conf.ready) && i > 80) return stdinReady.ready();\n } else if (e.match(conf.ready)) {\n return stdinReady.ready();\n }\n }\n\n // enter matchers: send Enter when any enter regex matches\n if (conf.enter && Array.isArray(conf.enter)) {\n for (const rx of conf.enter) {\n if (e.match(rx)) return await sendEnter();\n }\n }\n\n // fatal matchers: set isFatal flag when matched\n if (conf.fatal && Array.isArray(conf.fatal)) {\n for (const rx of conf.fatal) {\n if (e.match(rx)) return (isFatal = true);\n }\n }\n } catch (err) {\n // defensive: if e.match throws (e.g., not a string), ignore\n return;\n }\n })\n // .forEach(e => appendFile('.cache/io.log', \"output|\" + JSON.stringify(e) + '\\n')) // for debugging\n .run(),\n )\n .map((e) =>\n removeControlCharactersFromStdout ? removeControlCharacters(e) : e,\n )\n .to(fromWritable(process.stdout))\n .then(() => null); // run it immediately without await\n\n // wait for cli ready and send prompt if provided\n if (prompt)\n (async () => {\n // console.log(`[${cli}-yes] Ready to send prompt to ${cli}: ${prompt}`);\n // idleWaiter.ping();\n // console.log(\n // 'await idleWaiter.wait(1000); // wait a bit for claude to start'\n // );\n // await idleWaiter.wait(1000); // wait a bit for claude to start\n // console.log('await stdinReady.wait();');\n // await stdinReady.wait();\n // console.log(`[${cli}-yes] Waiting for ${cli} to be ready...`);\n // console.log('await idleWaiter.wait(200);');\n // await idleWaiter.wait(200);\n // console.log(`[${cli}-yes] Sending prompt to ${cli}: ${prompt}`);\n await sendMessage(prompt);\n })();\n\n const exitCode = await pendingExitCode.promise; // wait for the shell to exit\n console.log(`[${cli}-yes] ${cli} exited with code ${exitCode}`);\n\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(\n () => null,\n );\n await writeFile(logFilePath, terminalRender.render());\n }\n\n return { exitCode, logs: terminalRender.render() };\n\n async function sendEnter(waitms = 1000) {\n // wait for idle for a bit to let agent cli finish rendering\n const st = Date.now();\n\n await idleWaiter.wait(waitms);\n const et = Date.now();\n process.stdout.write(`\\ridleWaiter.wait(${waitms}) took ${et - st}ms\\r`);\n\n shell.write('\\r');\n }\n\n async function sendMessage(message: string) {\n await stdinReady.wait();\n // show in-place message: write msg and move cursor back start\n shell.write(message);\n idleWaiter.ping(); // just sent a message, wait for echo\n await sendEnter();\n }\n\n async function exitAgent() {\n continueOnCrash = false;\n // send exit command to the shell, must sleep a bit to avoid claude treat it as pasted input\n await sendMessage('/exit');\n\n // wait for shell to exit or kill it with a timeout\n let exited = false;\n await Promise.race([\n pendingExitCode.promise.then(() => (exited = true)), // resolve when shell exits\n\n // if shell doesn't exit in 5 seconds, kill it\n new Promise<void>((resolve) =>\n setTimeout(() => {\n if (exited) return; // if shell already exited, do nothing\n shell.kill(); // kill the shell process if it doesn't exit in time\n resolve();\n }, 5000),\n ), // 5 seconds timeout\n ]);\n }\n\n function getTerminalDimensions() {\n return {\n cols: Math.max(process.stdout.columns, 80),\n rows: process.stdout.rows,\n };\n }\n}\n\nexport { removeControlCharacters };\n",
5
+ "import { 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';\nimport { IdleWaiter } from './idleWaiter';\nimport { ReadyManager } from './ReadyManager';\nimport { removeControlCharacters } from './removeControlCharacters';\n\nexport const CLI_CONFIGURES: Record<\n string,\n {\n install?: string; // hint user for install command if not installed\n binary?: string; // actual binary name if different from cli\n ready?: RegExp[]; // regex matcher for stdin ready, or line index for gemini\n enter?: RegExp[]; // array of regex to match for sending Enter\n fatal?: RegExp[]; // array of regex to match for fatal errors\n ensureArgs?: (args: string[]) => string[]; // function to ensure certain args are present\n }\n> = {\n grok: {\n install: 'npm install -g @vibe-kit/grok-cli',\n ready: [/^ +│ ❯ /],\n },\n claude: {\n install: 'npm install -g @anthropic-ai/claude-code',\n ready: [/^> /], // regex matcher for stdin ready,\n enter: [/❯ 1. Yes/, /❯ 1. Dark mode✔/, /Press Enter to continue…/],\n fatal: [\n /No conversation found to continue/,\n /⎿ {2}Claude usage limit reached\\./,\n ],\n },\n gemini: {\n install: 'npm install -g @google/gemini-cli',\n // match the agent prompt after initial lines; handled by index logic using line index\n ready: [/Type your message/], // used with line index check\n enter: [/│ ● 1. Yes, allow once/],\n fatal: [],\n },\n codex: {\n install: 'npm install -g @openai/codex-cli',\n ready: [/⏎ send/],\n enter: [/ > 1. Approve/, /> 1. Yes, allow Codex to work in this folder/],\n fatal: [/Error: The cursor position could not be read within/],\n // add to codex --search by default when not provided by the user\n ensureArgs: (args: string[]) => {\n if (!args.includes('--search')) 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 // map logical \"cursor\" cli name to actual binary name\n binary: 'cursor-agent',\n ready: [/\\/ commands/],\n enter: [/→ Run \\(once\\) \\(y\\) \\(enter\\)/, /▶ \\[a\\] Trust this workspace/],\n fatal: [],\n },\n};\n/**\n * Main function to run Claude with automatic yes/no responses\n * @param options Configuration options\n * @param options.continueOnCrash - If true, automatically restart Claude when it crashes:\n * 1. Shows message 'Claude crashed, restarting..'\n * 2. Spawns a new 'claude --continue' process\n * 3. Re-attaches the new process to the shell stdio (pipes new process stdin/stdout)\n * 4. If it crashes with \"No conversation found to continue\", exits the process\n * @param options.exitOnIdle - Exit when Claude is idle. Boolean or timeout in milliseconds, recommended 5000 - 60000, default is false\n * @param options.claudeArgs - Additional arguments to pass to the Claude CLI\n * @param options.removeControlCharactersFromStdout - Remove ANSI control characters from stdout. Defaults to !process.stdout.isTTY\n *\n * @example\n * ```typescript\n * import claudeYes from 'claude-yes';\n * await claudeYes({\n * prompt: 'help me solve all todos in my codebase',\n *\n * // optional\n * cli: 'claude',\n * cliArgs: ['--verbose'], // additional args to pass to claude\n * exitOnIdle: 30000, // exit after 30 seconds of idle\n * continueOnCrash: true, // restart if claude crashes, default is true\n * logFile: 'claude.log', // save logs to file\n * });\n * ```\n */\nexport default async function claudeYes({\n cli = 'claude',\n cliArgs = [],\n prompt,\n continueOnCrash,\n cwd,\n env,\n exitOnIdle,\n logFile,\n removeControlCharactersFromStdout = false, // = !process.stdout.isTTY,\n verbose = false,\n}: {\n cli?: (string & {}) | keyof typeof CLI_CONFIGURES;\n cliArgs?: string[];\n prompt?: string;\n continueOnCrash?: boolean;\n cwd?: string;\n env?: Record<string, string>;\n exitOnIdle?: number;\n logFile?: string;\n removeControlCharactersFromStdout?: boolean;\n verbose?: boolean;\n} = {}) {\n const continueArgs = {\n codex: 'resume --last'.split(' '),\n claude: '--continue'.split(' '),\n gemini: [], // not possible yet\n };\n\n // if (verbose) {\n // console.log('calling claudeYes: ', {\n // cli,\n // continueOnCrash,\n // exitOnIdle,\n // cliArgs,\n // cwd,\n // removeControlCharactersFromStdout,\n // logFile,\n // verbose,\n // });\n // }\n // console.log(\n // `⭐ Starting ${cli}, automatically responding to yes/no prompts...`\n // );\n // console.log(\n // '⚠️ 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.'\n // );\n\n process.stdin.setRawMode?.(true); // must be called any stdout/stdin usage\n let isFatal = false; // match 'No conversation found to continue'\n const stdinReady = new ReadyManager();\n\n const shellOutputStream = new TransformStream<string, string>();\n const outputWriter = shellOutputStream.writable.getWriter();\n // const pty = await import('node-pty');\n\n // its recommened to use bun-pty in windows\n const pty = await import('node-pty')\n .catch(async () => await import('bun-pty'))\n .catch(async () =>\n DIE('Please install node-pty or bun-pty, run this: bun install bun-pty'),\n );\n\n const getPtyOptions = () => ({\n name: 'xterm-color',\n ...getTerminalDimensions(),\n cwd: cwd ?? process.cwd(),\n env: env ?? (process.env as Record<string, string>),\n });\n\n // Apply CLI specific configurations (moved to CLI_CONFIGURES)\n const cliConf = (CLI_CONFIGURES as Record<string, any>)[cli] || {};\n cliArgs = cliConf.ensureArgs?.(cliArgs) ?? cliArgs;\n const cliCommand = cliConf?.binary || cli;\n\n let shell = tryCatch(\n () => pty.spawn(cliCommand, cliArgs, getPtyOptions()),\n (error: unknown) => {\n console.error(`Fatal: Failed to start ${cliCommand}.`);\n if (cliConf?.install)\n console.error(\n `If you did not installed it yet, Please install it first: ${cliConf.install}`,\n );\n throw error;\n },\n );\n const pendingExitCode = Promise.withResolvers<number | null>();\n let pendingExitCodeValue = null;\n\n // TODO handle error if claude is not installed, show msg:\n // npm install -g @anthropic-ai/claude-code\n\n async function onData(data: string) {\n // append data to the buffer, so we can process it later\n await outputWriter.write(data);\n }\n\n shell.onData(onData);\n shell.onExit(function onExit({ exitCode }) {\n stdinReady.unready(); // start buffer stdin\n const agentCrashed = exitCode !== 0;\n const continueArg = (continueArgs as Record<string, string[]>)[cli];\n\n if (agentCrashed && continueOnCrash && continueArg) {\n if (!continueArg) {\n return console.warn(\n `continueOnCrash is only supported for ${Object.keys(continueArgs).join(', ')} currently, not ${cli}`,\n );\n }\n if (isFatal) {\n console.log(\n `${cli} crashed with \"No conversation found to continue\", exiting...`,\n );\n return pendingExitCode.resolve((pendingExitCodeValue = exitCode));\n }\n console.log(`${cli} crashed, restarting...`);\n\n shell = pty.spawn(cli, continueArg, getPtyOptions());\n shell.onData(onData);\n shell.onExit(onExit);\n return;\n }\n return pendingExitCode.resolve((pendingExitCodeValue = exitCode));\n });\n\n // when current tty resized, resize the pty\n process.stdout.on('resize', () => {\n const { cols, rows } = getTerminalDimensions(); // minimum 80 columns to avoid layout issues\n shell.resize(cols, rows); // minimum 80 columns to avoid layout issues\n });\n\n const terminalRender = new TerminalTextRender();\n const isStillWorkingQ = () =>\n terminalRender\n .render()\n .replace(/\\s+/g, ' ')\n .match(/esc to interrupt|to run in background/);\n\n const idleWaiter = new IdleWaiter();\n if (exitOnIdle)\n idleWaiter.wait(exitOnIdle).then(async () => {\n if (isStillWorkingQ()) {\n console.log(\n '[${cli}-yes] ${cli} is idle, but seems still working, not exiting yet',\n );\n return;\n }\n\n console.log('[${cli}-yes] ${cli} is idle, exiting...');\n await exitAgent();\n });\n\n // Message streaming\n sflow(fromReadable<Buffer>(process.stdin))\n .map((buffer) => buffer.toString())\n // .map((e) => e.replaceAll('\\x1a', '')) // remove ctrl+z from user's input (seems bug)\n // .forEach(e => appendFile('.cache/io.log', \"input |\" + JSON.stringify(e) + '\\n')) // for debugging\n // pipe\n .by({\n writable: new WritableStream<string>({\n write: async (data) => {\n await stdinReady.wait();\n // await idleWaiter.wait(20); // wait for idle for 200ms to avoid messing up claude's input\n shell.write(data);\n },\n }),\n readable: shellOutputStream.readable,\n })\n .forEach(() => idleWaiter.ping())\n .forEach((text) => {\n terminalRender.write(text);\n // todo: .onStatus((msg)=> shell.write(msg))\n if (process.stdin.isTTY) return; // only handle it when stdin is not tty\n if (text.includes('\\u001b[6n')) return; // only asked\n\n // todo: use terminalRender API to get cursor position when new version is available\n // xterm replies CSI row; column R if asked cursor position\n // https://en.wikipedia.org/wiki/ANSI_escape_code#:~:text=citation%20needed%5D-,xterm%20replies,-CSI%20row%C2%A0%3B\n // when agent asking position, respond with row; col\n const rendered = terminalRender.render();\n const row = rendered.split('\\n').length + 1;\n const col = (rendered.split('\\n').slice(-1)[0]?.length || 0) + 1;\n shell.write(`\\u001b[${row};${col}R`);\n })\n\n // auto-response\n .forkTo((e) =>\n e\n .map((e) => removeControlCharacters(e))\n .map((e) => e.replaceAll('\\r', '')) // remove carriage return\n .lines({ EOL: 'NONE' })\n // Generic auto-response handler driven by CLI_CONFIGURES\n .forEach(async (e, i) => {\n const conf =\n CLI_CONFIGURES[cli as keyof typeof CLI_CONFIGURES] || null;\n if (!conf) return;\n\n // ready matcher: if matched, mark stdin ready\n if (conf.ready?.some((rx: RegExp) => e.match(rx))) {\n if (cli === 'gemini' && i <= 80) return; // gemini initial noise, only after many lines\n stdinReady.ready();\n }\n\n // enter matchers: send Enter when any enter regex matches\n if (conf.enter?.some((rx: RegExp) => e.match(rx)))\n await sendEnter(300); // send Enter after 300ms idle wait\n\n // fatal matchers: set isFatal flag when matched\n if (conf.fatal?.some((rx: RegExp) => e.match(rx))) isFatal = true;\n })\n // .forEach(e => appendFile('.cache/io.log', \"output|\" + JSON.stringify(e) + '\\n')) // for debugging\n .run(),\n )\n .map((e) =>\n removeControlCharactersFromStdout ? removeControlCharacters(e) : e,\n )\n .to(fromWritable(process.stdout))\n .then(() => null); // run it immediately without await\n\n // wait for cli ready and send prompt if provided\n if (prompt)\n (async () => {\n // console.log(`[${cli}-yes] Ready to send prompt to ${cli}: ${prompt}`);\n // idleWaiter.ping();\n // console.log(\n // 'await idleWaiter.wait(1000); // wait a bit for claude to start'\n // );\n // await idleWaiter.wait(1000); // wait a bit for claude to start\n // console.log('await stdinReady.wait();');\n // await stdinReady.wait();\n // console.log(`[${cli}-yes] Waiting for ${cli} to be ready...`);\n // console.log('await idleWaiter.wait(200);');\n // await idleWaiter.wait(200);\n // console.log(`[${cli}-yes] Sending prompt to ${cli}: ${prompt}`);\n await sendMessage(prompt);\n })();\n\n const exitCode = await pendingExitCode.promise; // wait for the shell to exit\n console.log(`[${cli}-yes] ${cli} exited with code ${exitCode}`);\n\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(\n () => null,\n );\n await writeFile(logFilePath, terminalRender.render());\n }\n\n return { exitCode, logs: terminalRender.render() };\n\n async function sendEnter(waitms = 1000) {\n // wait for idle for a bit to let agent cli finish rendering\n const st = Date.now();\n\n await idleWaiter.wait(waitms);\n const et = Date.now();\n process.stdout.write(`\\ridleWaiter.wait(${waitms}) took ${et - st}ms\\r`);\n\n shell.write('\\r');\n }\n\n async function sendMessage(message: string) {\n await stdinReady.wait();\n // show in-place message: write msg and move cursor back start\n shell.write(message);\n idleWaiter.ping(); // just sent a message, wait for echo\n await sendEnter();\n }\n\n async function exitAgent() {\n continueOnCrash = false;\n // send exit command to the shell, must sleep a bit to avoid claude treat it as pasted input\n await sendMessage('/exit');\n\n // wait for shell to exit or kill it with a timeout\n let exited = false;\n await Promise.race([\n pendingExitCode.promise.then(() => (exited = true)), // resolve when shell exits\n\n // if shell doesn't exit in 5 seconds, kill it\n new Promise<void>((resolve) =>\n setTimeout(() => {\n if (exited) return; // if shell already exited, do nothing\n shell.kill(); // kill the shell process if it doesn't exit in time\n resolve();\n }, 5000),\n ), // 5 seconds timeout\n ]);\n }\n\n function getTerminalDimensions() {\n return {\n cols: Math.max(process.stdout.columns, 80),\n rows: process.stdout.rows,\n };\n }\n}\n\nexport { removeControlCharacters };\n\nfunction tryCatch<T, R>(fn: () => T, catchFn: (error: unknown) => R): T | R {\n try {\n return fn();\n } catch (error) {\n return catchFn(error);\n }\n}\n",
6
6
  "/**\n * A utility class to wait for idle periods based on activity pings.\n *\n * @example\n * const idleWaiter = new IdleWaiter();\n *\n * // Somewhere in your code, when activity occurs:\n * idleWaiter.ping();\n *\n * // To wait for an idle period of 5 seconds:\n * await idleWaiter.wait(5000);\n * console.log('System has been idle for 5 seconds');\n */\nexport class IdleWaiter {\n lastActivityTime = Date.now();\n checkInterval = 100; // Default check interval in milliseconds\n\n constructor() {\n this.ping();\n }\n\n ping() {\n this.lastActivityTime = Date.now();\n return this;\n }\n\n async wait(ms: number) {\n while (this.lastActivityTime >= Date.now() - ms)\n await new Promise((resolve) => setTimeout(resolve, this.checkInterval));\n }\n}\n",
7
7
  "export class ReadyManager {\n private isReady = false;\n private readyQueue: (() => void)[] = [];\n wait() {\n if (this.isReady) return;\n return new Promise<void>((resolve) => this.readyQueue.push(resolve));\n }\n unready() {\n this.isReady = false;\n }\n ready() {\n this.isReady = true;\n if (!this.readyQueue.length) return; // check len for performance\n this.readyQueue.splice(0).map((resolve) => resolve());\n }\n}\n",
8
8
  "export function removeControlCharacters(str: string): string {\n // Matches control characters in the C0 and C1 ranges, including Delete (U+007F)\n return str.replace(\n /[\\u001b\\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,\n '',\n );\n}\n"
9
9
  ],
10
- "mappings": "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",
11
- "debugId": "095427732AFAFB1F64756E2164756E21",
10
+ "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;;;ACQO,MAAM,WAAW;AAAA,EACtB,mBAAmB,KAAK,IAAI;AAAA,EAC5B,gBAAgB;AAAA,EAEhB,WAAW,GAAG;AAAA,IACZ,KAAK,KAAK;AAAA;AAAA,EAGZ,IAAI,GAAG;AAAA,IACL,KAAK,mBAAmB,KAAK,IAAI;AAAA,IACjC,OAAO;AAAA;AAAA,OAGH,KAAI,CAAC,IAAY;AAAA,IACrB,OAAO,KAAK,oBAAoB,KAAK,IAAI,IAAI;AAAA,MAC3C,MAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,KAAK,aAAa,CAAC;AAAA;AAE5E;;;AC9BO,MAAM,aAAa;AAAA,EAChB,UAAU;AAAA,EACV,aAA6B,CAAC;AAAA,EACtC,IAAI,GAAG;AAAA,IACL,IAAI,KAAK;AAAA,MAAS;AAAA,IAClB,OAAO,IAAI,QAAc,CAAC,YAAY,KAAK,WAAW,KAAK,OAAO,CAAC;AAAA;AAAA,EAErE,OAAO,GAAG;AAAA,IACR,KAAK,UAAU;AAAA;AAAA,EAEjB,KAAK,GAAG;AAAA,IACN,KAAK,UAAU;AAAA,IACf,IAAI,CAAC,KAAK,WAAW;AAAA,MAAQ;AAAA,IAC7B,KAAK,WAAW,OAAO,CAAC,EAAE,IAAI,CAAC,YAAY,QAAQ,CAAC;AAAA;AAExD;;;ACfO,SAAS,uBAAuB,CAAC,KAAqB;AAAA,EAE3D,OAAO,IAAI,QACT,+EACA,EACF;AAAA;;;AHKK,IAAM,iBAUT;AAAA,EACF,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,OAAO,CAAC,SAAQ;AAAA,EAClB;AAAA,EACA,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,OAAO,CAAC,KAAK;AAAA,IACb,OAAO,CAAC,YAAW,mBAAmB,0BAA0B;AAAA,IAChE,OAAO;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EACA,QAAQ;AAAA,IACN,SAAS;AAAA,IAET,OAAO,CAAC,mBAAmB;AAAA,IAC3B,OAAO,CAAC,wBAAuB;AAAA,IAC/B,OAAO,CAAC;AAAA,EACV;AAAA,EACA,OAAO;AAAA,IACL,SAAS;AAAA,IACT,OAAO,CAAC,QAAO;AAAA,IACf,OAAO,CAAC,iBAAiB,8CAA8C;AAAA,IACvE,OAAO,CAAC,qDAAqD;AAAA,IAE7D,YAAY,CAAC,SAAmB;AAAA,MAC9B,IAAI,CAAC,KAAK,SAAS,UAAU;AAAA,QAAG,OAAO,CAAC,YAAY,GAAG,IAAI;AAAA,MAC3D,OAAO;AAAA;AAAA,EAEX;AAAA,EACA,SAAS;AAAA,IACP,SAAS;AAAA,IACT,OAAO,CAAC,OAAO;AAAA,IACf,OAAO,CAAC,wBAAuB,UAAU;AAAA,IACzC,OAAO,CAAC;AAAA,EACV;AAAA,EACA,QAAQ;AAAA,IACN,SAAS;AAAA,IAET,QAAQ;AAAA,IACR,OAAO,CAAC,aAAa;AAAA,IACrB,OAAO,CAAC,kCAAiC,8BAA8B;AAAA,IACvE,OAAO,CAAC;AAAA,EACV;AACF;AA4BA,eAA8B,SAAS;AAAA,EACrC,MAAM;AAAA,EACN,UAAU,CAAC;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,oCAAoC;AAAA,EACpC,UAAU;AAAA,IAYR,CAAC,GAAG;AAAA,EACN,MAAM,eAAe;AAAA,IACnB,OAAO,gBAAgB,MAAM,GAAG;AAAA,IAChC,QAAQ,aAAa,MAAM,GAAG;AAAA,IAC9B,QAAQ,CAAC;AAAA,EACX;AAAA,EAqBA,QAAQ,MAAM,aAAa,IAAI;AAAA,EAC/B,IAAI,UAAU;AAAA,EACd,MAAM,aAAa,IAAI;AAAA,EAEvB,MAAM,oBAAoB,IAAI;AAAA,EAC9B,MAAM,eAAe,kBAAkB,SAAS,UAAU;AAAA,EAI1D,MAAM,MAAM,MAAa,mBACtB,MAAM,YAAY,MAAa,iBAAU,EACzC,MAAM,YACL,IAAI,mEAAmE,CACzE;AAAA,EAEF,MAAM,gBAAgB,OAAO;AAAA,IAC3B,MAAM;AAAA,OACH,sBAAsB;AAAA,IACzB,KAAK,OAAO,QAAQ,IAAI;AAAA,IACxB,KAAK,OAAQ,QAAQ;AAAA,EACvB;AAAA,EAGA,MAAM,UAAW,eAAuC,QAAQ,CAAC;AAAA,EACjE,UAAU,QAAQ,aAAa,OAAO,KAAK;AAAA,EAC3C,MAAM,aAAa,SAAS,UAAU;AAAA,EAEtC,IAAI,QAAQ,SACV,MAAM,IAAI,MAAM,YAAY,SAAS,cAAc,CAAC,GACpD,CAAC,UAAmB;AAAA,IAClB,QAAQ,MAAM,0BAA0B,aAAa;AAAA,IACrD,IAAI,SAAS;AAAA,MACX,QAAQ,MACN,6DAA6D,QAAQ,SACvE;AAAA,IACF,MAAM;AAAA,GAEV;AAAA,EACA,MAAM,kBAAkB,QAAQ,cAA6B;AAAA,EAC7D,IAAI,uBAAuB;AAAA,EAK3B,eAAe,MAAM,CAAC,MAAc;AAAA,IAElC,MAAM,aAAa,MAAM,IAAI;AAAA;AAAA,EAG/B,MAAM,OAAO,MAAM;AAAA,EACnB,MAAM,OAAO,SAAS,MAAM,GAAG,uBAAY;AAAA,IACzC,WAAW,QAAQ;AAAA,IACnB,MAAM,eAAe,cAAa;AAAA,IAClC,MAAM,cAAe,aAA0C;AAAA,IAE/D,IAAI,gBAAgB,mBAAmB,aAAa;AAAA,MAClD,IAAI,CAAC,aAAa;AAAA,QAChB,OAAO,QAAQ,KACb,yCAAyC,OAAO,KAAK,YAAY,EAAE,KAAK,IAAI,oBAAoB,KAClG;AAAA,MACF;AAAA,MACA,IAAI,SAAS;AAAA,QACX,QAAQ,IACN,GAAG,kEACL;AAAA,QACA,OAAO,gBAAgB,QAAS,uBAAuB,SAAS;AAAA,MAClE;AAAA,MACA,QAAQ,IAAI,GAAG,4BAA4B;AAAA,MAE3C,QAAQ,IAAI,MAAM,KAAK,aAAa,cAAc,CAAC;AAAA,MACnD,MAAM,OAAO,MAAM;AAAA,MACnB,MAAM,OAAO,MAAM;AAAA,MACnB;AAAA,IACF;AAAA,IACA,OAAO,gBAAgB,QAAS,uBAAuB,SAAS;AAAA,GACjE;AAAA,EAGD,QAAQ,OAAO,GAAG,UAAU,MAAM;AAAA,IAChC,QAAQ,MAAM,SAAS,sBAAsB;AAAA,IAC7C,MAAM,OAAO,MAAM,IAAI;AAAA,GACxB;AAAA,EAED,MAAM,iBAAiB,IAAI;AAAA,EAC3B,MAAM,kBAAkB,MACtB,eACG,OAAO,EACP,QAAQ,QAAQ,GAAG,EACnB,MAAM,uCAAuC;AAAA,EAElD,MAAM,aAAa,IAAI;AAAA,EACvB,IAAI;AAAA,IACF,WAAW,KAAK,UAAU,EAAE,KAAK,YAAY;AAAA,MAC3C,IAAI,gBAAgB,GAAG;AAAA,QACrB,QAAQ,IACN,uEACF;AAAA,QACA;AAAA,MACF;AAAA,MAEA,QAAQ,IAAI,yCAAyC;AAAA,MACrD,MAAM,UAAU;AAAA,KACjB;AAAA,EAGH,MAAM,aAAqB,QAAQ,KAAK,CAAC,EACtC,IAAI,CAAC,WAAW,OAAO,SAAS,CAAC,EAIjC,GAAG;AAAA,IACF,UAAU,IAAI,eAAuB;AAAA,MACnC,OAAO,OAAO,SAAS;AAAA,QACrB,MAAM,WAAW,KAAK;AAAA,QAEtB,MAAM,MAAM,IAAI;AAAA;AAAA,IAEpB,CAAC;AAAA,IACD,UAAU,kBAAkB;AAAA,EAC9B,CAAC,EACA,QAAQ,MAAM,WAAW,KAAK,CAAC,EAC/B,QAAQ,CAAC,SAAS;AAAA,IACjB,eAAe,MAAM,IAAI;AAAA,IAEzB,IAAI,QAAQ,MAAM;AAAA,MAAO;AAAA,IACzB,IAAI,KAAK,SAAS,SAAW;AAAA,MAAG;AAAA,IAMhC,MAAM,WAAW,eAAe,OAAO;AAAA,IACvC,MAAM,MAAM,SAAS,MAAM;AAAA,CAAI,EAAE,SAAS;AAAA,IAC1C,MAAM,OAAO,SAAS,MAAM;AAAA,CAAI,EAAE,MAAM,EAAE,EAAE,IAAI,UAAU,KAAK;AAAA,IAC/D,MAAM,MAAM,QAAU,OAAO,MAAM;AAAA,GACpC,EAGA,OAAO,CAAC,MACP,EACG,IAAI,CAAC,OAAM,wBAAwB,EAAC,CAAC,EACrC,IAAI,CAAC,OAAM,GAAE,WAAW,MAAM,EAAE,CAAC,EACjC,MAAM,EAAE,KAAK,OAAO,CAAC,EAErB,QAAQ,OAAO,IAAG,MAAM;AAAA,IACvB,MAAM,OACJ,eAAe,QAAuC;AAAA,IACxD,IAAI,CAAC;AAAA,MAAM;AAAA,IAGX,IAAI,KAAK,OAAO,KAAK,CAAC,OAAe,GAAE,MAAM,EAAE,CAAC,GAAG;AAAA,MACjD,IAAI,QAAQ,YAAY,KAAK;AAAA,QAAI;AAAA,MACjC,WAAW,MAAM;AAAA,IACnB;AAAA,IAGA,IAAI,KAAK,OAAO,KAAK,CAAC,OAAe,GAAE,MAAM,EAAE,CAAC;AAAA,MAC9C,MAAM,UAAU,GAAG;AAAA,IAGrB,IAAI,KAAK,OAAO,KAAK,CAAC,OAAe,GAAE,MAAM,EAAE,CAAC;AAAA,MAAG,UAAU;AAAA,GAC9D,EAEA,IAAI,CACT,EACC,IAAI,CAAC,MACJ,oCAAoC,wBAAwB,CAAC,IAAI,CACnE,EACC,GAAG,aAAa,QAAQ,MAAM,CAAC,EAC/B,KAAK,MAAM,IAAI;AAAA,EAGlB,IAAI;AAAA,KACD,YAAY;AAAA,MAaX,MAAM,YAAY,MAAM;AAAA,OACvB;AAAA,EAEL,MAAM,WAAW,MAAM,gBAAgB;AAAA,EACvC,QAAQ,IAAI,IAAI,YAAY,wBAAwB,UAAU;AAAA,EAE9D,IAAI,SAAS;AAAA,IACX,WAAW,QAAQ,IAAI,IAAI,qCAAqC,SAAS;AAAA,IACzE,MAAM,cAAc,KAAK,QAAQ,OAAO;AAAA,IACxC,MAAM,MAAM,KAAK,QAAQ,WAAW,GAAG,EAAE,WAAW,KAAK,CAAC,EAAE,MAC1D,MAAM,IACR;AAAA,IACA,MAAM,UAAU,aAAa,eAAe,OAAO,CAAC;AAAA,EACtD;AAAA,EAEA,OAAO,EAAE,UAAU,MAAM,eAAe,OAAO,EAAE;AAAA,EAEjD,eAAe,SAAS,CAAC,SAAS,MAAM;AAAA,IAEtC,MAAM,KAAK,KAAK,IAAI;AAAA,IAEpB,MAAM,WAAW,KAAK,MAAM;AAAA,IAC5B,MAAM,KAAK,KAAK,IAAI;AAAA,IACpB,QAAQ,OAAO,MAAM,qBAAqB,gBAAgB,KAAK,QAAQ;AAAA,IAEvE,MAAM,MAAM,IAAI;AAAA;AAAA,EAGlB,eAAe,WAAW,CAAC,SAAiB;AAAA,IAC1C,MAAM,WAAW,KAAK;AAAA,IAEtB,MAAM,MAAM,OAAO;AAAA,IACnB,WAAW,KAAK;AAAA,IAChB,MAAM,UAAU;AAAA;AAAA,EAGlB,eAAe,SAAS,GAAG;AAAA,IACzB,kBAAkB;AAAA,IAElB,MAAM,YAAY,OAAO;AAAA,IAGzB,IAAI,SAAS;AAAA,IACb,MAAM,QAAQ,KAAK;AAAA,MACjB,gBAAgB,QAAQ,KAAK,MAAO,SAAS,IAAK;AAAA,MAGlD,IAAI,QAAc,CAAC,YACjB,WAAW,MAAM;AAAA,QACf,IAAI;AAAA,UAAQ;AAAA,QACZ,MAAM,KAAK;AAAA,QACX,QAAQ;AAAA,SACP,IAAI,CACT;AAAA,IACF,CAAC;AAAA;AAAA,EAGH,SAAS,qBAAqB,GAAG;AAAA,IAC/B,OAAO;AAAA,MACL,MAAM,KAAK,IAAI,QAAQ,OAAO,SAAS,EAAE;AAAA,MACzC,MAAM,QAAQ,OAAO;AAAA,IACvB;AAAA;AAAA;AAMJ,SAAS,QAAc,CAAC,IAAa,SAAuC;AAAA,EAC1E,IAAI;AAAA,IACF,OAAO,GAAG;AAAA,IACV,OAAO,OAAO;AAAA,IACd,OAAO,QAAQ,KAAK;AAAA;AAAA;",
11
+ "debugId": "69E33BC2DDEE744C64756E2164756E21",
12
12
  "names": []
13
13
  }
package/index.ts CHANGED
@@ -11,15 +11,21 @@ import { removeControlCharacters } from './removeControlCharacters';
11
11
  export const CLI_CONFIGURES: Record<
12
12
  string,
13
13
  {
14
+ install?: string; // hint user for install command if not installed
14
15
  binary?: string; // actual binary name if different from cli
15
- ready?: RegExp; // regex matcher for stdin ready, or line index for gemini
16
+ ready?: RegExp[]; // regex matcher for stdin ready, or line index for gemini
16
17
  enter?: RegExp[]; // array of regex to match for sending Enter
17
18
  fatal?: RegExp[]; // array of regex to match for fatal errors
18
19
  ensureArgs?: (args: string[]) => string[]; // function to ensure certain args are present
19
20
  }
20
21
  > = {
22
+ grok: {
23
+ install: 'npm install -g @vibe-kit/grok-cli',
24
+ ready: [/^ +│ ❯ /],
25
+ },
21
26
  claude: {
22
- ready: /^> /, // regex matcher for stdin ready,
27
+ install: 'npm install -g @anthropic-ai/claude-code',
28
+ ready: [/^> /], // regex matcher for stdin ready,
23
29
  enter: [/❯ 1. Yes/, /❯ 1. Dark mode✔/, /Press Enter to continue…/],
24
30
  fatal: [
25
31
  /No conversation found to continue/,
@@ -27,13 +33,15 @@ export const CLI_CONFIGURES: Record<
27
33
  ],
28
34
  },
29
35
  gemini: {
36
+ install: 'npm install -g @google/gemini-cli',
30
37
  // match the agent prompt after initial lines; handled by index logic using line index
31
- ready: /Type your message/, // used with line index check
38
+ ready: [/Type your message/], // used with line index check
32
39
  enter: [/│ ● 1. Yes, allow once/],
33
40
  fatal: [],
34
41
  },
35
42
  codex: {
36
- ready: /⏎ send/,
43
+ install: 'npm install -g @openai/codex-cli',
44
+ ready: [/⏎ send/],
37
45
  enter: [/ > 1. Approve/, /> 1. Yes, allow Codex to work in this folder/],
38
46
  fatal: [/Error: The cursor position could not be read within/],
39
47
  // add to codex --search by default when not provided by the user
@@ -43,14 +51,16 @@ export const CLI_CONFIGURES: Record<
43
51
  },
44
52
  },
45
53
  copilot: {
46
- ready: /^ > /,
54
+ install: 'npm install -g @github/copilot',
55
+ ready: [/^ > /],
47
56
  enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/],
48
57
  fatal: [],
49
58
  },
50
59
  cursor: {
60
+ install: 'open https://cursor.com/ja/docs/cli/installation',
51
61
  // map logical "cursor" cli name to actual binary name
52
62
  binary: 'cursor-agent',
53
- ready: /\/ commands/,
63
+ ready: [/\/ commands/],
54
64
  enter: [/→ Run \(once\) \(y\) \(enter\)/, /▶ \[a\] Trust this workspace/],
55
65
  fatal: [],
56
66
  },
@@ -157,7 +167,17 @@ export default async function claudeYes({
157
167
  cliArgs = cliConf.ensureArgs?.(cliArgs) ?? cliArgs;
158
168
  const cliCommand = cliConf?.binary || cli;
159
169
 
160
- let shell = pty.spawn(cliCommand, cliArgs, getPtyOptions());
170
+ let shell = tryCatch(
171
+ () => pty.spawn(cliCommand, cliArgs, getPtyOptions()),
172
+ (error: unknown) => {
173
+ console.error(`Fatal: Failed to start ${cliCommand}.`);
174
+ if (cliConf?.install)
175
+ console.error(
176
+ `If you did not installed it yet, Please install it first: ${cliConf.install}`,
177
+ );
178
+ throw error;
179
+ },
180
+ );
161
181
  const pendingExitCode = Promise.withResolvers<number | null>();
162
182
  let pendingExitCodeValue = null;
163
183
 
@@ -269,34 +289,18 @@ export default async function claudeYes({
269
289
  CLI_CONFIGURES[cli as keyof typeof CLI_CONFIGURES] || null;
270
290
  if (!conf) return;
271
291
 
272
- try {
273
- // ready matcher: if matched, mark stdin ready
274
- if (conf.ready) {
275
- // special-case gemini to avoid initial prompt noise: only after many lines
276
- if (cli === 'gemini' && conf.ready instanceof RegExp) {
277
- if (e.match(conf.ready) && i > 80) return stdinReady.ready();
278
- } else if (e.match(conf.ready)) {
279
- return stdinReady.ready();
280
- }
281
- }
282
-
283
- // enter matchers: send Enter when any enter regex matches
284
- if (conf.enter && Array.isArray(conf.enter)) {
285
- for (const rx of conf.enter) {
286
- if (e.match(rx)) return await sendEnter();
287
- }
288
- }
289
-
290
- // fatal matchers: set isFatal flag when matched
291
- if (conf.fatal && Array.isArray(conf.fatal)) {
292
- for (const rx of conf.fatal) {
293
- if (e.match(rx)) return (isFatal = true);
294
- }
295
- }
296
- } catch (err) {
297
- // defensive: if e.match throws (e.g., not a string), ignore
298
- return;
292
+ // ready matcher: if matched, mark stdin ready
293
+ if (conf.ready?.some((rx: RegExp) => e.match(rx))) {
294
+ if (cli === 'gemini' && i <= 80) return; // gemini initial noise, only after many lines
295
+ stdinReady.ready();
299
296
  }
297
+
298
+ // enter matchers: send Enter when any enter regex matches
299
+ if (conf.enter?.some((rx: RegExp) => e.match(rx)))
300
+ await sendEnter(300); // send Enter after 300ms idle wait
301
+
302
+ // fatal matchers: set isFatal flag when matched
303
+ if (conf.fatal?.some((rx: RegExp) => e.match(rx))) isFatal = true;
300
304
  })
301
305
  // .forEach(e => appendFile('.cache/io.log', "output|" + JSON.stringify(e) + '\n')) // for debugging
302
306
  .run(),
@@ -388,3 +392,11 @@ export default async function claudeYes({
388
392
  }
389
393
 
390
394
  export { removeControlCharacters };
395
+
396
+ function tryCatch<T, R>(fn: () => T, catchFn: (error: unknown) => R): T | R {
397
+ try {
398
+ return fn();
399
+ } catch (error) {
400
+ return catchFn(error);
401
+ }
402
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-yes",
3
- "version": "1.20.0",
3
+ "version": "1.21.0",
4
4
  "description": "A wrapper tool that automates interactions with the Claude CLI by automatically handling common prompts and responses.",
5
5
  "keywords": [
6
6
  "claude",