up-cc 0.7.0 → 0.9.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/README.md +4 -2
- package/bin/install.js +254 -8
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
╚═════╝ ╚═╝</pre>
|
|
9
9
|
</p>
|
|
10
10
|
|
|
11
|
-
<h3 align="center">Desenvolvimento orientado a especificacao para Claude Code,
|
|
11
|
+
<h3 align="center">Desenvolvimento orientado a especificacao para Claude Code, Codex CLI, OpenCode e Gemini CLI</h3>
|
|
12
12
|
|
|
13
13
|
<p align="center">
|
|
14
14
|
<a href="https://www.npmjs.com/package/up-cc"><img src="https://img.shields.io/npm/v/up-cc.svg" alt="npm version"></a>
|
|
@@ -20,7 +20,9 @@
|
|
|
20
20
|
|
|
21
21
|
**UP** e um sistema de meta-prompting que transforma seu assistente de IA em um desenvolvedor estruturado. Em vez de pedir "faz X", voce descreve o projeto e o UP cuida do planejamento, execucao, verificacao e rastreamento — tudo via slash commands.
|
|
22
22
|
|
|
23
|
-
Funciona com **Claude Code**, **
|
|
23
|
+
Funciona com **Claude Code**, **OpenAI Codex CLI**, **OpenCode** e **Gemini CLI**.
|
|
24
|
+
|
|
25
|
+
> **Codex CLI (v0.8.0+)**: Comandos viram skills (invocadas via `$up-plan` em vez de `/up:plan`). Agentes viram TOML em `~/.codex/agents/`. Hierarquia governance suportada via `[agents] max_depth = 4` no `~/.codex/config.toml`.
|
|
24
26
|
|
|
25
27
|
## Por que UP?
|
|
26
28
|
|
package/bin/install.js
CHANGED
|
@@ -43,6 +43,7 @@ const hasLocal = args.includes('--local') || args.includes('-l');
|
|
|
43
43
|
const hasClaude = args.includes('--claude');
|
|
44
44
|
const hasGemini = args.includes('--gemini');
|
|
45
45
|
const hasOpencode = args.includes('--opencode');
|
|
46
|
+
const hasCodex = args.includes('--codex');
|
|
46
47
|
const hasAll = args.includes('--all');
|
|
47
48
|
const hasUninstall = args.includes('--uninstall') || args.includes('-u');
|
|
48
49
|
const hasHelp = args.includes('--help') || args.includes('-h');
|
|
@@ -50,11 +51,12 @@ const hasHelp = args.includes('--help') || args.includes('-h');
|
|
|
50
51
|
// Runtime selection
|
|
51
52
|
let selectedRuntimes = [];
|
|
52
53
|
if (hasAll) {
|
|
53
|
-
selectedRuntimes = ['claude', 'gemini', 'opencode'];
|
|
54
|
+
selectedRuntimes = ['claude', 'gemini', 'opencode', 'codex'];
|
|
54
55
|
} else {
|
|
55
56
|
if (hasClaude) selectedRuntimes.push('claude');
|
|
56
57
|
if (hasGemini) selectedRuntimes.push('gemini');
|
|
57
58
|
if (hasOpencode) selectedRuntimes.push('opencode');
|
|
59
|
+
if (hasCodex) selectedRuntimes.push('codex');
|
|
58
60
|
}
|
|
59
61
|
|
|
60
62
|
const banner = '\n' +
|
|
@@ -77,6 +79,7 @@ if (hasHelp) {
|
|
|
77
79
|
console.log(` ${cyan}--claude${reset} Install for Claude Code`);
|
|
78
80
|
console.log(` ${cyan}--gemini${reset} Install for Gemini CLI`);
|
|
79
81
|
console.log(` ${cyan}--opencode${reset} Install for OpenCode`);
|
|
82
|
+
console.log(` ${cyan}--codex${reset} Install for OpenAI Codex CLI`);
|
|
80
83
|
console.log(` ${cyan}--all${reset} Install for all runtimes`);
|
|
81
84
|
console.log(` ${cyan}-u, --uninstall${reset} Remove all UP files`);
|
|
82
85
|
console.log(` ${cyan}-h, --help${reset} Show this help\n`);
|
|
@@ -101,12 +104,14 @@ const packageRoot = path.resolve(scriptDir, '..');
|
|
|
101
104
|
function getDirName(runtime) {
|
|
102
105
|
if (runtime === 'opencode') return '.opencode';
|
|
103
106
|
if (runtime === 'gemini') return '.gemini';
|
|
107
|
+
if (runtime === 'codex') return '.codex';
|
|
104
108
|
return '.claude';
|
|
105
109
|
}
|
|
106
110
|
|
|
107
111
|
function getRuntimeLabel(runtime) {
|
|
108
112
|
if (runtime === 'opencode') return 'OpenCode';
|
|
109
113
|
if (runtime === 'gemini') return 'Gemini';
|
|
114
|
+
if (runtime === 'codex') return 'Codex CLI';
|
|
110
115
|
return 'Claude Code';
|
|
111
116
|
}
|
|
112
117
|
|
|
@@ -120,6 +125,10 @@ function getGlobalDir(runtime) {
|
|
|
120
125
|
if (process.env.GEMINI_CONFIG_DIR) return process.env.GEMINI_CONFIG_DIR;
|
|
121
126
|
return path.join(os.homedir(), '.gemini');
|
|
122
127
|
}
|
|
128
|
+
if (runtime === 'codex') {
|
|
129
|
+
if (process.env.CODEX_HOME) return process.env.CODEX_HOME;
|
|
130
|
+
return path.join(os.homedir(), '.codex');
|
|
131
|
+
}
|
|
123
132
|
// Claude Code
|
|
124
133
|
if (process.env.CLAUDE_CONFIG_DIR) return process.env.CLAUDE_CONFIG_DIR;
|
|
125
134
|
return path.join(os.homedir(), '.claude');
|
|
@@ -361,6 +370,125 @@ function convertCommandToGeminiToml(content) {
|
|
|
361
370
|
return toml;
|
|
362
371
|
}
|
|
363
372
|
|
|
373
|
+
// ── Codex Conversion ──
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Map UP agent name to Codex sandbox_mode based on role.
|
|
377
|
+
* Specialists/executors/devops get workspace-write.
|
|
378
|
+
* Supervisors/auditors/reviewers get read-only.
|
|
379
|
+
*/
|
|
380
|
+
function getCodexSandboxMode(agentName) {
|
|
381
|
+
const writeAgents = [
|
|
382
|
+
'up-frontend-specialist', 'up-backend-specialist', 'up-database-specialist',
|
|
383
|
+
'up-executor', 'up-devops-agent', 'up-technical-writer', 'up-arquiteto',
|
|
384
|
+
'up-system-designer', 'up-roteirista', 'up-sintetizador', 'up-sintetizador-melhorias',
|
|
385
|
+
'up-consolidador-ideias', 'up-clone-crawler', 'up-clone-design-extractor',
|
|
386
|
+
'up-clone-feature-mapper', 'up-clone-prd-writer', 'up-clone-verifier',
|
|
387
|
+
'up-visual-critic', 'up-exhaustive-tester', 'up-api-tester', 'up-qa-agent',
|
|
388
|
+
'up-depurador', 'up-verificador', 'up-blind-validator', 'up-planejador',
|
|
389
|
+
'up-mapeador-codigo', 'up-analista-codigo', 'up-pesquisador-projeto',
|
|
390
|
+
'up-pesquisador-mercado', 'up-product-analyst', 'up-project-ceo',
|
|
391
|
+
];
|
|
392
|
+
return writeAgents.includes(agentName) ? 'workspace-write' : 'read-only';
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Prepare markdown body for embedding inside a TOML literal string ('''...''').
|
|
397
|
+
* TOML literal strings don't interpret escape sequences, so backslashes in shell
|
|
398
|
+
* commands and regex patterns survive intact. The only thing we can't have inside
|
|
399
|
+
* the literal is the literal sequence ''' which would close the string.
|
|
400
|
+
*/
|
|
401
|
+
function prepareTomlLiteralBody(str) {
|
|
402
|
+
// If the body contains ''' (rare in markdown), break it by inserting a zero-width space.
|
|
403
|
+
// This is a known TOML limitation — literal strings cannot contain their own delimiter.
|
|
404
|
+
if (str.includes("'''")) {
|
|
405
|
+
// Replace with backtick-marked version preserving readability
|
|
406
|
+
return str.replace(/'''/g, "''\u200B'");
|
|
407
|
+
}
|
|
408
|
+
return str;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Convert Claude Code agent .md to Codex TOML format.
|
|
413
|
+
*
|
|
414
|
+
* Codex agent file structure:
|
|
415
|
+
* name = "..."
|
|
416
|
+
* description = "..."
|
|
417
|
+
* developer_instructions = '''...'''
|
|
418
|
+
* sandbox_mode = "workspace-write" | "read-only"
|
|
419
|
+
*
|
|
420
|
+
* Uses TOML literal strings ('''...''') for the body so that backslashes in
|
|
421
|
+
* embedded shell commands and regex patterns survive without escaping.
|
|
422
|
+
*
|
|
423
|
+
* Codex agents do NOT have a `tools` field. Tool access is governed by sandbox_mode only.
|
|
424
|
+
* The `color` field has no Codex equivalent and is dropped.
|
|
425
|
+
*/
|
|
426
|
+
function convertAgentToCodex(content, fallbackName) {
|
|
427
|
+
const { frontmatter, body } = extractFrontmatterAndBody(content);
|
|
428
|
+
|
|
429
|
+
let name = fallbackName || 'unknown';
|
|
430
|
+
let description = '';
|
|
431
|
+
if (frontmatter) {
|
|
432
|
+
name = extractFrontmatterField(frontmatter, 'name') || name;
|
|
433
|
+
description = extractFrontmatterField(frontmatter, 'description') || '';
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
const sandboxMode = getCodexSandboxMode(name);
|
|
437
|
+
const cleanBody = prepareTomlLiteralBody(body.trim());
|
|
438
|
+
|
|
439
|
+
let toml = '';
|
|
440
|
+
toml += `name = ${JSON.stringify(name)}\n`;
|
|
441
|
+
toml += `description = ${JSON.stringify(description)}\n`;
|
|
442
|
+
toml += `sandbox_mode = ${JSON.stringify(sandboxMode)}\n`;
|
|
443
|
+
toml += `developer_instructions = '''\n${cleanBody}\n'''\n`;
|
|
444
|
+
return toml;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Convert Claude Code command .md to Codex skill SKILL.md format.
|
|
449
|
+
* Codex skills use YAML frontmatter (same as Claude) but skill body is loaded
|
|
450
|
+
* AFTER trigger, so we keep most content there.
|
|
451
|
+
*
|
|
452
|
+
* Returns { skillMd, openaiYaml } for the caller to write to disk.
|
|
453
|
+
*/
|
|
454
|
+
function convertCommandToCodexSkill(content, commandName) {
|
|
455
|
+
const { frontmatter, body } = extractFrontmatterAndBody(content);
|
|
456
|
+
|
|
457
|
+
let description = '';
|
|
458
|
+
if (frontmatter) {
|
|
459
|
+
description = extractFrontmatterField(frontmatter, 'description') || '';
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
const skillName = commandName.startsWith('up-') ? commandName : `up-${commandName}`;
|
|
463
|
+
|
|
464
|
+
// SKILL.md frontmatter must have name + description (Codex skill spec)
|
|
465
|
+
const skillMd =
|
|
466
|
+
`---\n` +
|
|
467
|
+
`name: ${skillName}\n` +
|
|
468
|
+
`description: ${JSON.stringify(description)}\n` +
|
|
469
|
+
`---\n` +
|
|
470
|
+
body;
|
|
471
|
+
|
|
472
|
+
// openai.yaml — explicit invocation only (don't pollute auto-discovery)
|
|
473
|
+
const displayName = skillName
|
|
474
|
+
.replace(/^up-/, 'UP ')
|
|
475
|
+
.replace(/-/g, ' ')
|
|
476
|
+
.replace(/\b\w/g, (c) => c.toUpperCase());
|
|
477
|
+
const shortDesc = description.slice(0, 60);
|
|
478
|
+
const defaultPrompt = `Use $${skillName} to ${description.slice(0, 80).toLowerCase()}`;
|
|
479
|
+
|
|
480
|
+
const openaiYaml =
|
|
481
|
+
`interface:\n` +
|
|
482
|
+
` display_name: ${JSON.stringify(displayName)}\n` +
|
|
483
|
+
` short_description: ${JSON.stringify(shortDesc)}\n` +
|
|
484
|
+
` default_prompt: ${JSON.stringify(defaultPrompt)}\n` +
|
|
485
|
+
`\n` +
|
|
486
|
+
`policy:\n` +
|
|
487
|
+
` allow_implicit_invocation: false\n`;
|
|
488
|
+
|
|
489
|
+
return { skillMd, openaiYaml };
|
|
490
|
+
}
|
|
491
|
+
|
|
364
492
|
// ── File Copy ──
|
|
365
493
|
|
|
366
494
|
/**
|
|
@@ -390,6 +518,26 @@ function replacePaths(content, pathPrefix, runtime) {
|
|
|
390
518
|
content = content.replace(/\bTodoWrite\b/g, 'todowrite');
|
|
391
519
|
}
|
|
392
520
|
|
|
521
|
+
if (runtime === 'codex') {
|
|
522
|
+
// Slash commands become skill mentions in Codex
|
|
523
|
+
content = content.replace(/\/up:([a-z-]+)/g, '$$up-$1');
|
|
524
|
+
|
|
525
|
+
// Translate programmatic Task() calls to Codex's natural-language invocation pattern.
|
|
526
|
+
// Codex multi-agent feature spawns agents from natural language in prompts.
|
|
527
|
+
//
|
|
528
|
+
// Pattern: Task(subagent_type="up-X", prompt="...") → "Spawn the up-X subagent..."
|
|
529
|
+
// We can't fully reformat the multi-line python-like calls, but we can strip the
|
|
530
|
+
// Python wrappers so workflow content reads as natural instructions.
|
|
531
|
+
content = content.replace(/Task\(\s*subagent_type="(up-[a-z-]+)",\s*prompt="/g,
|
|
532
|
+
'Spawn the $1 subagent with the following task: "');
|
|
533
|
+
content = content.replace(/Agent\(\s*subagent_type="(up-[a-z-]+)",/g,
|
|
534
|
+
'Spawn the $1 subagent with the following config:');
|
|
535
|
+
content = content.replace(/subagent_type="general-purpose"/g, 'general purpose');
|
|
536
|
+
// Codex tools naming
|
|
537
|
+
content = content.replace(/\bAskUserQuestion\b/g, 'ask user');
|
|
538
|
+
content = content.replace(/\bTodoWrite\b/g, 'task tracking');
|
|
539
|
+
}
|
|
540
|
+
|
|
393
541
|
return content;
|
|
394
542
|
}
|
|
395
543
|
|
|
@@ -497,7 +645,7 @@ function uninstall(targetDir, runtime) {
|
|
|
497
645
|
const agentsDir = path.join(targetDir, 'agents');
|
|
498
646
|
if (fs.existsSync(agentsDir)) {
|
|
499
647
|
for (const file of fs.readdirSync(agentsDir)) {
|
|
500
|
-
if (file.startsWith('up-') && file.endsWith('.md')) {
|
|
648
|
+
if (file.startsWith('up-') && (file.endsWith('.md') || file.endsWith('.toml'))) {
|
|
501
649
|
fs.unlinkSync(path.join(agentsDir, file));
|
|
502
650
|
removed++;
|
|
503
651
|
}
|
|
@@ -506,7 +654,23 @@ function uninstall(targetDir, runtime) {
|
|
|
506
654
|
}
|
|
507
655
|
|
|
508
656
|
// Remove UP commands (runtime-specific structure)
|
|
509
|
-
if (runtime === '
|
|
657
|
+
if (runtime === 'codex') {
|
|
658
|
+
// Codex: skills/up-X folders
|
|
659
|
+
const skillsDir = path.join(targetDir, 'skills');
|
|
660
|
+
if (fs.existsSync(skillsDir)) {
|
|
661
|
+
let skillCount = 0;
|
|
662
|
+
for (const entry of fs.readdirSync(skillsDir, { withFileTypes: true })) {
|
|
663
|
+
if (entry.isDirectory() && entry.name.startsWith('up-')) {
|
|
664
|
+
rmDir(path.join(skillsDir, entry.name));
|
|
665
|
+
skillCount++;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
if (skillCount > 0) {
|
|
669
|
+
console.log(` ${green}✓${reset} Removed ${skillCount} skills (commands)`);
|
|
670
|
+
removed += skillCount;
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
} else if (runtime === 'opencode') {
|
|
510
674
|
const commandDir = path.join(targetDir, 'command');
|
|
511
675
|
if (fs.existsSync(commandDir)) {
|
|
512
676
|
let cmdCount = 0;
|
|
@@ -618,6 +782,41 @@ function install(isGlobal, runtime) {
|
|
|
618
782
|
} else {
|
|
619
783
|
failures.push('commands');
|
|
620
784
|
}
|
|
785
|
+
} else if (runtime === 'codex') {
|
|
786
|
+
// Codex: each command becomes a skill folder under skills/up-X/
|
|
787
|
+
const skillsDir = path.join(targetDir, 'skills');
|
|
788
|
+
fs.mkdirSync(skillsDir, { recursive: true });
|
|
789
|
+
|
|
790
|
+
// Remove old up-* skill folders
|
|
791
|
+
for (const entry of fs.readdirSync(skillsDir, { withFileTypes: true })) {
|
|
792
|
+
if (entry.isDirectory() && entry.name.startsWith('up-')) {
|
|
793
|
+
rmDir(path.join(skillsDir, entry.name));
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
let skillCount = 0;
|
|
798
|
+
for (const file of fs.readdirSync(cmdsSrc)) {
|
|
799
|
+
if (file.endsWith('.md')) {
|
|
800
|
+
const commandName = file.replace(/\.md$/, '');
|
|
801
|
+
const skillName = `up-${commandName}`;
|
|
802
|
+
const skillDir = path.join(skillsDir, skillName);
|
|
803
|
+
fs.mkdirSync(skillDir, { recursive: true });
|
|
804
|
+
fs.mkdirSync(path.join(skillDir, 'agents'), { recursive: true });
|
|
805
|
+
|
|
806
|
+
let content = fs.readFileSync(path.join(cmdsSrc, file), 'utf8');
|
|
807
|
+
content = replacePaths(content, pathPrefix, runtime);
|
|
808
|
+
|
|
809
|
+
const { skillMd, openaiYaml } = convertCommandToCodexSkill(content, commandName);
|
|
810
|
+
fs.writeFileSync(path.join(skillDir, 'SKILL.md'), skillMd);
|
|
811
|
+
fs.writeFileSync(path.join(skillDir, 'agents', 'openai.yaml'), openaiYaml);
|
|
812
|
+
skillCount++;
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
if (skillCount > 0) {
|
|
816
|
+
console.log(` ${green}✓${reset} Installed ${skillCount} skills (commands)`);
|
|
817
|
+
} else {
|
|
818
|
+
failures.push('commands');
|
|
819
|
+
}
|
|
621
820
|
} else {
|
|
622
821
|
// Claude & Gemini: nested commands/up/
|
|
623
822
|
const cmdsDest = path.join(targetDir, 'commands', 'up');
|
|
@@ -644,6 +843,15 @@ function install(isGlobal, runtime) {
|
|
|
644
843
|
}
|
|
645
844
|
}
|
|
646
845
|
|
|
846
|
+
// Codex needs old .toml files removed too
|
|
847
|
+
if (runtime === 'codex') {
|
|
848
|
+
for (const file of fs.readdirSync(agentsDest)) {
|
|
849
|
+
if (file.startsWith('up-') && file.endsWith('.toml')) {
|
|
850
|
+
fs.unlinkSync(path.join(agentsDest, file));
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
|
|
647
855
|
// Copy UP agents with runtime conversion
|
|
648
856
|
let agentCount = 0;
|
|
649
857
|
for (const file of fs.readdirSync(agentsSrc)) {
|
|
@@ -653,11 +861,18 @@ function install(isGlobal, runtime) {
|
|
|
653
861
|
|
|
654
862
|
if (runtime === 'gemini') {
|
|
655
863
|
content = convertAgentToGemini(content);
|
|
864
|
+
fs.writeFileSync(path.join(agentsDest, file), content);
|
|
656
865
|
} else if (runtime === 'opencode') {
|
|
657
866
|
content = convertAgentToOpencode(content);
|
|
867
|
+
fs.writeFileSync(path.join(agentsDest, file), content);
|
|
868
|
+
} else if (runtime === 'codex') {
|
|
869
|
+
// Codex agents are .toml not .md
|
|
870
|
+
const baseName = file.replace(/\.md$/, '');
|
|
871
|
+
const tomlContent = convertAgentToCodex(content, baseName);
|
|
872
|
+
fs.writeFileSync(path.join(agentsDest, `${baseName}.toml`), tomlContent);
|
|
873
|
+
} else {
|
|
874
|
+
fs.writeFileSync(path.join(agentsDest, file), content);
|
|
658
875
|
}
|
|
659
|
-
|
|
660
|
-
fs.writeFileSync(path.join(agentsDest, file), content);
|
|
661
876
|
agentCount++;
|
|
662
877
|
}
|
|
663
878
|
}
|
|
@@ -740,6 +955,32 @@ function install(isGlobal, runtime) {
|
|
|
740
955
|
}
|
|
741
956
|
}
|
|
742
957
|
|
|
958
|
+
// 4b. Configure Codex config.toml with [agents] max_depth
|
|
959
|
+
if (runtime === 'codex') {
|
|
960
|
+
const configPath = path.join(targetDir, 'config.toml');
|
|
961
|
+
let existing = '';
|
|
962
|
+
if (fs.existsSync(configPath)) {
|
|
963
|
+
existing = fs.readFileSync(configPath, 'utf8');
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
// UP needs deeper agent nesting than Codex default (max_depth=1).
|
|
967
|
+
// Hierarchy: CEO → Chiefs → Supervisors → Operationals = 4 levels.
|
|
968
|
+
// We do an idempotent merge: if [agents] section exists, only add missing keys.
|
|
969
|
+
const upMarker = '# UP — added by up-cc installer';
|
|
970
|
+
if (!existing.includes(upMarker)) {
|
|
971
|
+
const upConfig =
|
|
972
|
+
`\n${upMarker}\n` +
|
|
973
|
+
`[agents]\n` +
|
|
974
|
+
`max_depth = 4\n` +
|
|
975
|
+
`max_threads = 8\n` +
|
|
976
|
+
`job_max_runtime_seconds = 3600\n`;
|
|
977
|
+
fs.writeFileSync(configPath, existing + upConfig);
|
|
978
|
+
console.log(` ${green}✓${reset} Configured config.toml ([agents] max_depth=4, max_threads=8)`);
|
|
979
|
+
} else {
|
|
980
|
+
console.log(` ${dim}config.toml already has UP settings — skipped${reset}`);
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
|
|
743
984
|
// 5. Write VERSION file
|
|
744
985
|
const versionDest = path.join(upDest, 'VERSION');
|
|
745
986
|
fs.writeFileSync(versionDest, VERSION);
|
|
@@ -760,7 +1001,10 @@ function install(isGlobal, runtime) {
|
|
|
760
1001
|
process.exit(1);
|
|
761
1002
|
}
|
|
762
1003
|
|
|
763
|
-
|
|
1004
|
+
let command;
|
|
1005
|
+
if (runtime === 'opencode') command = '/up-ajuda';
|
|
1006
|
+
else if (runtime === 'codex') command = '$up-ajuda';
|
|
1007
|
+
else command = '/up:ajuda';
|
|
764
1008
|
console.log(`\n ${green}Done!${reset} Run ${cyan}${command}${reset} in ${label} to get started.\n`);
|
|
765
1009
|
}
|
|
766
1010
|
|
|
@@ -777,13 +1021,15 @@ function promptRuntime(callback) {
|
|
|
777
1021
|
console.log(` ${cyan}1${reset}) Claude Code ${dim}(~/.claude)${reset}`);
|
|
778
1022
|
console.log(` ${cyan}2${reset}) Gemini ${dim}(~/.gemini)${reset}`);
|
|
779
1023
|
console.log(` ${cyan}3${reset}) OpenCode ${dim}(~/.config/opencode)${reset}`);
|
|
780
|
-
console.log(` ${cyan}4${reset})
|
|
1024
|
+
console.log(` ${cyan}4${reset}) Codex CLI ${dim}(~/.codex)${reset}`);
|
|
1025
|
+
console.log(` ${cyan}5${reset}) All\n`);
|
|
781
1026
|
|
|
782
1027
|
rl.question(` Choice ${dim}[1]${reset}: `, (answer) => {
|
|
783
1028
|
answered = true;
|
|
784
1029
|
rl.close();
|
|
785
1030
|
const choice = answer.trim() || '1';
|
|
786
|
-
if (choice === '
|
|
1031
|
+
if (choice === '5') callback(['claude', 'gemini', 'opencode', 'codex']);
|
|
1032
|
+
else if (choice === '4') callback(['codex']);
|
|
787
1033
|
else if (choice === '3') callback(['opencode']);
|
|
788
1034
|
else if (choice === '2') callback(['gemini']);
|
|
789
1035
|
else callback(['claude']);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "up-cc",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Simplified spec-driven development for Claude Code, Gemini and
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"description": "Simplified spec-driven development for Claude Code, Gemini, OpenCode and OpenAI Codex.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"up-cc": "bin/install.js"
|
|
7
7
|
},
|