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.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-4",
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 with simple setup").argument("[directory]", "Target directory (default: current directory)").option("-f, --force", "Force overwrite existing files").option("-t, --task <description>", "Main task description").option("-g, --git-url <url>", "Git repository URL").option("-i, --interactive", "Launch simple interactive setup").action(async (directory, options, command) => {
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: options.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
- Examples:
16247
- $ juno-code init # Initialize in current directory
16248
- $ juno-code init my-project # Initialize in ./my-project
16249
- $ juno-code init --interactive # Use simple interactive setup
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
- Simplified Interactive Flow:
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("-m, --model <name>", "Model to use (subagent-specific)").option("--agents <agents>", "Agents configuration (forwarded to claude.py when using shell backend)").option("-b, --backend <type>", "Backend to use (mcp, shell)").option("-I, --interactive", "Interactive mode for typing prompts").option("-ip, --interactive-prompt", "Launch TUI prompt editor").action(async (options, command) => {
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("-m, --model <name>", "Model to use").option("-b, --backend <type>", "Backend to use (mcp, shell)").option("-w, --cwd <path>", "Working directory").action(async (prompt, options, command) => {
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