uv-suite 0.4.0 → 0.6.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.
- package/bin/cli.js +96 -38
- package/hooks/context-warning.sh +4 -0
- package/install.sh +42 -28
- package/package.json +2 -1
- package/uv.sh +106 -40
package/bin/cli.js
CHANGED
|
@@ -1,49 +1,52 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
const { execSync } = require('child_process');
|
|
3
|
+
const { execSync, spawn } = require('child_process');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const fs = require('fs');
|
|
6
6
|
|
|
7
7
|
const UV_SUITE_DIR = path.resolve(__dirname, '..');
|
|
8
8
|
const args = process.argv.slice(2);
|
|
9
9
|
const command = args[0];
|
|
10
|
+
const pkg = require(path.join(UV_SUITE_DIR, 'package.json'));
|
|
11
|
+
|
|
12
|
+
const PERSONAS = ['spike', 'sport', 'pro', 'professional', 'auto'];
|
|
13
|
+
const TOOLS = ['claude', 'codex'];
|
|
10
14
|
|
|
11
15
|
function usage() {
|
|
12
16
|
console.log(`
|
|
13
|
-
uv
|
|
17
|
+
uv v${pkg.version} — AI-assisted development framework
|
|
14
18
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
19
|
+
Launch a session:
|
|
20
|
+
uv claude pro Claude Code, Professional persona
|
|
21
|
+
uv claude auto Claude Code, Auto persona
|
|
22
|
+
uv codex pro Codex, Professional persona
|
|
23
|
+
uv codex sport Codex, Sport persona
|
|
24
|
+
uv pro Shorthand (defaults to Claude Code)
|
|
25
|
+
uv Claude Code, Professional
|
|
18
26
|
|
|
19
|
-
|
|
20
|
-
install
|
|
21
|
-
|
|
27
|
+
Setup:
|
|
28
|
+
uv install Install UV Suite into current project
|
|
29
|
+
uv install --persona sport
|
|
30
|
+
uv info Show what's installed
|
|
22
31
|
|
|
23
32
|
Personas:
|
|
24
|
-
spike
|
|
25
|
-
sport
|
|
26
|
-
|
|
27
|
-
auto
|
|
28
|
-
|
|
29
|
-
Examples:
|
|
30
|
-
npx uv-suite install Install with Professional persona
|
|
31
|
-
npx uv-suite install --persona sport Install with Sport persona
|
|
32
|
-
npx uv-suite install --global Install to ~/.claude/
|
|
33
|
+
spike Research & docs (Opus, max effort)
|
|
34
|
+
sport New projects (Sonnet, high effort)
|
|
35
|
+
pro Production code (all hooks, all guardrails)
|
|
36
|
+
auto Fully autonomous (max effort, everything approved)
|
|
33
37
|
`);
|
|
34
38
|
}
|
|
35
39
|
|
|
36
40
|
function info() {
|
|
37
41
|
console.log(`
|
|
38
|
-
UV Suite
|
|
42
|
+
UV Suite v${pkg.version}
|
|
39
43
|
|
|
40
44
|
Contents:
|
|
41
45
|
10 agents Claude Code (.md), Cursor (.mdc), Codex (.toml)
|
|
42
46
|
9 skills Slash commands for Claude Code
|
|
43
|
-
|
|
44
|
-
6 guardrails Anti-slop rules
|
|
47
|
+
5 hooks auto-lint, slop-check, danger-zone, block-destructive, review-reminder
|
|
48
|
+
6 guardrails Anti-slop rules
|
|
45
49
|
4 personas Spike, Sport, Professional, Auto
|
|
46
|
-
1 launcher uv.sh (session launcher with persona selection)
|
|
47
50
|
|
|
48
51
|
Source: ${UV_SUITE_DIR}
|
|
49
52
|
`);
|
|
@@ -55,8 +58,6 @@ function install() {
|
|
|
55
58
|
console.error('Error: install.sh not found at', installScript);
|
|
56
59
|
process.exit(1);
|
|
57
60
|
}
|
|
58
|
-
|
|
59
|
-
// Pass through all args after "install"
|
|
60
61
|
const installArgs = args.slice(1).join(' ');
|
|
61
62
|
try {
|
|
62
63
|
execSync(`bash "${installScript}" ${installArgs}`, { stdio: 'inherit' });
|
|
@@ -65,20 +66,77 @@ function install() {
|
|
|
65
66
|
}
|
|
66
67
|
}
|
|
67
68
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
69
|
+
function normPersona(p) {
|
|
70
|
+
if (p === 'pro' || p === 'professional') return 'professional';
|
|
71
|
+
if (PERSONAS.includes(p)) return p;
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function personaLabel(p) {
|
|
76
|
+
const labels = {
|
|
77
|
+
spike: 'Spike — research & docs (Opus, max)',
|
|
78
|
+
sport: 'Sport — lightweight (Sonnet, high)',
|
|
79
|
+
professional: 'Professional — full rigor (all hooks, all guardrails)',
|
|
80
|
+
auto: 'Auto — autonomous (max, everything approved)',
|
|
81
|
+
};
|
|
82
|
+
return labels[p] || p;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function launchClaude(persona, extra) {
|
|
86
|
+
const settings = path.resolve('.claude/personas', `${persona}.json`);
|
|
87
|
+
if (!fs.existsSync(settings)) {
|
|
88
|
+
console.error(`Error: ${settings} not found. Run 'uv install' first.`);
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
console.log(`UV Suite | Claude Code | ${personaLabel(persona)}`);
|
|
92
|
+
console.log('');
|
|
93
|
+
const child = spawn('claude', ['--settings', settings, ...extra], { stdio: 'inherit' });
|
|
94
|
+
child.on('exit', (code) => process.exit(code || 0));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function launchCodex(persona, extra) {
|
|
98
|
+
const approvalMap = {
|
|
99
|
+
spike: ['--model', 'o3', '--approval-mode', 'suggest'],
|
|
100
|
+
sport: ['--approval-mode', 'auto-edit'],
|
|
101
|
+
professional: ['--approval-mode', 'suggest'],
|
|
102
|
+
auto: ['--approval-mode', 'full-auto'],
|
|
103
|
+
};
|
|
104
|
+
const codexArgs = approvalMap[persona] || ['--approval-mode', 'suggest'];
|
|
105
|
+
console.log(`UV Suite | Codex | ${personaLabel(persona)}`);
|
|
106
|
+
console.log('');
|
|
107
|
+
const child = spawn('codex', [...codexArgs, ...extra], { stdio: 'inherit' });
|
|
108
|
+
child.on('exit', (code) => process.exit(code || 0));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// --- Parse and route ---
|
|
112
|
+
|
|
113
|
+
if (!command || command === '--help' || command === '-h') {
|
|
114
|
+
usage();
|
|
115
|
+
process.exit(0);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (command === 'install') {
|
|
119
|
+
install();
|
|
120
|
+
} else if (command === 'info') {
|
|
121
|
+
info();
|
|
122
|
+
} else if (TOOLS.includes(command)) {
|
|
123
|
+
// uv claude pro, uv codex auto
|
|
124
|
+
const persona = normPersona(args[1] || 'pro');
|
|
125
|
+
if (!persona) {
|
|
126
|
+
console.error(`Unknown persona: ${args[1]}`);
|
|
127
|
+
console.error('Available: spike, sport, pro, auto');
|
|
83
128
|
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
const extra = args.slice(2);
|
|
131
|
+
if (command === 'claude') launchClaude(persona, extra);
|
|
132
|
+
else launchCodex(persona, extra);
|
|
133
|
+
} else if (normPersona(command)) {
|
|
134
|
+
// uv pro (shorthand for uv claude pro)
|
|
135
|
+
const persona = normPersona(command);
|
|
136
|
+
const extra = args.slice(1);
|
|
137
|
+
launchClaude(persona, extra);
|
|
138
|
+
} else {
|
|
139
|
+
console.error(`Unknown command: ${command}`);
|
|
140
|
+
usage();
|
|
141
|
+
process.exit(1);
|
|
84
142
|
}
|
package/install.sh
CHANGED
|
@@ -75,11 +75,32 @@ mkdir -p "$TARGET_DIR/hooks"
|
|
|
75
75
|
mkdir -p "$TARGET_DIR/rules"
|
|
76
76
|
|
|
77
77
|
# --- Install agents (Claude Code subagent definitions) ---
|
|
78
|
-
echo "Installing 10 agent definitions..."
|
|
78
|
+
echo "Installing 10 Claude Code agent definitions..."
|
|
79
79
|
cp "$UV_SUITE_DIR/agents/claude-code/"*.md "$TARGET_DIR/agents/"
|
|
80
80
|
echo " ✓ cartographer, spec-writer, architect, reviewer, test-writer"
|
|
81
81
|
echo " ✓ eval-writer, anti-slop-guard, prototype-builder, devops, security"
|
|
82
82
|
|
|
83
|
+
# --- Install Codex agents (.codex/agents/*.toml + AGENTS.md) ---
|
|
84
|
+
PROJECT_ROOT="$(dirname "$TARGET_DIR")"
|
|
85
|
+
echo "Installing 10 Codex agent definitions..."
|
|
86
|
+
mkdir -p "$PROJECT_ROOT/.codex/agents"
|
|
87
|
+
cp "$UV_SUITE_DIR/agents/codex/"*.toml "$PROJECT_ROOT/.codex/agents/"
|
|
88
|
+
|
|
89
|
+
# Create AGENTS.md for Codex (it reads this instead of CLAUDE.md)
|
|
90
|
+
if [ ! -f "$PROJECT_ROOT/AGENTS.md" ]; then
|
|
91
|
+
cp "$PROJECT_ROOT/CLAUDE.md" "$PROJECT_ROOT/AGENTS.md" 2>/dev/null || touch "$PROJECT_ROOT/AGENTS.md"
|
|
92
|
+
echo " ✓ AGENTS.md created (Codex reads this)"
|
|
93
|
+
else
|
|
94
|
+
echo " ✓ AGENTS.md already exists"
|
|
95
|
+
fi
|
|
96
|
+
echo " ✓ .codex/agents/*.toml installed"
|
|
97
|
+
|
|
98
|
+
# --- Install Cursor rules (.cursor/rules/*.mdc) ---
|
|
99
|
+
echo "Installing 10 Cursor rule definitions..."
|
|
100
|
+
mkdir -p "$PROJECT_ROOT/.cursor/rules"
|
|
101
|
+
cp "$UV_SUITE_DIR/agents/cursor/"*.mdc "$PROJECT_ROOT/.cursor/rules/"
|
|
102
|
+
echo " ✓ .cursor/rules/*.mdc installed"
|
|
103
|
+
|
|
83
104
|
# --- Install skills (slash commands) ---
|
|
84
105
|
echo "Installing 9 skills..."
|
|
85
106
|
for skill_dir in "$UV_SUITE_DIR/skills/"*/; do
|
|
@@ -383,15 +404,17 @@ cat << 'HOOKS'
|
|
|
383
404
|
HOOKS
|
|
384
405
|
fi)
|
|
385
406
|
|
|
386
|
-
###
|
|
407
|
+
### Context management
|
|
387
408
|
|
|
388
|
-
|
|
409
|
+
If the conversation is getting long, proactively suggest running /compact or starting a new session. Use /cost to check token usage. The user's status line shows context window usage.
|
|
410
|
+
|
|
411
|
+
### Launching sessions
|
|
389
412
|
|
|
390
413
|
\`\`\`
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
414
|
+
uv claude pro # Claude Code, Professional persona
|
|
415
|
+
uv claude auto # Claude Code, Auto persona
|
|
416
|
+
uv codex pro # OpenAI Codex, Professional persona
|
|
417
|
+
uv codex sport # OpenAI Codex, Sport persona
|
|
395
418
|
\`\`\`
|
|
396
419
|
CLAUDEMD
|
|
397
420
|
|
|
@@ -412,14 +435,11 @@ echo "╚═══════════════════════
|
|
|
412
435
|
echo ""
|
|
413
436
|
echo "What was installed:"
|
|
414
437
|
echo ""
|
|
415
|
-
echo "
|
|
416
|
-
echo "
|
|
417
|
-
echo "
|
|
418
|
-
|
|
419
|
-
echo "
|
|
420
|
-
fi
|
|
421
|
-
echo " PERSONAS (4) $TARGET_DIR/personas/*.json"
|
|
422
|
-
echo " SETTINGS $TARGET_DIR/settings.json"
|
|
438
|
+
echo " Claude Code .claude/agents/*.md + skills/ + hooks/ + rules/"
|
|
439
|
+
echo " Codex .codex/agents/*.toml + AGENTS.md"
|
|
440
|
+
echo " Cursor .cursor/rules/*.mdc"
|
|
441
|
+
echo " Personas (4) .claude/personas/*.json"
|
|
442
|
+
echo " Launcher ./uv.sh"
|
|
423
443
|
echo ""
|
|
424
444
|
|
|
425
445
|
echo "Available slash commands:"
|
|
@@ -470,17 +490,11 @@ echo "Can write docs and analysis files. Cannot edit existing code, commit, or p
|
|
|
470
490
|
fi
|
|
471
491
|
|
|
472
492
|
echo ""
|
|
473
|
-
echo "Start a session
|
|
474
|
-
echo ""
|
|
475
|
-
echo " ./uv.sh spike Research & docs (Opus, max, doc-slop checked)"
|
|
476
|
-
echo " ./uv.sh sport New projects (Sonnet, high, lint only)"
|
|
477
|
-
echo " ./uv.sh pro Production code (all hooks, all guardrails)"
|
|
478
|
-
echo " ./uv.sh auto Fully autonomous (max effort, everything approved)"
|
|
479
|
-
echo " ./uv.sh Defaults to Professional"
|
|
480
|
-
echo ""
|
|
481
|
-
echo "Or launch Claude directly with a persona:"
|
|
493
|
+
echo "Start a session:"
|
|
482
494
|
echo ""
|
|
483
|
-
echo " claude
|
|
484
|
-
echo " claude
|
|
485
|
-
echo "
|
|
486
|
-
echo "
|
|
495
|
+
echo " ./uv.sh claude pro Claude Code, Professional"
|
|
496
|
+
echo " ./uv.sh claude auto Claude Code, Auto"
|
|
497
|
+
echo " ./uv.sh codex pro Codex, Professional"
|
|
498
|
+
echo " ./uv.sh codex auto Codex, Auto"
|
|
499
|
+
echo " ./uv.sh pro Shorthand (defaults to Claude Code)"
|
|
500
|
+
echo " ./uv.sh Claude Code, Professional"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uv-suite",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Portable framework for AI-assisted software development. 10 agents, 9 skills, 5 hooks, 4 personas. Works with Claude Code, Cursor, and Codex.",
|
|
5
5
|
"author": "Utsav Anand",
|
|
6
6
|
"license": "MIT",
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"repomix": "^0.3.0"
|
|
25
25
|
},
|
|
26
26
|
"bin": {
|
|
27
|
+
"uv": "./bin/cli.js",
|
|
27
28
|
"uv-suite": "./bin/cli.js"
|
|
28
29
|
},
|
|
29
30
|
"files": [
|
package/uv.sh
CHANGED
|
@@ -1,56 +1,122 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
# UV Suite —
|
|
3
|
-
# Starts
|
|
2
|
+
# UV Suite — Unified session launcher
|
|
3
|
+
# Starts Claude Code or Codex with the specified persona.
|
|
4
4
|
#
|
|
5
5
|
# Usage:
|
|
6
|
-
# uv
|
|
7
|
-
# uv
|
|
8
|
-
# uv
|
|
9
|
-
# uv
|
|
10
|
-
# uv
|
|
6
|
+
# uv claude pro Claude Code, Professional persona
|
|
7
|
+
# uv claude auto Claude Code, Auto persona
|
|
8
|
+
# uv codex sport OpenAI Codex, Sport persona
|
|
9
|
+
# uv codex pro OpenAI Codex, Professional persona
|
|
10
|
+
# uv pro Shorthand — defaults to Claude Code
|
|
11
|
+
# uv Claude Code, Professional persona
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
TOOL=""
|
|
14
|
+
PERSONA=""
|
|
14
15
|
|
|
15
|
-
#
|
|
16
|
-
case "$
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
# Parse arguments
|
|
17
|
+
case "$1" in
|
|
18
|
+
claude|codex)
|
|
19
|
+
TOOL="$1"
|
|
20
|
+
PERSONA="${2:-pro}"
|
|
21
|
+
shift 2 2>/dev/null
|
|
20
22
|
;;
|
|
21
|
-
sport)
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
spike|sport|pro|professional|auto)
|
|
24
|
+
TOOL="claude"
|
|
25
|
+
PERSONA="$1"
|
|
26
|
+
shift
|
|
24
27
|
;;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
--help|-h)
|
|
29
|
+
echo ""
|
|
30
|
+
echo " uv — UV Suite session launcher"
|
|
31
|
+
echo ""
|
|
32
|
+
echo " Usage:"
|
|
33
|
+
echo " uv claude <persona> Start Claude Code with persona"
|
|
34
|
+
echo " uv codex <persona> Start OpenAI Codex with persona"
|
|
35
|
+
echo " uv <persona> Shorthand for uv claude <persona>"
|
|
36
|
+
echo " uv Defaults to uv claude pro"
|
|
37
|
+
echo ""
|
|
38
|
+
echo " Personas:"
|
|
39
|
+
echo " spike Research & docs (Opus, max effort)"
|
|
40
|
+
echo " sport New projects (Sonnet, high effort)"
|
|
41
|
+
echo " pro Production code (all hooks, all guardrails)"
|
|
42
|
+
echo " auto Fully autonomous (max effort, everything approved)"
|
|
43
|
+
echo ""
|
|
44
|
+
exit 0
|
|
45
|
+
;;
|
|
46
|
+
"")
|
|
47
|
+
TOOL="claude"
|
|
48
|
+
PERSONA="pro"
|
|
28
49
|
;;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
50
|
+
*)
|
|
51
|
+
echo "Unknown argument: $1"
|
|
52
|
+
echo "Usage: uv [claude|codex] [spike|sport|pro|auto]"
|
|
53
|
+
exit 1
|
|
32
54
|
;;
|
|
55
|
+
esac
|
|
56
|
+
|
|
57
|
+
# Normalize persona name
|
|
58
|
+
case "$PERSONA" in
|
|
59
|
+
pro|professional) PERSONA="professional" ;;
|
|
60
|
+
spike|sport|auto) ;; # already correct
|
|
33
61
|
*)
|
|
34
62
|
echo "Unknown persona: $PERSONA"
|
|
35
|
-
echo ""
|
|
36
|
-
echo "Usage: uv [spike|sport|pro|auto]"
|
|
37
|
-
echo ""
|
|
38
|
-
echo " spike Research & documentation (Opus, max, doc-slop hook)"
|
|
39
|
-
echo " sport New projects, prototyping (Sonnet, high, lint only)"
|
|
40
|
-
echo " pro Production code (all hooks, all guardrails, human-gated)"
|
|
41
|
-
echo " auto Fully autonomous (max effort, everything auto-approved)"
|
|
42
|
-
echo ""
|
|
43
|
-
echo " uv Defaults to 'pro'"
|
|
63
|
+
echo "Available: spike, sport, pro, auto"
|
|
44
64
|
exit 1
|
|
45
65
|
;;
|
|
46
66
|
esac
|
|
47
67
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
68
|
+
# Persona labels
|
|
69
|
+
case "$PERSONA" in
|
|
70
|
+
spike) LABEL="Spike — research & docs (Opus, max)" ;;
|
|
71
|
+
sport) LABEL="Sport — lightweight (Sonnet, high)" ;;
|
|
72
|
+
professional) LABEL="Professional — full rigor (all hooks, all guardrails)" ;;
|
|
73
|
+
auto) LABEL="Auto — autonomous (max, everything approved)" ;;
|
|
74
|
+
esac
|
|
75
|
+
|
|
76
|
+
SETTINGS=".claude/personas/$PERSONA.json"
|
|
53
77
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
78
|
+
if [ "$TOOL" = "claude" ]; then
|
|
79
|
+
# --- Claude Code ---
|
|
80
|
+
if ! command -v claude &>/dev/null; then
|
|
81
|
+
echo "Error: claude not found. Install Claude Code first."
|
|
82
|
+
exit 1
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
if [ ! -f "$SETTINGS" ]; then
|
|
86
|
+
echo "Error: $SETTINGS not found. Run 'npx uv-suite install' first."
|
|
87
|
+
exit 1
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
echo "UV Suite | Claude Code | $LABEL"
|
|
91
|
+
echo ""
|
|
92
|
+
exec claude --settings "$SETTINGS" "$@"
|
|
93
|
+
|
|
94
|
+
elif [ "$TOOL" = "codex" ]; then
|
|
95
|
+
# --- OpenAI Codex ---
|
|
96
|
+
if ! command -v codex &>/dev/null; then
|
|
97
|
+
echo "Error: codex not found. Install OpenAI Codex first."
|
|
98
|
+
echo " npm install -g @openai/codex"
|
|
99
|
+
exit 1
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
# Codex doesn't have --settings, but reads AGENTS.md and .codex/agents/
|
|
103
|
+
# We can pass model and approval mode based on persona
|
|
104
|
+
case "$PERSONA" in
|
|
105
|
+
spike)
|
|
106
|
+
CODEX_ARGS="--model o3 --approval-mode suggest"
|
|
107
|
+
;;
|
|
108
|
+
sport)
|
|
109
|
+
CODEX_ARGS="--approval-mode auto-edit"
|
|
110
|
+
;;
|
|
111
|
+
professional)
|
|
112
|
+
CODEX_ARGS="--approval-mode suggest"
|
|
113
|
+
;;
|
|
114
|
+
auto)
|
|
115
|
+
CODEX_ARGS="--approval-mode full-auto"
|
|
116
|
+
;;
|
|
117
|
+
esac
|
|
118
|
+
|
|
119
|
+
echo "UV Suite | Codex | $LABEL"
|
|
120
|
+
echo ""
|
|
121
|
+
exec codex $CODEX_ARGS "$@"
|
|
122
|
+
fi
|