juno-code 1.0.28 → 1.0.30
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/dist/bin/cli.js +89 -17
- package/dist/bin/cli.js.map +1 -1
- package/dist/bin/cli.mjs +89 -17
- package/dist/bin/cli.mjs.map +1 -1
- package/dist/index.js +24 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +24 -1
- package/dist/index.mjs.map +1 -1
- package/dist/templates/services/claude.py +17 -4
- package/package.json +6 -6
package/dist/bin/cli.mjs
CHANGED
|
@@ -1104,8 +1104,23 @@ async function ensureHooksConfig(baseDir) {
|
|
|
1104
1104
|
await fs3.writeJson(configPath, defaultConfig, { spaces: 2 });
|
|
1105
1105
|
} else {
|
|
1106
1106
|
const existingConfig = await fs3.readJson(configPath);
|
|
1107
|
+
let needsUpdate = false;
|
|
1107
1108
|
if (!existingConfig.hooks) {
|
|
1108
1109
|
existingConfig.hooks = allHookTypes;
|
|
1110
|
+
needsUpdate = true;
|
|
1111
|
+
}
|
|
1112
|
+
if (!existingConfig.defaultModel) {
|
|
1113
|
+
const subagent = existingConfig.defaultSubagent || "claude";
|
|
1114
|
+
const modelDefaults = {
|
|
1115
|
+
claude: ":sonnet",
|
|
1116
|
+
codex: "gpt-5",
|
|
1117
|
+
gemini: "gemini-2.5-pro",
|
|
1118
|
+
cursor: "auto"
|
|
1119
|
+
};
|
|
1120
|
+
existingConfig.defaultModel = modelDefaults[subagent] || ":sonnet";
|
|
1121
|
+
needsUpdate = true;
|
|
1122
|
+
}
|
|
1123
|
+
if (needsUpdate) {
|
|
1109
1124
|
await fs3.writeJson(configPath, existingConfig, { spaces: 2 });
|
|
1110
1125
|
}
|
|
1111
1126
|
}
|
|
@@ -3529,6 +3544,12 @@ function createExecutionRequest(options) {
|
|
|
3529
3544
|
if (options.agents !== void 0) {
|
|
3530
3545
|
result.agents = options.agents;
|
|
3531
3546
|
}
|
|
3547
|
+
if (options.tools !== void 0) {
|
|
3548
|
+
result.tools = options.tools;
|
|
3549
|
+
}
|
|
3550
|
+
if (options.disallowedTools !== void 0) {
|
|
3551
|
+
result.disallowedTools = options.disallowedTools;
|
|
3552
|
+
}
|
|
3532
3553
|
if (options.mcpServerName !== void 0) {
|
|
3533
3554
|
result.mcpServerName = options.mcpServerName;
|
|
3534
3555
|
}
|
|
@@ -3978,6 +3999,8 @@ var init_engine = __esm({
|
|
|
3978
3999
|
project_path: context.request.workingDirectory,
|
|
3979
4000
|
...context.request.model !== void 0 && { model: context.request.model },
|
|
3980
4001
|
...context.request.agents !== void 0 && { agents: context.request.agents },
|
|
4002
|
+
...context.request.tools !== void 0 && { tools: context.request.tools },
|
|
4003
|
+
...context.request.disallowedTools !== void 0 && { disallowedTools: context.request.disallowedTools },
|
|
3981
4004
|
iteration: iterationNumber
|
|
3982
4005
|
},
|
|
3983
4006
|
timeout: context.request.timeoutMs || this.engineConfig.config.mcpTimeout,
|
|
@@ -7143,6 +7166,16 @@ var init_shell_backend = __esm({
|
|
|
7143
7166
|
if (isPython && request.arguments?.agents) {
|
|
7144
7167
|
args.push("--agents", request.arguments.agents);
|
|
7145
7168
|
}
|
|
7169
|
+
if (isPython && request.arguments?.tools && Array.isArray(request.arguments.tools)) {
|
|
7170
|
+
for (const tool of request.arguments.tools) {
|
|
7171
|
+
args.push("--tool", tool);
|
|
7172
|
+
}
|
|
7173
|
+
}
|
|
7174
|
+
if (isPython && request.arguments?.disallowedTools && Array.isArray(request.arguments.disallowedTools)) {
|
|
7175
|
+
for (const tool of request.arguments.disallowedTools) {
|
|
7176
|
+
args.push("--disallowed-tool", tool);
|
|
7177
|
+
}
|
|
7178
|
+
}
|
|
7146
7179
|
if (this.config.debug) {
|
|
7147
7180
|
engineLogger.debug(`Executing script: ${command} ${args.join(" ")}`);
|
|
7148
7181
|
engineLogger.debug(`Working directory: ${this.config.workingDirectory}`);
|
|
@@ -12548,6 +12581,9 @@ async function mainCommandHandler(args, options, command) {
|
|
|
12548
12581
|
if (options.agents && selectedBackend !== "shell") {
|
|
12549
12582
|
console.error(chalk15.yellow("\n\u26A0\uFE0F Note: --agents flag is only supported with shell backend and will be ignored"));
|
|
12550
12583
|
}
|
|
12584
|
+
if ((options.tools || options.disallowedTools) && selectedBackend !== "shell") {
|
|
12585
|
+
console.error(chalk15.yellow("\n\u26A0\uFE0F Note: --tools and --disallowed-tools flags are only supported with shell backend and will be ignored"));
|
|
12586
|
+
}
|
|
12551
12587
|
const executionRequest = createExecutionRequest({
|
|
12552
12588
|
instruction,
|
|
12553
12589
|
subagent: options.subagent,
|
|
@@ -12555,7 +12591,9 @@ async function mainCommandHandler(args, options, command) {
|
|
|
12555
12591
|
workingDirectory: config.workingDirectory,
|
|
12556
12592
|
maxIterations: options.maxIterations || config.defaultMaxIterations,
|
|
12557
12593
|
model: options.model || config.defaultModel,
|
|
12558
|
-
agents: options.agents
|
|
12594
|
+
agents: options.agents,
|
|
12595
|
+
tools: options.tools,
|
|
12596
|
+
disallowedTools: options.disallowedTools
|
|
12559
12597
|
});
|
|
12560
12598
|
const coordinator = new MainExecutionCoordinator(config, options.verbose, options.enableFeedback || false);
|
|
12561
12599
|
const result = await coordinator.execute(executionRequest);
|
|
@@ -12648,6 +12686,11 @@ function createMainCommand() {
|
|
|
12648
12686
|
description: "Model to use (optional, subagent-specific)",
|
|
12649
12687
|
env: "JUNO_CODE_MODEL"
|
|
12650
12688
|
}),
|
|
12689
|
+
createOption({
|
|
12690
|
+
flags: "--agents <config>",
|
|
12691
|
+
description: "Agents configuration (forwarded to shell backend, ignored for MCP)",
|
|
12692
|
+
env: "JUNO_CODE_AGENTS"
|
|
12693
|
+
}),
|
|
12651
12694
|
createOption({
|
|
12652
12695
|
flags: "-I, --interactive",
|
|
12653
12696
|
description: "Interactive mode for typing/pasting prompts",
|
|
@@ -15933,7 +15976,7 @@ ${variables.EDITOR ? `using ${variables.EDITOR} as primary AI subagent` : ""}
|
|
|
15933
15976
|
}
|
|
15934
15977
|
getDefaultModelForSubagent(subagent) {
|
|
15935
15978
|
const modelDefaults = {
|
|
15936
|
-
claude: "sonnet
|
|
15979
|
+
claude: ":sonnet",
|
|
15937
15980
|
codex: "gpt-5",
|
|
15938
15981
|
gemini: "gemini-2.5-pro",
|
|
15939
15982
|
cursor: "auto"
|
|
@@ -16226,12 +16269,13 @@ async function initCommandHandler(args, options, command) {
|
|
|
16226
16269
|
}
|
|
16227
16270
|
}
|
|
16228
16271
|
function configureInitCommand(program) {
|
|
16229
|
-
program.command("init").description("Initialize new juno-code project
|
|
16272
|
+
program.command("init").description("Initialize new juno-code project - supports both interactive and inline modes").argument("[description]", "Task description for inline mode (optional - triggers inline mode if provided)").option("-s, --subagent <name>", "AI subagent to use (claude, codex, gemini, cursor)").option("-g, --git-repo <url>", "Git repository URL").option("-d, --directory <path>", "Target directory (default: current directory)").option("-f, --force", "Force overwrite existing files").option("-i, --interactive", "Force interactive mode (even if description is provided)").option("--git-url <url>", "Git repository URL (alias for --git-repo)").option("-t, --task <description>", "Task description (alias for positional description)").action(async (description, options, command) => {
|
|
16273
|
+
const taskDescription = description || options.task;
|
|
16230
16274
|
const initOptions = {
|
|
16231
|
-
directory,
|
|
16275
|
+
directory: options.directory,
|
|
16232
16276
|
force: options.force,
|
|
16233
|
-
task:
|
|
16234
|
-
gitUrl: options.gitUrl,
|
|
16277
|
+
task: taskDescription,
|
|
16278
|
+
gitUrl: options.gitRepo || options.gitUrl,
|
|
16235
16279
|
subagent: options.subagent,
|
|
16236
16280
|
interactive: options.interactive,
|
|
16237
16281
|
// Global options
|
|
@@ -16243,12 +16287,35 @@ function configureInitCommand(program) {
|
|
|
16243
16287
|
};
|
|
16244
16288
|
await initCommandHandler([], initOptions, command);
|
|
16245
16289
|
}).addHelpText("after", `
|
|
16246
|
-
|
|
16247
|
-
|
|
16248
|
-
|
|
16249
|
-
|
|
16290
|
+
Modes:
|
|
16291
|
+
Interactive Mode (default):
|
|
16292
|
+
$ juno-code init # Opens interactive TUI
|
|
16293
|
+
$ juno-code init --interactive # Force interactive mode
|
|
16294
|
+
|
|
16295
|
+
Inline Mode (for automation):
|
|
16296
|
+
$ juno-code init "Build a REST API" # Minimal inline mode
|
|
16297
|
+
$ juno-code init "Build a REST API" --subagent claude --git-repo https://github.com/owner/repo
|
|
16298
|
+
$ juno-code init "Build a REST API" --subagent codex --directory ./my-project
|
|
16250
16299
|
|
|
16251
|
-
|
|
16300
|
+
Examples:
|
|
16301
|
+
# Interactive mode (default)
|
|
16302
|
+
$ juno-code init # Initialize in current directory with TUI
|
|
16303
|
+
$ juno-code init --directory my-project # Initialize in ./my-project with TUI
|
|
16304
|
+
|
|
16305
|
+
# Inline mode (automation-friendly)
|
|
16306
|
+
$ juno-code init "Create a TypeScript library" # Quick init with inline description
|
|
16307
|
+
$ juno-code init "Build web app" --subagent claude # Specify AI subagent
|
|
16308
|
+
$ juno-code init "API server" --git-repo https://github.com/me/repo
|
|
16309
|
+
|
|
16310
|
+
Arguments & Options:
|
|
16311
|
+
[description] Task description (optional - triggers inline mode)
|
|
16312
|
+
-s, --subagent <name> AI subagent: claude, codex, gemini, cursor (default: claude)
|
|
16313
|
+
-g, --git-repo <url> Git repository URL
|
|
16314
|
+
-d, --directory <path> Target directory (default: current directory)
|
|
16315
|
+
-f, --force Force overwrite existing files
|
|
16316
|
+
-i, --interactive Force interactive mode
|
|
16317
|
+
|
|
16318
|
+
Interactive Flow:
|
|
16252
16319
|
1. Project Root \u2192 Specify target directory
|
|
16253
16320
|
2. Main Task \u2192 Multi-line description (no character limits)
|
|
16254
16321
|
3. Subagent Selection \u2192 Choose from Claude, Codex, Gemini, Cursor
|
|
@@ -16256,10 +16323,10 @@ Simplified Interactive Flow:
|
|
|
16256
16323
|
5. Save \u2192 Handle existing files with override/cancel options
|
|
16257
16324
|
|
|
16258
16325
|
Notes:
|
|
16326
|
+
- All inline mode arguments are optional
|
|
16327
|
+
- Defaults: directory=cwd, subagent=claude, no git repo
|
|
16259
16328
|
- No prompt cost calculation or token counting
|
|
16260
16329
|
- No character limits on task descriptions
|
|
16261
|
-
- Simple file structure with basic templates
|
|
16262
|
-
- Focus on quick project setup without complexity
|
|
16263
16330
|
`);
|
|
16264
16331
|
}
|
|
16265
16332
|
|
|
@@ -16325,6 +16392,9 @@ async function startCommandHandler(args, options, command) {
|
|
|
16325
16392
|
backend: options.backend,
|
|
16326
16393
|
maxIterations: options.maxIterations,
|
|
16327
16394
|
model: options.model,
|
|
16395
|
+
agents: options.agents,
|
|
16396
|
+
tools: options.tools,
|
|
16397
|
+
disallowedTools: options.disallowedTools,
|
|
16328
16398
|
directory: options.directory,
|
|
16329
16399
|
verbose: options.verbose,
|
|
16330
16400
|
quiet: options.quiet,
|
|
@@ -16359,7 +16429,7 @@ async function startCommandHandler(args, options, command) {
|
|
|
16359
16429
|
}
|
|
16360
16430
|
}
|
|
16361
16431
|
function configureStartCommand(program) {
|
|
16362
|
-
program.command("start").description("Start execution using .juno_task/init.md as prompt").option("-s, --subagent <name>", "Subagent to use (claude, cursor, codex, gemini)").option("-b, --backend <type>", "Backend to use (mcp, shell)").option("-i, --max-iterations <number>", "Maximum number of iterations", parseInt).option("-m, --model <name>", "Model to use for execution").option("-d, --directory <path>", "Project directory (default: current)").option("--enable-feedback", "Enable concurrent feedback collection during execution").option("--show-metrics", "Display performance metrics summary after execution").option("--show-dashboard", "Show interactive performance dashboard after execution").option("--show-trends", "Display performance trends from historical data").option("--save-metrics [file]", "Save performance metrics to file (default: .juno_task/metrics.json)").option("--metrics-file <path>", "Specify custom path for metrics file").option("--dry-run", "Validate configuration and exit without executing").action(async (options, command) => {
|
|
16432
|
+
program.command("start").description("Start execution using .juno_task/init.md as prompt").option("-s, --subagent <name>", "Subagent to use (claude, cursor, codex, gemini)").option("-b, --backend <type>", "Backend to use (mcp, shell)").option("-i, --max-iterations <number>", "Maximum number of iterations", parseInt).option("-m, --model <name>", "Model to use for execution").option("--agents <config>", "Agents configuration (forwarded to shell backend, ignored for MCP)").option("-d, --directory <path>", "Project directory (default: current)").option("--enable-feedback", "Enable concurrent feedback collection during execution").option("--show-metrics", "Display performance metrics summary after execution").option("--show-dashboard", "Show interactive performance dashboard after execution").option("--show-trends", "Display performance trends from historical data").option("--save-metrics [file]", "Save performance metrics to file (default: .juno_task/metrics.json)").option("--metrics-file <path>", "Specify custom path for metrics file").option("--dry-run", "Validate configuration and exit without executing").action(async (options, command) => {
|
|
16363
16433
|
const allOptions2 = command.optsWithGlobals ? command.optsWithGlobals() : { ...command.opts(), ...options };
|
|
16364
16434
|
if (allOptions2.saveMetrics === true) {
|
|
16365
16435
|
allOptions2.saveMetrics = true;
|
|
@@ -23602,7 +23672,7 @@ function handleCLIError(error, verbose = false) {
|
|
|
23602
23672
|
process.exit(EXIT_CODES.UNEXPECTED_ERROR);
|
|
23603
23673
|
}
|
|
23604
23674
|
function setupGlobalOptions(program) {
|
|
23605
|
-
program.option("-v, --verbose", "Enable verbose output with detailed progress").option("-q, --quiet", "Disable rich formatting, use plain text").option("-c, --config <path>", "Configuration file path (.json, .toml, pyproject.toml)").option("-l, --log-file <path>", "Log file path (auto-generated if not specified)").option("--no-color", "Disable colored output").option("--log-level <level>", "Log level for output (error, warn, info, debug, trace)", "info").option("-s, --subagent <name>", "Subagent to use (claude, cursor, codex, gemini)").option("--mcp-timeout <number>", "MCP server timeout in milliseconds", parseInt).option("--enable-feedback", "Enable interactive feedback mode (F+Enter to enter, Q+Enter to submit)");
|
|
23675
|
+
program.option("-v, --verbose", "Enable verbose output with detailed progress").option("-q, --quiet", "Disable rich formatting, use plain text").option("-c, --config <path>", "Configuration file path (.json, .toml, pyproject.toml)").option("-l, --log-file <path>", "Log file path (auto-generated if not specified)").option("--no-color", "Disable colored output").option("--log-level <level>", "Log level for output (error, warn, info, debug, trace)", "info").option("-s, --subagent <name>", "Subagent to use (claude, cursor, codex, gemini)").option("-b, --backend <type>", "Backend to use (mcp, shell)").option("-m, --model <name>", "Model to use (subagent-specific)").option("--agents <config>", "Agents configuration (forwarded to shell backend, ignored for MCP)").option("--tools <tools...>", "Allowed tools for Claude (passed to shell backend, ignored for MCP)").option("--disallowed-tools <tools...>", "Disallowed tools for Claude (passed to shell backend, ignored for MCP)").option("--mcp-timeout <number>", "MCP server timeout in milliseconds", parseInt).option("--enable-feedback", "Enable interactive feedback mode (F+Enter to enter, Q+Enter to submit)");
|
|
23606
23676
|
program.exitOverride((err) => {
|
|
23607
23677
|
if (err.code === "commander.helpDisplayed") {
|
|
23608
23678
|
process.exit(0);
|
|
@@ -23620,7 +23690,7 @@ function setupGlobalOptions(program) {
|
|
|
23620
23690
|
});
|
|
23621
23691
|
}
|
|
23622
23692
|
function setupMainCommand(program) {
|
|
23623
|
-
program.option("-p, --prompt <text>", "Prompt input (file path or inline text)").option("-w, --cwd <path>", "Working directory").option("-i, --max-iterations <number>", "Maximum iterations (-1 for unlimited)", parseInt).option("-
|
|
23693
|
+
program.option("-p, --prompt <text>", "Prompt input (file path or inline text)").option("-w, --cwd <path>", "Working directory").option("-i, --max-iterations <number>", "Maximum iterations (-1 for unlimited)", parseInt).option("-I, --interactive", "Interactive mode for typing prompts").option("-ip, --interactive-prompt", "Launch TUI prompt editor").action(async (options, command) => {
|
|
23624
23694
|
try {
|
|
23625
23695
|
const globalOptions = program.opts();
|
|
23626
23696
|
const definedGlobalOptions = Object.fromEntries(
|
|
@@ -23703,11 +23773,13 @@ function setupCompletion(program) {
|
|
|
23703
23773
|
function setupAliases(program) {
|
|
23704
23774
|
const subagents = ["claude", "cursor", "codex", "gemini"];
|
|
23705
23775
|
for (const subagent of subagents) {
|
|
23706
|
-
program.command(subagent, { hidden: true }).description(`Execute with ${subagent} subagent`).argument("[prompt...]", "Prompt text or file path").option("-i, --max-iterations <number>", "Maximum iterations", parseInt).option("-
|
|
23776
|
+
program.command(subagent, { hidden: true }).description(`Execute with ${subagent} subagent`).argument("[prompt...]", "Prompt text or file path").option("-i, --max-iterations <number>", "Maximum iterations", parseInt).option("-w, --cwd <path>", "Working directory").action(async (prompt, options, command) => {
|
|
23707
23777
|
try {
|
|
23708
23778
|
const { mainCommandHandler: mainCommandHandler2 } = await Promise.resolve().then(() => (init_main(), main_exports));
|
|
23709
23779
|
const promptText = Array.isArray(prompt) ? prompt.join(" ") : prompt;
|
|
23780
|
+
const globalOptions = program.opts();
|
|
23710
23781
|
await mainCommandHandler2([], {
|
|
23782
|
+
...globalOptions,
|
|
23711
23783
|
...options,
|
|
23712
23784
|
subagent,
|
|
23713
23785
|
prompt: promptText
|