Skip to content

Commit c637ac9

Browse files
committed
feat(index.ts): add continueOnCrash option to yesClaude function to allow automatic restart on crash
refactor(index.ts): clean up commented code and improve readability of yesClaude function
1 parent aa6ab27 commit c637ac9

File tree

1 file changed

+23
-17
lines changed

1 file changed

+23
-17
lines changed

index.ts

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,13 @@ async function main() {
1414
// node-pty is not supported in bun, so we use node.js to run this script
1515
}
1616

17-
export default async function yesClaude({ exitOnIdle, claudeArgs = [] }: { exitOnIdle?: boolean | number, claudeArgs?: string[] } = {}) {
17+
export default async function yesClaude({ continueOnCrash, exitOnIdle, claudeArgs = [] }: { continueOnCrash?: boolean, exitOnIdle?: boolean | number, claudeArgs?: string[] } = {}) {
1818
const defaultTimeout = 5e3; // 5 seconds idle timeout
1919
const idleTimeout = typeof exitOnIdle === 'number' ? exitOnIdle : defaultTimeout;
2020

2121
console.log('⭐ Starting claude, automatically responding to yes/no prompts...');
2222
console.log('⚠️ 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.');
2323

24-
// if (!process.stdin.isTTY) {
25-
// console.error('Error: This script requires a TTY (terminal) input. Please run it in a terminal.');
26-
// console.error('If you want to use prompts, try run:')
27-
// console.error(' yes-claude "your prompt here"');
28-
// return;
29-
// }
30-
3124
process.stdin.setRawMode?.(true) //must be called any stdout/stdin usage
3225
const prefix = '' // "YESC|"
3326
const PREFIXLENGTH = prefix.length;
@@ -38,12 +31,11 @@ export default async function yesClaude({ exitOnIdle, claudeArgs = [] }: { exitO
3831
// 2. spawn a 'claude --continue'
3932
// 3. when new process it's ready, re-attach the into new process (in shellStdio, pipe new process stdin/stdout to )
4033
// 4. if it crashes again, exit the process
41-
const continueOnCrashFlag = "--continue-on-crash";
4234

4335
const shellOutputStream = new TransformStream<string, string>()
4436
const outputWriter = shellOutputStream.writable.getWriter()
4537

46-
const shell = pty.spawn('claude', claudeArgs, {
38+
let shell = pty.spawn('claude', claudeArgs, {
4739
cols: process.stdout.columns - PREFIXLENGTH,
4840
rows: process.stdout.rows,
4941
cwd: process.cwd(),
@@ -52,14 +44,28 @@ export default async function yesClaude({ exitOnIdle, claudeArgs = [] }: { exitO
5244
// TODO handle error if claude is not installed, show msg:
5345
// npm install -g @anthropic-ai/claude-code
5446

55-
// when claude process exits, exit the main process with the same exit code
56-
shell.onExit(({ exitCode }) => {
57-
void process.exit(exitCode)
58-
})
59-
shell.onData(async (data) => {
47+
async function onData(data: string) {
6048
// append data to the buffer, so we can process it later
6149
await outputWriter.write(data);
62-
})
50+
}
51+
shell.onData(onData)
52+
// when claude process exits, exit the main process with the same exit code
53+
shell.onExit(function onExit({ exitCode }) {
54+
if (continueOnCrash) {
55+
if (exitCode !== 0) {
56+
console.log('Claude crashed, restarting...');
57+
shell = pty.spawn('claude', ['continue', '--continue'], {
58+
cols: process.stdout.columns - PREFIXLENGTH,
59+
rows: process.stdout.rows,
60+
cwd: process.cwd(),
61+
env: process.env,
62+
});
63+
shell.onData(onData)
64+
shell.onExit(onExit);
65+
}
66+
}
67+
void process.exit(exitCode);
68+
});
6369

6470
const exitClaudeCode = async () => {
6571
// send exit command to the shell, must sleep a bit to avoid claude treat it as pasted input
@@ -123,7 +129,7 @@ export default async function yesClaude({ exitOnIdle, claudeArgs = [] }: { exitO
123129
)
124130
.replaceAll(/.*(?:\r\n?|\r?\n)/g, (line) => prefix + line) // add prefix
125131
.forEach(() => idleWatcher.ping()) // ping the idle watcher on output for last active time to keep track of claude status
126-
// .map(e => !process.stdout.isTTY ? removeControlCharacters(e) : (e)) // remove control characters if output is not a TTY
132+
.map(e => !process.stdout.isTTY ? removeControlCharacters(e) : (e)) // remove control characters if output is not a TTY
127133
.to(fromWritable(process.stdout));
128134
}
129135

0 commit comments

Comments
 (0)