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 CHANGED
@@ -1140,8 +1140,23 @@ async function ensureHooksConfig(baseDir) {
1140
1140
  await fs3__default.default.writeJson(configPath, defaultConfig, { spaces: 2 });
1141
1141
  } else {
1142
1142
  const existingConfig = await fs3__default.default.readJson(configPath);
1143
+ let needsUpdate = false;
1143
1144
  if (!existingConfig.hooks) {
1144
1145
  existingConfig.hooks = allHookTypes;
1146
+ needsUpdate = true;
1147
+ }
1148
+ if (!existingConfig.defaultModel) {
1149
+ const subagent = existingConfig.defaultSubagent || "claude";
1150
+ const modelDefaults = {
1151
+ claude: ":sonnet",
1152
+ codex: "gpt-5",
1153
+ gemini: "gemini-2.5-pro",
1154
+ cursor: "auto"
1155
+ };
1156
+ existingConfig.defaultModel = modelDefaults[subagent] || ":sonnet";
1157
+ needsUpdate = true;
1158
+ }
1159
+ if (needsUpdate) {
1145
1160
  await fs3__default.default.writeJson(configPath, existingConfig, { spaces: 2 });
1146
1161
  }
1147
1162
  }
@@ -3565,6 +3580,12 @@ function createExecutionRequest(options) {
3565
3580
  if (options.agents !== void 0) {
3566
3581
  result.agents = options.agents;
3567
3582
  }
3583
+ if (options.tools !== void 0) {
3584
+ result.tools = options.tools;
3585
+ }
3586
+ if (options.disallowedTools !== void 0) {
3587
+ result.disallowedTools = options.disallowedTools;
3588
+ }
3568
3589
  if (options.mcpServerName !== void 0) {
3569
3590
  result.mcpServerName = options.mcpServerName;
3570
3591
  }
@@ -4014,6 +4035,8 @@ var init_engine = __esm({
4014
4035
  project_path: context.request.workingDirectory,
4015
4036
  ...context.request.model !== void 0 && { model: context.request.model },
4016
4037
  ...context.request.agents !== void 0 && { agents: context.request.agents },
4038
+ ...context.request.tools !== void 0 && { tools: context.request.tools },
4039
+ ...context.request.disallowedTools !== void 0 && { disallowedTools: context.request.disallowedTools },
4017
4040
  iteration: iterationNumber
4018
4041
  },
4019
4042
  timeout: context.request.timeoutMs || this.engineConfig.config.mcpTimeout,
@@ -7179,6 +7202,16 @@ var init_shell_backend = __esm({
7179
7202
  if (isPython && request.arguments?.agents) {
7180
7203
  args.push("--agents", request.arguments.agents);
7181
7204
  }
7205
+ if (isPython && request.arguments?.tools && Array.isArray(request.arguments.tools)) {
7206
+ for (const tool of request.arguments.tools) {
7207
+ args.push("--tool", tool);
7208
+ }
7209
+ }
7210
+ if (isPython && request.arguments?.disallowedTools && Array.isArray(request.arguments.disallowedTools)) {
7211
+ for (const tool of request.arguments.disallowedTools) {
7212
+ args.push("--disallowed-tool", tool);
7213
+ }
7214
+ }
7182
7215
  if (this.config.debug) {
7183
7216
  engineLogger.debug(`Executing script: ${command} ${args.join(" ")}`);
7184
7217
  engineLogger.debug(`Working directory: ${this.config.workingDirectory}`);
@@ -12584,6 +12617,9 @@ async function mainCommandHandler(args, options, command) {
12584
12617
  if (options.agents && selectedBackend !== "shell") {
12585
12618
  console.error(chalk15__default.default.yellow("\n\u26A0\uFE0F Note: --agents flag is only supported with shell backend and will be ignored"));
12586
12619
  }
12620
+ if ((options.tools || options.disallowedTools) && selectedBackend !== "shell") {
12621
+ console.error(chalk15__default.default.yellow("\n\u26A0\uFE0F Note: --tools and --disallowed-tools flags are only supported with shell backend and will be ignored"));
12622
+ }
12587
12623
  const executionRequest = createExecutionRequest({
12588
12624
  instruction,
12589
12625
  subagent: options.subagent,
@@ -12591,7 +12627,9 @@ async function mainCommandHandler(args, options, command) {
12591
12627
  workingDirectory: config.workingDirectory,
12592
12628
  maxIterations: options.maxIterations || config.defaultMaxIterations,
12593
12629
  model: options.model || config.defaultModel,
12594
- agents: options.agents
12630
+ agents: options.agents,
12631
+ tools: options.tools,
12632
+ disallowedTools: options.disallowedTools
12595
12633
  });
12596
12634
  const coordinator = new MainExecutionCoordinator(config, options.verbose, options.enableFeedback || false);
12597
12635
  const result = await coordinator.execute(executionRequest);
@@ -12684,6 +12722,11 @@ function createMainCommand() {
12684
12722
  description: "Model to use (optional, subagent-specific)",
12685
12723
  env: "JUNO_CODE_MODEL"
12686
12724
  }),
12725
+ createOption({
12726
+ flags: "--agents <config>",
12727
+ description: "Agents configuration (forwarded to shell backend, ignored for MCP)",
12728
+ env: "JUNO_CODE_AGENTS"
12729
+ }),
12687
12730
  createOption({
12688
12731
  flags: "-I, --interactive",
12689
12732
  description: "Interactive mode for typing/pasting prompts",
@@ -15969,7 +16012,7 @@ ${variables.EDITOR ? `using ${variables.EDITOR} as primary AI subagent` : ""}
15969
16012
  }
15970
16013
  getDefaultModelForSubagent(subagent) {
15971
16014
  const modelDefaults = {
15972
- claude: "sonnet-4",
16015
+ claude: ":sonnet",
15973
16016
  codex: "gpt-5",
15974
16017
  gemini: "gemini-2.5-pro",
15975
16018
  cursor: "auto"
@@ -16262,12 +16305,13 @@ async function initCommandHandler(args, options, command) {
16262
16305
  }
16263
16306
  }
16264
16307
  function configureInitCommand(program) {
16265
- 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) => {
16308
+ 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) => {
16309
+ const taskDescription = description || options.task;
16266
16310
  const initOptions = {
16267
- directory,
16311
+ directory: options.directory,
16268
16312
  force: options.force,
16269
- task: options.task,
16270
- gitUrl: options.gitUrl,
16313
+ task: taskDescription,
16314
+ gitUrl: options.gitRepo || options.gitUrl,
16271
16315
  subagent: options.subagent,
16272
16316
  interactive: options.interactive,
16273
16317
  // Global options
@@ -16279,12 +16323,35 @@ function configureInitCommand(program) {
16279
16323
  };
16280
16324
  await initCommandHandler([], initOptions, command);
16281
16325
  }).addHelpText("after", `
16282
- Examples:
16283
- $ juno-code init # Initialize in current directory
16284
- $ juno-code init my-project # Initialize in ./my-project
16285
- $ juno-code init --interactive # Use simple interactive setup
16326
+ Modes:
16327
+ Interactive Mode (default):
16328
+ $ juno-code init # Opens interactive TUI
16329
+ $ juno-code init --interactive # Force interactive mode
16330
+
16331
+ Inline Mode (for automation):
16332
+ $ juno-code init "Build a REST API" # Minimal inline mode
16333
+ $ juno-code init "Build a REST API" --subagent claude --git-repo https://github.com/owner/repo
16334
+ $ juno-code init "Build a REST API" --subagent codex --directory ./my-project
16286
16335
 
16287
- Simplified Interactive Flow:
16336
+ Examples:
16337
+ # Interactive mode (default)
16338
+ $ juno-code init # Initialize in current directory with TUI
16339
+ $ juno-code init --directory my-project # Initialize in ./my-project with TUI
16340
+
16341
+ # Inline mode (automation-friendly)
16342
+ $ juno-code init "Create a TypeScript library" # Quick init with inline description
16343
+ $ juno-code init "Build web app" --subagent claude # Specify AI subagent
16344
+ $ juno-code init "API server" --git-repo https://github.com/me/repo
16345
+
16346
+ Arguments & Options:
16347
+ [description] Task description (optional - triggers inline mode)
16348
+ -s, --subagent <name> AI subagent: claude, codex, gemini, cursor (default: claude)
16349
+ -g, --git-repo <url> Git repository URL
16350
+ -d, --directory <path> Target directory (default: current directory)
16351
+ -f, --force Force overwrite existing files
16352
+ -i, --interactive Force interactive mode
16353
+
16354
+ Interactive Flow:
16288
16355
  1. Project Root \u2192 Specify target directory
16289
16356
  2. Main Task \u2192 Multi-line description (no character limits)
16290
16357
  3. Subagent Selection \u2192 Choose from Claude, Codex, Gemini, Cursor
@@ -16292,10 +16359,10 @@ Simplified Interactive Flow:
16292
16359
  5. Save \u2192 Handle existing files with override/cancel options
16293
16360
 
16294
16361
  Notes:
16362
+ - All inline mode arguments are optional
16363
+ - Defaults: directory=cwd, subagent=claude, no git repo
16295
16364
  - No prompt cost calculation or token counting
16296
16365
  - No character limits on task descriptions
16297
- - Simple file structure with basic templates
16298
- - Focus on quick project setup without complexity
16299
16366
  `);
16300
16367
  }
16301
16368
 
@@ -16361,6 +16428,9 @@ async function startCommandHandler(args, options, command) {
16361
16428
  backend: options.backend,
16362
16429
  maxIterations: options.maxIterations,
16363
16430
  model: options.model,
16431
+ agents: options.agents,
16432
+ tools: options.tools,
16433
+ disallowedTools: options.disallowedTools,
16364
16434
  directory: options.directory,
16365
16435
  verbose: options.verbose,
16366
16436
  quiet: options.quiet,
@@ -16395,7 +16465,7 @@ async function startCommandHandler(args, options, command) {
16395
16465
  }
16396
16466
  }
16397
16467
  function configureStartCommand(program) {
16398
- 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) => {
16468
+ 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) => {
16399
16469
  const allOptions2 = command.optsWithGlobals ? command.optsWithGlobals() : { ...command.opts(), ...options };
16400
16470
  if (allOptions2.saveMetrics === true) {
16401
16471
  allOptions2.saveMetrics = true;
@@ -23638,7 +23708,7 @@ function handleCLIError(error, verbose = false) {
23638
23708
  process.exit(EXIT_CODES.UNEXPECTED_ERROR);
23639
23709
  }
23640
23710
  function setupGlobalOptions(program) {
23641
- 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)");
23711
+ 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)");
23642
23712
  program.exitOverride((err) => {
23643
23713
  if (err.code === "commander.helpDisplayed") {
23644
23714
  process.exit(0);
@@ -23656,7 +23726,7 @@ function setupGlobalOptions(program) {
23656
23726
  });
23657
23727
  }
23658
23728
  function setupMainCommand(program) {
23659
- 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) => {
23729
+ 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) => {
23660
23730
  try {
23661
23731
  const globalOptions = program.opts();
23662
23732
  const definedGlobalOptions = Object.fromEntries(
@@ -23739,11 +23809,13 @@ function setupCompletion(program) {
23739
23809
  function setupAliases(program) {
23740
23810
  const subagents = ["claude", "cursor", "codex", "gemini"];
23741
23811
  for (const subagent of subagents) {
23742
- 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) => {
23812
+ 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) => {
23743
23813
  try {
23744
23814
  const { mainCommandHandler: mainCommandHandler2 } = await Promise.resolve().then(() => (init_main(), main_exports));
23745
23815
  const promptText = Array.isArray(prompt) ? prompt.join(" ") : prompt;
23816
+ const globalOptions = program.opts();
23746
23817
  await mainCommandHandler2([], {
23818
+ ...globalOptions,
23747
23819
  ...options,
23748
23820
  subagent,
23749
23821
  prompt: promptText