claude-yolo 1.7.0 → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +6 -0
- package/.cursor/mcp.json +0 -0
- package/.cursor/rules/cursor-tools.mdc +161 -0
- package/.cursorindexingignore +3 -0
- package/.mcp.json +13 -0
- package/.specstory/history/.what-is-this.md +54 -0
- package/.specstory/history/2025-02-26_13-24-checking-recent-tweets.md +124 -0
- package/.specstory/history/2025-03-10_15-17-sending-a-yo-to-my-server.md +32 -0
- package/.specstory/history/2025-03-10_17-20-sending-a-simple-yo-message.md +104 -0
- package/.specstory/history/2025-03-12_08-37-documentation-retrieval-for-repomix-repo.md +32 -0
- package/.specstory/history/2025-03-12_09-23-interactive-browser-session-setup.md +7864 -0
- package/.specstory/history/2025-03-12_17-16-chat-name-generation.md +430 -0
- package/.specstory/history/2025-03-13_01-22-python-pi-calculation-and-notification.md +254 -0
- package/.specstory/history/2025-03-13_22-46-server-update-for-eric.md +35 -0
- package/.specstory/history/2025-03-13_23-02-sending-a-simple-yo-message.md +18 -0
- package/.specstory/history/2025-03-13_23-10-casual-greetings.md +80 -0
- package/.specstory/history/2025-03-14_13-07-casual-greetings-sending-a-yo.md +44 -0
- package/.specstory/history/2025-03-14_13-28-casual-greetings.md +924 -0
- package/.specstory/history/2025-03-14_13-37-sending-a-yo-message.md +34 -0
- package/.specstory/history/2025-03-14_13-48-casual-greetings.md +76 -0
- package/.specstory/history/2025-03-14_13-53-casual-greetings.md +44 -0
- package/.specstory/history/2025-03-14_13-57-casual-greetings.md +64 -0
- package/.specstory/history/2025-03-14_21-41-simple-greeting-send-a-yo.md +34 -0
- package/.specstory/history/2025-03-15_13-44-casual-greeting-request.md +26 -0
- package/.specstory/history/2025-03-16_21-17-using-curl-to-fetch-url-content.md +3728 -0
- package/.specstory/history/2025-10-25_08-17-create-a-new-repository-with-gh-cli.md +173 -0
- package/.specstory/history/casual-greetings-1.md +32 -0
- package/AGENTS.md +1 -0
- package/README.md +104 -24
- package/bin/cl +113 -0
- package/bin/claude-yolo.js +191 -16
- package/demo.txt +1 -0
- package/package.json +14 -10
- package/test.txt +1 -0
- package/yolo-test.txt +1 -0
package/bin/claude-yolo.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
import fs from 'fs';
|
|
5
5
|
import path from 'path';
|
|
6
|
+
import os from 'os';
|
|
6
7
|
import { createRequire } from 'module';
|
|
7
8
|
import { fileURLToPath } from 'url';
|
|
8
9
|
import { execSync } from 'child_process';
|
|
@@ -12,9 +13,27 @@ import readline from 'readline';
|
|
|
12
13
|
const RED = '\x1b[31m';
|
|
13
14
|
const YELLOW = '\x1b[33m';
|
|
14
15
|
const CYAN = '\x1b[36m';
|
|
16
|
+
const GREEN = '\x1b[32m';
|
|
15
17
|
const RESET = '\x1b[0m';
|
|
16
18
|
const BOLD = '\x1b[1m';
|
|
17
19
|
|
|
20
|
+
// Path to persistent state file
|
|
21
|
+
const stateFile = path.join(os.homedir(), '.claude_yolo_state');
|
|
22
|
+
|
|
23
|
+
// Function to get current mode from state file
|
|
24
|
+
function getMode() {
|
|
25
|
+
try {
|
|
26
|
+
return fs.readFileSync(stateFile, 'utf8').trim();
|
|
27
|
+
} catch {
|
|
28
|
+
return 'YOLO'; // Default mode
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Function to set mode in state file
|
|
33
|
+
function setMode(mode) {
|
|
34
|
+
fs.writeFileSync(stateFile, mode);
|
|
35
|
+
}
|
|
36
|
+
|
|
18
37
|
// Debug logging function that only logs if DEBUG env var is set
|
|
19
38
|
const debug = (message) => {
|
|
20
39
|
if (process.env.DEBUG) {
|
|
@@ -30,20 +49,21 @@ function askForConsent() {
|
|
|
30
49
|
output: process.stdout
|
|
31
50
|
});
|
|
32
51
|
|
|
33
|
-
console.log(`\n${BOLD}${YELLOW}🔥 CLAUDE-YOLO
|
|
52
|
+
console.log(`\n${BOLD}${YELLOW}🔥 CLAUDE-YOLO CONSENT REQUIRED 🔥${RESET}\n`);
|
|
34
53
|
console.log(`${CYAN}----------------------------------------${RESET}`);
|
|
35
54
|
console.log(`${BOLD}What is claude-yolo?${RESET}`);
|
|
36
55
|
console.log(`This package creates a wrapper around the official Claude CLI tool that:`);
|
|
37
56
|
console.log(` 1. ${RED}BYPASSES safety checks${RESET} by automatically adding the --dangerously-skip-permissions flag`);
|
|
38
57
|
console.log(` 2. Automatically updates to the latest Claude CLI version`);
|
|
39
|
-
console.log(` 3. Adds colorful YOLO-themed loading messages
|
|
58
|
+
console.log(` 3. Adds colorful YOLO-themed loading messages`);
|
|
59
|
+
console.log(` 4. ${GREEN}NOW SUPPORTS SAFE MODE${RESET} with --safe flag\n`);
|
|
40
60
|
|
|
41
61
|
console.log(`${BOLD}${RED}⚠️ IMPORTANT SECURITY WARNING ⚠️${RESET}`);
|
|
42
62
|
console.log(`The ${BOLD}--dangerously-skip-permissions${RESET} flag was designed for use in containers`);
|
|
43
63
|
console.log(`and bypasses important safety checks. This includes ignoring file access`);
|
|
44
64
|
console.log(`permissions that protect your system and privacy.\n`);
|
|
45
65
|
|
|
46
|
-
console.log(`${BOLD}By using claude-yolo:${RESET}`);
|
|
66
|
+
console.log(`${BOLD}By using claude-yolo in YOLO mode:${RESET}`);
|
|
47
67
|
console.log(` • You acknowledge these safety checks are being bypassed`);
|
|
48
68
|
console.log(` • You understand this may allow Claude CLI to access sensitive files`);
|
|
49
69
|
console.log(` • You accept full responsibility for any security implications\n`);
|
|
@@ -94,7 +114,29 @@ async function checkForUpdates() {
|
|
|
94
114
|
const dependencies = packageJson.dependencies || {};
|
|
95
115
|
const currentVersion = dependencies['@anthropic-ai/claude-code'];
|
|
96
116
|
|
|
97
|
-
debug(`
|
|
117
|
+
debug(`Claude version from package.json: ${currentVersion}`);
|
|
118
|
+
|
|
119
|
+
// Get the global Claude version if available
|
|
120
|
+
let globalVersion;
|
|
121
|
+
if (globalClaudeDir) {
|
|
122
|
+
try {
|
|
123
|
+
const globalPackageJsonPath = path.join(globalClaudeDir, 'package.json');
|
|
124
|
+
if (fs.existsSync(globalPackageJsonPath)) {
|
|
125
|
+
const globalPackageJson = JSON.parse(fs.readFileSync(globalPackageJsonPath, 'utf8'));
|
|
126
|
+
globalVersion = globalPackageJson.version;
|
|
127
|
+
debug(`Global Claude version: ${globalVersion}`);
|
|
128
|
+
|
|
129
|
+
// If global version is latest, inform user
|
|
130
|
+
if (globalVersion === latestVersion) {
|
|
131
|
+
debug(`Global Claude installation is already the latest version`);
|
|
132
|
+
} else if (globalVersion && latestVersion) {
|
|
133
|
+
debug(`Global Claude installation (${globalVersion}) differs from latest (${latestVersion})`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
} catch (err) {
|
|
137
|
+
debug(`Error getting global Claude version: ${err.message}`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
98
140
|
|
|
99
141
|
// If using a specific version (not "latest"), and it's out of date, update
|
|
100
142
|
if (currentVersion !== "latest" && currentVersion !== latestVersion) {
|
|
@@ -119,22 +161,123 @@ async function checkForUpdates() {
|
|
|
119
161
|
}
|
|
120
162
|
}
|
|
121
163
|
|
|
122
|
-
//
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
164
|
+
// Try to find global installation of Claude CLI first
|
|
165
|
+
let globalClaudeDir;
|
|
166
|
+
try {
|
|
167
|
+
const globalNodeModules = execSync('npm -g root').toString().trim();
|
|
168
|
+
debug(`Global node_modules: ${globalNodeModules}`);
|
|
169
|
+
const potentialGlobalDir = path.join(globalNodeModules, '@anthropic-ai', 'claude-code');
|
|
170
|
+
|
|
171
|
+
if (fs.existsSync(potentialGlobalDir)) {
|
|
172
|
+
globalClaudeDir = potentialGlobalDir;
|
|
173
|
+
debug(`Found global Claude installation at: ${globalClaudeDir}`);
|
|
130
174
|
}
|
|
175
|
+
} catch (error) {
|
|
176
|
+
debug(`Error finding global Claude installation: ${error.message}`);
|
|
131
177
|
}
|
|
132
178
|
|
|
133
|
-
|
|
179
|
+
// Path to the local Claude CLI installation
|
|
180
|
+
const localClaudeDir = path.join(nodeModulesDir, 'node_modules', '@anthropic-ai', 'claude-code');
|
|
181
|
+
|
|
182
|
+
// For AGENTS mode, always use LOCAL installation to ensure patches work correctly
|
|
183
|
+
// Global installation may have different minified variable names
|
|
184
|
+
const claudeDir = localClaudeDir;
|
|
185
|
+
debug(`Using Claude installation from: ${claudeDir}`);
|
|
186
|
+
debug(`Using ${claudeDir === globalClaudeDir ? 'GLOBAL' : 'LOCAL'} Claude installation`);
|
|
187
|
+
|
|
188
|
+
// Check for both .js and .mjs versions of the CLI
|
|
189
|
+
let mjs = path.join(claudeDir, 'cli.mjs');
|
|
190
|
+
let js = path.join(claudeDir, 'cli.js');
|
|
191
|
+
let originalCliPath;
|
|
192
|
+
let yoloCliPath;
|
|
193
|
+
|
|
194
|
+
if (fs.existsSync(js)) {
|
|
195
|
+
originalCliPath = js;
|
|
196
|
+
yoloCliPath = path.join(claudeDir, 'cli-yolo.js');
|
|
197
|
+
debug(`Found Claude CLI at ${originalCliPath} (js version)`);
|
|
198
|
+
} else if (fs.existsSync(mjs)) {
|
|
199
|
+
originalCliPath = mjs;
|
|
200
|
+
yoloCliPath = path.join(claudeDir, 'cli-yolo.mjs');
|
|
201
|
+
debug(`Found Claude CLI at ${originalCliPath} (mjs version)`);
|
|
202
|
+
} else {
|
|
203
|
+
console.error(`Error: Claude CLI not found in ${claudeDir}. Make sure @anthropic-ai/claude-code is installed.`);
|
|
204
|
+
process.exit(1);
|
|
205
|
+
}
|
|
134
206
|
const consentFlagPath = path.join(claudeDir, '.claude-yolo-consent');
|
|
135
207
|
|
|
136
208
|
// Main function to run the application
|
|
137
209
|
async function run() {
|
|
210
|
+
// Handle mode commands first
|
|
211
|
+
const args = process.argv.slice(2);
|
|
212
|
+
if (args[0] === 'mode') {
|
|
213
|
+
if (args[1] === 'yolo') {
|
|
214
|
+
console.log(`${YELLOW}🔥 Switching to YOLO mode...${RESET}`);
|
|
215
|
+
console.log(`${RED}⚠️ WARNING: All safety checks will be DISABLED!${RESET}`);
|
|
216
|
+
setMode('YOLO');
|
|
217
|
+
console.log(`${YELLOW}✓ YOLO mode activated${RESET}`);
|
|
218
|
+
return;
|
|
219
|
+
} else if (args[1] === 'safe') {
|
|
220
|
+
console.log(`${CYAN}🛡️ Switching to SAFE mode...${RESET}`);
|
|
221
|
+
console.log(`${GREEN}✓ Safety checks will be enabled${RESET}`);
|
|
222
|
+
setMode('SAFE');
|
|
223
|
+
console.log(`${CYAN}✓ SAFE mode activated${RESET}`);
|
|
224
|
+
return;
|
|
225
|
+
} else {
|
|
226
|
+
const currentMode = getMode();
|
|
227
|
+
console.log(`Current mode: ${currentMode === 'YOLO' ? YELLOW : CYAN}${currentMode}${RESET}`);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Check for --safe or --no-yolo flags
|
|
233
|
+
const safeMode = process.argv.includes('--safe') ||
|
|
234
|
+
process.argv.includes('--no-yolo') ||
|
|
235
|
+
getMode() === 'SAFE';
|
|
236
|
+
|
|
237
|
+
if (safeMode) {
|
|
238
|
+
// Remove our flags before passing to original CLI
|
|
239
|
+
process.argv = process.argv.filter(arg =>
|
|
240
|
+
arg !== '--safe' && arg !== '--no-yolo'
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
console.log(`${CYAN}[SAFE] Running Claude in SAFE mode${RESET}`);
|
|
244
|
+
|
|
245
|
+
// Update if needed
|
|
246
|
+
await checkForUpdates();
|
|
247
|
+
|
|
248
|
+
// Ensure original CLI exists
|
|
249
|
+
if (!fs.existsSync(originalCliPath)) {
|
|
250
|
+
console.error(`Error: ${originalCliPath} not found. Make sure @anthropic-ai/claude-code is installed.`);
|
|
251
|
+
process.exit(1);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Run original CLI without modifications
|
|
255
|
+
await import(originalCliPath);
|
|
256
|
+
return; // Exit early
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// YOLO MODE continues below
|
|
260
|
+
console.log(`${YELLOW}[YOLO] Running Claude in YOLO mode${RESET}`);
|
|
261
|
+
|
|
262
|
+
// Enable bypass permissions mode for YOLO mode (allows auto-accept of plans)
|
|
263
|
+
if (!process.argv.includes('--dangerously-skip-permissions')) {
|
|
264
|
+
process.argv.push('--dangerously-skip-permissions');
|
|
265
|
+
debug("Added --dangerously-skip-permissions flag for YOLO mode");
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Temporarily fake non-root for YOLO mode
|
|
269
|
+
if (process.getuid && process.getuid() === 0) {
|
|
270
|
+
console.log(`${YELLOW}⚠️ Running as root - applying YOLO bypass...${RESET}`);
|
|
271
|
+
// Store original getuid
|
|
272
|
+
const originalGetuid = process.getuid;
|
|
273
|
+
// Override getuid to return non-root
|
|
274
|
+
process.getuid = () => 1000; // Fake regular user ID
|
|
275
|
+
// Restore after a delay to allow CLI to start
|
|
276
|
+
setTimeout(() => {
|
|
277
|
+
process.getuid = originalGetuid;
|
|
278
|
+
}, 100);
|
|
279
|
+
}
|
|
280
|
+
|
|
138
281
|
// Check and update Claude package first
|
|
139
282
|
await checkForUpdates();
|
|
140
283
|
|
|
@@ -167,9 +310,10 @@ async function run() {
|
|
|
167
310
|
// Read the original CLI file content
|
|
168
311
|
let cliContent = fs.readFileSync(originalCliPath, 'utf8');
|
|
169
312
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
313
|
+
if (claudeDir === localClaudeDir) {
|
|
314
|
+
cliContent = cliContent.replace(/"punycode"/g, '"punycode/"');
|
|
315
|
+
debug('Replaced all instances of "punycode" with "punycode/"');
|
|
316
|
+
}
|
|
173
317
|
|
|
174
318
|
// Replace getIsDocker() calls with true
|
|
175
319
|
cliContent = cliContent.replace(/[a-zA-Z0-9_]*\.getIsDocker\(\)/g, 'true');
|
|
@@ -179,6 +323,37 @@ async function run() {
|
|
|
179
323
|
cliContent = cliContent.replace(/[a-zA-Z0-9_]*\.hasInternetAccess\(\)/g, 'false');
|
|
180
324
|
debug("Replaced all instances of *.hasInternetAccess() with false");
|
|
181
325
|
|
|
326
|
+
// Replace root check patterns
|
|
327
|
+
// Pattern 1: process.getuid() === 0
|
|
328
|
+
cliContent = cliContent.replace(/process\.getuid\(\)\s*===\s*0/g, 'false');
|
|
329
|
+
debug("Replaced process.getuid() === 0 checks with false");
|
|
330
|
+
|
|
331
|
+
// Pattern 2: process.getuid?.() === 0
|
|
332
|
+
cliContent = cliContent.replace(/process\.getuid\?\.\(\)\s*===\s*0/g, 'false');
|
|
333
|
+
debug("Replaced process.getuid?.() === 0 checks with false");
|
|
334
|
+
|
|
335
|
+
// Pattern 3: getuid() === 0 (with any variable)
|
|
336
|
+
cliContent = cliContent.replace(/(\w+)\.getuid\(\)\s*===\s*0/g, 'false');
|
|
337
|
+
debug("Replaced all getuid() === 0 checks with false");
|
|
338
|
+
|
|
339
|
+
// Pattern 4: Replace any EUID checks
|
|
340
|
+
cliContent = cliContent.replace(/process\.geteuid\(\)\s*===\s*0/g, 'false');
|
|
341
|
+
cliContent = cliContent.replace(/process\.geteuid\?\.\(\)\s*===\s*0/g, 'false');
|
|
342
|
+
debug("Replaced geteuid() checks with false");
|
|
343
|
+
|
|
344
|
+
// Auto-accept plan mode confirmation
|
|
345
|
+
// Inject a useEffect that automatically triggers "yes-bypass-permissions" when:
|
|
346
|
+
// - bypass permissions mode is available (G.toolPermissionContext.isBypassPermissionsModeAvailable)
|
|
347
|
+
// - there's a valid plan (!F means plan is not empty)
|
|
348
|
+
const planAutoAcceptPatch = `k5.useEffect(()=>{if(G.toolPermissionContext.isBypassPermissionsModeAvailable&&!F){N("yes-bypass-permissions")}},[]);`;
|
|
349
|
+
const targetString = 'let M=Md(),R=M?oH(M):null';
|
|
350
|
+
if (cliContent.includes(targetString)) {
|
|
351
|
+
cliContent = cliContent.replace(targetString, targetString + ';' + planAutoAcceptPatch);
|
|
352
|
+
debug("Patched plan mode to auto-accept when bypass permissions is available");
|
|
353
|
+
} else {
|
|
354
|
+
debug("WARNING: Could not find target string for plan auto-accept patch");
|
|
355
|
+
}
|
|
356
|
+
|
|
182
357
|
// Add warning message
|
|
183
358
|
console.log(`${YELLOW}🔥 YOLO MODE ACTIVATED 🔥${RESET}`);
|
|
184
359
|
|
package/demo.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
goodbye world
|
package/package.json
CHANGED
|
@@ -1,34 +1,38 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-yolo",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.9.1",
|
|
4
|
+
"description": "Claude CLI wrapper with YOLO mode (bypass safety) and SAFE mode support, auto-updates, and colorful loading messages",
|
|
5
5
|
"bin": {
|
|
6
|
-
"claude-yolo": "./bin/claude-yolo.js"
|
|
6
|
+
"claude-yolo": "./bin/claude-yolo.js",
|
|
7
|
+
"cl": "./bin/cl"
|
|
7
8
|
},
|
|
8
9
|
"dependencies": {
|
|
9
|
-
"@anthropic-ai/claude-code": "0.
|
|
10
|
-
"punycode": "
|
|
10
|
+
"@anthropic-ai/claude-code": "2.0.76",
|
|
11
|
+
"punycode": "2.3.1"
|
|
11
12
|
},
|
|
12
13
|
"type": "module",
|
|
13
14
|
"scripts": {
|
|
15
|
+
"postinstall": "chmod +x ./bin/cl"
|
|
14
16
|
},
|
|
15
17
|
"repository": {
|
|
16
18
|
"type": "git",
|
|
17
|
-
"url": "git+https://github.com/
|
|
19
|
+
"url": "git+https://github.com/maxparez/claude-yolo.git"
|
|
18
20
|
},
|
|
19
21
|
"keywords": [
|
|
20
22
|
"claude",
|
|
21
23
|
"cli",
|
|
22
24
|
"anthropic",
|
|
23
25
|
"wrapper",
|
|
24
|
-
"yolo"
|
|
26
|
+
"yolo",
|
|
27
|
+
"safe-mode",
|
|
28
|
+
"permissions"
|
|
25
29
|
],
|
|
26
|
-
"author": "eastlondoner",
|
|
30
|
+
"author": "eastlondoner (fork by maxparez)",
|
|
27
31
|
"license": "MIT",
|
|
28
32
|
"bugs": {
|
|
29
|
-
"url": "https://github.com/
|
|
33
|
+
"url": "https://github.com/maxparez/claude-yolo/issues"
|
|
30
34
|
},
|
|
31
|
-
"homepage": "https://github.com/
|
|
35
|
+
"homepage": "https://github.com/maxparez/claude-yolo#readme",
|
|
32
36
|
"engines": {
|
|
33
37
|
"node": ">=14.16"
|
|
34
38
|
}
|
package/test.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
hello world
|
package/yolo-test.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
YOLO mode works
|