claude-yolo-extended 1.9.4 → 1.9.5
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/.editorconfig +21 -0
- package/.prettierrc +8 -0
- package/AI_HANDOFF.md +10 -6
- package/CONTRIBUTING.md +84 -0
- package/SECURITY.md +36 -0
- package/bin/ascii-art.js +3 -10
- package/bin/cl +9 -9
- package/bin/cl.js +77 -40
- package/bin/claude-yolo.js +494 -204
- package/eslint.config.js +25 -0
- package/jest.config.js +9 -0
- package/lib/constants.js +97 -0
- package/package.json +17 -1
- package/postinstall.js +1 -7
- package/preuninstall.js +77 -0
- package/tests/constants.test.js +146 -0
package/.editorconfig
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# EditorConfig helps maintain consistent coding styles
|
|
2
|
+
# https://editorconfig.org
|
|
3
|
+
|
|
4
|
+
root = true
|
|
5
|
+
|
|
6
|
+
[*]
|
|
7
|
+
charset = utf-8
|
|
8
|
+
end_of_line = lf
|
|
9
|
+
indent_style = space
|
|
10
|
+
indent_size = 2
|
|
11
|
+
insert_final_newline = true
|
|
12
|
+
trim_trailing_whitespace = true
|
|
13
|
+
|
|
14
|
+
[*.md]
|
|
15
|
+
trim_trailing_whitespace = false
|
|
16
|
+
|
|
17
|
+
[*.json]
|
|
18
|
+
indent_size = 2
|
|
19
|
+
|
|
20
|
+
[Makefile]
|
|
21
|
+
indent_style = tab
|
package/.prettierrc
ADDED
package/AI_HANDOFF.md
CHANGED
|
@@ -2,12 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
## Current State
|
|
4
4
|
* **Last Updated:** 2025-12-26
|
|
5
|
-
* **Version:** 1.9.
|
|
6
|
-
* **Status:**
|
|
5
|
+
* **Version:** 1.9.4 (ready for 1.9.5)
|
|
6
|
+
* **Status:** All verification complete, ready to publish
|
|
7
7
|
|
|
8
|
-
##
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
## Verification Results
|
|
9
|
+
- npm install: 331 packages, 0 vulnerabilities
|
|
10
|
+
- npm test: 14/14 tests passed
|
|
11
|
+
- npm run lint: 0 errors
|
|
12
|
+
- npm run format: Applied to 4 files
|
|
11
13
|
|
|
12
14
|
## NEXT STEPS (Resume Work Here)
|
|
13
|
-
1. [ ]
|
|
15
|
+
1. [ ] Run `npm version patch` to bump to 1.9.5
|
|
16
|
+
2. [ ] Run `git push origin main --tags` to push changes
|
|
17
|
+
3. [ ] Delete CODE_REVIEW_TASKS.md after successful publish
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Contributing to Claude YOLO Extended
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing!
|
|
4
|
+
|
|
5
|
+
## Development Setup
|
|
6
|
+
|
|
7
|
+
1. Clone the repository:
|
|
8
|
+
```bash
|
|
9
|
+
git clone https://github.com/jslitzkerttcu/claude-yolo.git
|
|
10
|
+
cd claude-yolo
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
2. Install dependencies:
|
|
14
|
+
```bash
|
|
15
|
+
npm install
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
3. Link for local development:
|
|
19
|
+
```bash
|
|
20
|
+
npm link
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Development Workflow
|
|
24
|
+
|
|
25
|
+
### Running the Tool
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Run in YOLO mode
|
|
29
|
+
claude-yolo-extended
|
|
30
|
+
|
|
31
|
+
# Run in SAFE mode
|
|
32
|
+
claude-yolo-extended --safe
|
|
33
|
+
|
|
34
|
+
# Switch modes
|
|
35
|
+
claude-yolo-extended mode yolo
|
|
36
|
+
claude-yolo-extended mode safe
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Code Quality
|
|
40
|
+
|
|
41
|
+
Before submitting a PR, ensure:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Run linting
|
|
45
|
+
npm run lint
|
|
46
|
+
|
|
47
|
+
# Run tests
|
|
48
|
+
npm test
|
|
49
|
+
|
|
50
|
+
# Check formatting
|
|
51
|
+
npm run format:check
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Commit Guidelines
|
|
55
|
+
|
|
56
|
+
- Use conventional commit messages
|
|
57
|
+
- Keep commits focused and atomic
|
|
58
|
+
- Reference issues when applicable
|
|
59
|
+
|
|
60
|
+
### Pull Request Process
|
|
61
|
+
|
|
62
|
+
1. Fork the repository
|
|
63
|
+
2. Create a feature branch
|
|
64
|
+
3. Make your changes
|
|
65
|
+
4. Run linting and tests
|
|
66
|
+
5. Submit a pull request
|
|
67
|
+
|
|
68
|
+
## Project Structure
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
claude-yolo/
|
|
72
|
+
├── bin/ # CLI entry points
|
|
73
|
+
│ ├── claude-yolo.js # Main wrapper
|
|
74
|
+
│ ├── cl.js # cl command wrapper
|
|
75
|
+
│ └── ascii-art.js # ASCII art and status displays
|
|
76
|
+
├── lib/ # Shared modules
|
|
77
|
+
│ └── constants.js # Shared constants and utilities
|
|
78
|
+
├── tests/ # Test files
|
|
79
|
+
└── package.json
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Questions?
|
|
83
|
+
|
|
84
|
+
Open an issue on GitHub if you have questions or suggestions.
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported Versions
|
|
4
|
+
|
|
5
|
+
| Version | Supported |
|
|
6
|
+
| ------- | ------------------ |
|
|
7
|
+
| 1.9.x | :white_check_mark: |
|
|
8
|
+
| < 1.9 | :x: |
|
|
9
|
+
|
|
10
|
+
## Reporting a Vulnerability
|
|
11
|
+
|
|
12
|
+
If you discover a security vulnerability within this project, please report it by opening an issue on GitHub or by emailing the maintainer directly.
|
|
13
|
+
|
|
14
|
+
**Please do not publicly disclose the vulnerability until it has been addressed.**
|
|
15
|
+
|
|
16
|
+
### What to Include
|
|
17
|
+
|
|
18
|
+
- Description of the vulnerability
|
|
19
|
+
- Steps to reproduce
|
|
20
|
+
- Potential impact
|
|
21
|
+
- Suggested fix (if any)
|
|
22
|
+
|
|
23
|
+
## Security Considerations
|
|
24
|
+
|
|
25
|
+
This package modifies the Claude CLI to bypass safety checks when running in YOLO mode. By design, this introduces security risks that users should be aware of:
|
|
26
|
+
|
|
27
|
+
1. **File Access**: In YOLO mode, Claude CLI can access any file without permission prompts
|
|
28
|
+
2. **Command Execution**: Safety prompts for potentially dangerous operations are bypassed
|
|
29
|
+
3. **Root Detection**: Root user checks are bypassed to allow running as root
|
|
30
|
+
|
|
31
|
+
### Recommendations
|
|
32
|
+
|
|
33
|
+
- Only use YOLO mode in trusted, isolated environments
|
|
34
|
+
- Never use YOLO mode with sensitive data or in production
|
|
35
|
+
- Use SAFE mode for normal development work
|
|
36
|
+
- Review Claude's actions carefully when in YOLO mode
|
package/bin/ascii-art.js
CHANGED
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
const RED = '\x1b[31m';
|
|
3
|
-
const YELLOW = '\x1b[33m';
|
|
4
|
-
const CYAN = '\x1b[36m';
|
|
5
|
-
const GREEN = '\x1b[32m';
|
|
6
|
-
const RESET = '\x1b[0m';
|
|
7
|
-
const BOLD = '\x1b[1m';
|
|
8
|
-
const ORANGE = '\x1b[38;5;208m';
|
|
1
|
+
import { RED, YELLOW, CYAN, GREEN, ORANGE, RESET, BOLD } from '../lib/constants.js';
|
|
9
2
|
|
|
10
3
|
export const YOLO_ART = `${YELLOW}
|
|
11
4
|
██╗ ██╗ ██████╗ ██╗ ██████╗ ██╗
|
|
@@ -49,7 +42,7 @@ export function showSafeActivated() {
|
|
|
49
42
|
export function showModeStatus(mode) {
|
|
50
43
|
console.log(`${BOLD}Claude CLI Status:${RESET}`);
|
|
51
44
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
52
|
-
|
|
45
|
+
|
|
53
46
|
if (mode === 'YOLO') {
|
|
54
47
|
console.log(YOLO_ART);
|
|
55
48
|
console.log(`Mode: ${YELLOW}${BOLD}YOLO${RESET} 🔥`);
|
|
@@ -62,4 +55,4 @@ export function showModeStatus(mode) {
|
|
|
62
55
|
console.log(`Permissions: ${GREEN}REQUIRED${RESET}`);
|
|
63
56
|
}
|
|
64
57
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
65
|
-
}
|
|
58
|
+
}
|
package/bin/cl
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# Claude YOLO/SAFE Mode Wrapper Script
|
|
4
4
|
# Usage: cl /YON | /YOFF | /STATUS | /HELP | [claude commands]
|
|
5
5
|
|
|
6
|
-
#
|
|
6
|
+
# Terminal colors
|
|
7
7
|
RED='\033[0;31m'
|
|
8
8
|
YELLOW='\033[1;33m'
|
|
9
9
|
CYAN='\033[0;36m'
|
|
@@ -11,24 +11,24 @@ GREEN='\033[0;32m'
|
|
|
11
11
|
RESET='\033[0m'
|
|
12
12
|
BOLD='\033[1m'
|
|
13
13
|
|
|
14
|
-
#
|
|
14
|
+
# State file for mode persistence
|
|
15
15
|
STATE_FILE="$HOME/.claude_yolo_state"
|
|
16
16
|
|
|
17
|
-
#
|
|
17
|
+
# Function to get current mode
|
|
18
18
|
get_mode() {
|
|
19
19
|
if [ -f "$STATE_FILE" ]; then
|
|
20
20
|
cat "$STATE_FILE"
|
|
21
21
|
else
|
|
22
|
-
echo "SAFE" #
|
|
22
|
+
echo "SAFE" # Default to safe mode
|
|
23
23
|
fi
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
#
|
|
26
|
+
# Function to set mode
|
|
27
27
|
set_mode() {
|
|
28
28
|
echo "$1" > "$STATE_FILE"
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
#
|
|
31
|
+
# Process arguments
|
|
32
32
|
case "$1" in
|
|
33
33
|
/YON)
|
|
34
34
|
echo -e "${YELLOW}${BOLD}🔥 ACTIVATING YOLO MODE 🔥${RESET}"
|
|
@@ -83,10 +83,10 @@ case "$1" in
|
|
|
83
83
|
;;
|
|
84
84
|
|
|
85
85
|
*)
|
|
86
|
-
#
|
|
86
|
+
# Run Claude in current mode
|
|
87
87
|
MODE=$(get_mode)
|
|
88
|
-
|
|
89
|
-
#
|
|
88
|
+
|
|
89
|
+
# Show mode before running
|
|
90
90
|
if [ "$MODE" = "YOLO" ]; then
|
|
91
91
|
echo -e "${YELLOW}[YOLO]${RESET} Running Claude in YOLO mode..."
|
|
92
92
|
# Check if claude-yolo-extended is installed
|
package/bin/cl.js
CHANGED
|
@@ -1,38 +1,57 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import fs from 'fs';
|
|
4
|
-
import path from 'path';
|
|
5
4
|
import { spawn } from 'child_process';
|
|
6
|
-
import os from 'os';
|
|
7
|
-
import { fileURLToPath } from 'url';
|
|
8
5
|
import { showYoloActivated, showSafeActivated, showModeStatus } from './ascii-art.js';
|
|
9
6
|
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
import {
|
|
8
|
+
YELLOW,
|
|
9
|
+
CYAN,
|
|
10
|
+
RESET,
|
|
11
|
+
BOLD,
|
|
12
|
+
DANGEROUS_CHARS_PATTERN,
|
|
13
|
+
STATE_FILE,
|
|
14
|
+
logError,
|
|
15
|
+
handleFatalError
|
|
16
|
+
} from '../lib/constants.js';
|
|
12
17
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const GREEN = '\x1b[32m';
|
|
18
|
-
const RESET = '\x1b[0m';
|
|
19
|
-
const BOLD = '\x1b[1m';
|
|
20
|
-
|
|
21
|
-
// State file path
|
|
22
|
-
const stateFile = path.join(os.homedir(), '.claude_yolo_state');
|
|
23
|
-
|
|
24
|
-
// Function to get current mode
|
|
18
|
+
/**
|
|
19
|
+
* Get current mode from state file
|
|
20
|
+
* @returns {string} Current mode ('YOLO' or 'SAFE')
|
|
21
|
+
*/
|
|
25
22
|
function getMode() {
|
|
26
23
|
try {
|
|
27
|
-
return fs.readFileSync(
|
|
24
|
+
return fs.readFileSync(STATE_FILE, 'utf8').trim();
|
|
28
25
|
} catch {
|
|
29
26
|
return 'YOLO'; // Default to YOLO mode (matches claude-yolo-extended behavior)
|
|
30
27
|
}
|
|
31
28
|
}
|
|
32
29
|
|
|
33
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Set mode in state file
|
|
32
|
+
* @param {string} mode - Mode to set ('YOLO' or 'SAFE')
|
|
33
|
+
*/
|
|
34
34
|
function setMode(mode) {
|
|
35
|
-
fs.writeFileSync(
|
|
35
|
+
fs.writeFileSync(STATE_FILE, mode);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Validate command-line arguments for shell injection (Windows only)
|
|
40
|
+
* @param {string[]} args - Arguments to validate
|
|
41
|
+
* @returns {boolean} True if all arguments are safe
|
|
42
|
+
*/
|
|
43
|
+
function validateArgs(args) {
|
|
44
|
+
const isWindows = process.platform === 'win32';
|
|
45
|
+
if (!isWindows) return true; // Non-Windows uses shell:false
|
|
46
|
+
|
|
47
|
+
for (const arg of args) {
|
|
48
|
+
if (DANGEROUS_CHARS_PATTERN.test(arg)) {
|
|
49
|
+
logError(`Invalid characters in argument: ${arg}`);
|
|
50
|
+
console.error('Arguments cannot contain: ; & | ` $ > <');
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return true;
|
|
36
55
|
}
|
|
37
56
|
|
|
38
57
|
// Get command line arguments
|
|
@@ -41,13 +60,13 @@ const args = process.argv.slice(2);
|
|
|
41
60
|
// Handle special commands
|
|
42
61
|
if (args.length > 0) {
|
|
43
62
|
const command = args[0].toUpperCase();
|
|
44
|
-
|
|
63
|
+
|
|
45
64
|
switch (command) {
|
|
46
65
|
case '/YON':
|
|
47
66
|
showYoloActivated();
|
|
48
67
|
setMode('YOLO');
|
|
49
68
|
console.log(`${YELLOW}✓ YOLO mode is now ON${RESET}`);
|
|
50
|
-
|
|
69
|
+
|
|
51
70
|
// Auto-start with remaining args
|
|
52
71
|
if (args.length > 1) {
|
|
53
72
|
runClaude(args.slice(1));
|
|
@@ -55,12 +74,12 @@ if (args.length > 0) {
|
|
|
55
74
|
runClaude([]);
|
|
56
75
|
}
|
|
57
76
|
break;
|
|
58
|
-
|
|
77
|
+
|
|
59
78
|
case '/YOFF':
|
|
60
79
|
showSafeActivated();
|
|
61
80
|
setMode('SAFE');
|
|
62
81
|
console.log(`${CYAN}✓ YOLO mode is now OFF (Safe mode ON)${RESET}`);
|
|
63
|
-
|
|
82
|
+
|
|
64
83
|
// Auto-start with remaining args
|
|
65
84
|
if (args.length > 1) {
|
|
66
85
|
runClaude(args.slice(1));
|
|
@@ -68,12 +87,13 @@ if (args.length > 0) {
|
|
|
68
87
|
runClaude([]);
|
|
69
88
|
}
|
|
70
89
|
break;
|
|
71
|
-
|
|
72
|
-
case '/STATUS':
|
|
90
|
+
|
|
91
|
+
case '/STATUS': {
|
|
73
92
|
const mode = getMode();
|
|
74
93
|
showModeStatus(mode);
|
|
75
94
|
break;
|
|
76
|
-
|
|
95
|
+
}
|
|
96
|
+
|
|
77
97
|
case '/HELP':
|
|
78
98
|
case '/H':
|
|
79
99
|
case '/?':
|
|
@@ -95,7 +115,7 @@ if (args.length > 0) {
|
|
|
95
115
|
console.log('Your mode choice is saved in ~/.claude_yolo_state');
|
|
96
116
|
console.log('and persists between terminal sessions.');
|
|
97
117
|
break;
|
|
98
|
-
|
|
118
|
+
|
|
99
119
|
default:
|
|
100
120
|
// Run Claude with provided arguments
|
|
101
121
|
runClaude(args);
|
|
@@ -105,33 +125,50 @@ if (args.length > 0) {
|
|
|
105
125
|
runClaude([]);
|
|
106
126
|
}
|
|
107
127
|
|
|
128
|
+
/**
|
|
129
|
+
* Run Claude CLI with the given arguments in current mode
|
|
130
|
+
* @param {string[]} claudeArgs - Arguments to pass to Claude
|
|
131
|
+
*/
|
|
108
132
|
function runClaude(claudeArgs) {
|
|
133
|
+
// Validate arguments before running (security check for Windows shell)
|
|
134
|
+
if (!validateArgs(claudeArgs)) {
|
|
135
|
+
process.exit(1);
|
|
136
|
+
}
|
|
137
|
+
|
|
109
138
|
const mode = getMode();
|
|
110
|
-
|
|
139
|
+
|
|
111
140
|
// Show current mode
|
|
112
141
|
if (mode === 'YOLO') {
|
|
113
142
|
console.log(`${YELLOW}[YOLO]${RESET} Running Claude in YOLO mode...`);
|
|
114
143
|
} else {
|
|
115
144
|
console.log(`${CYAN}[SAFE]${RESET} Running Claude in SAFE mode...`);
|
|
116
145
|
}
|
|
117
|
-
|
|
146
|
+
|
|
118
147
|
// Determine which command to run
|
|
119
148
|
const command = 'claude-yolo-extended';
|
|
120
149
|
const commandArgs = mode === 'SAFE' ? ['--safe', ...claudeArgs] : claudeArgs;
|
|
121
|
-
|
|
150
|
+
|
|
122
151
|
// Spawn the process
|
|
152
|
+
// Note: shell:false is safer (prevents command injection) but requires
|
|
153
|
+
// the command to be in PATH. On Windows, we need shell:true for .cmd files.
|
|
154
|
+
const isWindows = process.platform === 'win32';
|
|
123
155
|
const child = spawn(command, commandArgs, {
|
|
124
156
|
stdio: 'inherit',
|
|
125
|
-
shell:
|
|
157
|
+
shell: isWindows // Only use shell on Windows where it's required for PATH resolution
|
|
126
158
|
});
|
|
127
|
-
|
|
159
|
+
|
|
128
160
|
child.on('error', (err) => {
|
|
129
|
-
|
|
130
|
-
console.error(err.message);
|
|
131
|
-
process.exit(1);
|
|
161
|
+
handleFatalError(`Failed to start ${command}: ${err.message}`, err);
|
|
132
162
|
});
|
|
133
|
-
|
|
134
|
-
child.on('exit', (code) => {
|
|
135
|
-
|
|
163
|
+
|
|
164
|
+
child.on('exit', (code, signal) => {
|
|
165
|
+
if (signal) {
|
|
166
|
+
// Process was killed by signal - exit with 128 + signal number (Unix convention)
|
|
167
|
+
// Common signals: SIGTERM=15, SIGKILL=9, SIGINT=2
|
|
168
|
+
const signalCodes = { SIGTERM: 15, SIGKILL: 9, SIGINT: 2, SIGHUP: 1 };
|
|
169
|
+
const signalNum = signalCodes[signal] || 1;
|
|
170
|
+
process.exit(128 + signalNum);
|
|
171
|
+
}
|
|
172
|
+
process.exit(code ?? 0);
|
|
136
173
|
});
|
|
137
|
-
}
|
|
174
|
+
}
|