bankai-cli 0.6.11 → 0.6.13

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.
Files changed (3) hide show
  1. package/README.md +3 -0
  2. package/dist/main.js +136 -54
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -49,6 +49,9 @@ npm install -g bankai-cli
49
49
  # Launch a specific agent with bypass flags
50
50
  bankai claude
51
51
 
52
+ # Pass args directly to the target agent
53
+ bankai codex -C /path/to/project
54
+
52
55
  # Interactive agent picker
53
56
  bankai
54
57
 
package/dist/main.js CHANGED
@@ -6,15 +6,31 @@ import { createRequire } from "module";
6
6
 
7
7
  // src/commands/run.ts
8
8
  import { spawn } from "child_process";
9
+ import { readFileSync, writeFileSync, appendFileSync, mkdirSync } from "fs";
10
+ import { join } from "path";
11
+ import { homedir } from "os";
9
12
  import chalk2 from "chalk";
10
13
 
11
14
  // src/registry/builtin.ts
12
15
  var builtinAgents = [
13
16
  {
14
- type: "cli",
17
+ type: "settings",
15
18
  cmd: "claude",
16
19
  displayName: "Claude Code",
17
- lines: ["claude --dangerously-skip-permissions"]
20
+ lines: ["claude --dangerously-skip-permissions"],
21
+ targets: [
22
+ {
23
+ kind: "json",
24
+ scope: "global",
25
+ filePath: "~/.claude/settings.json",
26
+ merge: {
27
+ sandbox: {
28
+ enabled: false
29
+ }
30
+ },
31
+ description: "Global (~/.claude/settings.json) \u2014 disable sandbox"
32
+ }
33
+ ]
18
34
  },
19
35
  {
20
36
  type: "cli",
@@ -32,7 +48,7 @@ var builtinAgents = [
32
48
  type: "cli",
33
49
  cmd: "gemini",
34
50
  displayName: "Gemini CLI",
35
- lines: ["gemini --yolo"],
51
+ lines: ["gemini --yolo --sandbox=false"],
36
52
  cmdAliases: ["gemini-cli"]
37
53
  },
38
54
  {
@@ -60,10 +76,18 @@ var builtinAgents = [
60
76
  displayName: "Kimi Code",
61
77
  lines: ["kimi --yolo"]
62
78
  },
79
+ {
80
+ type: "cli",
81
+ cmd: "opencode",
82
+ displayName: "OpenCode",
83
+ lines: ["OPENCODE_YOLO=true opencode"],
84
+ cmdAliases: ["opencode-yolo"]
85
+ },
63
86
  {
64
87
  type: "settings",
65
88
  cmd: "cursor-agent",
66
89
  displayName: "Cursor Agent CLI",
90
+ lines: ["cursor-agent --yolo"],
67
91
  targets: [
68
92
  {
69
93
  kind: "json",
@@ -78,7 +102,8 @@ var builtinAgents = [
78
102
  "Delete(**)",
79
103
  "Grep(**)",
80
104
  "LS(**)"
81
- ]
105
+ ],
106
+ deny: []
82
107
  }
83
108
  },
84
109
  description: "Project (.cursor/cli.json)"
@@ -96,7 +121,8 @@ var builtinAgents = [
96
121
  "Delete(**)",
97
122
  "Grep(**)",
98
123
  "LS(**)"
99
- ]
124
+ ],
125
+ deny: []
100
126
  }
101
127
  },
102
128
  description: "Global (~/.cursor/cli-config.json)"
@@ -176,7 +202,8 @@ var SettingsAgentDefSchema = z.object({
176
202
  cmd: z.string().min(1),
177
203
  displayName: z.string().optional(),
178
204
  cmdAliases: z.array(z.string().min(1)).optional(),
179
- targets: z.array(SettingsTargetSchema).min(1)
205
+ targets: z.array(SettingsTargetSchema).min(1),
206
+ lines: z.array(z.string().min(1)).optional()
180
207
  });
181
208
  var AgentDefSchema = z.preprocess(
182
209
  (val) => typeof val === "object" && val !== null && !("type" in val) ? { ...val, type: "cli" } : val,
@@ -254,8 +281,6 @@ function resolveAll(customFilePath) {
254
281
 
255
282
  // src/commands/apply.ts
256
283
  import chalk from "chalk";
257
- import select from "@inquirer/select";
258
- import confirm from "@inquirer/confirm";
259
284
 
260
285
  // src/settings.ts
261
286
  import fs2 from "fs";
@@ -278,6 +303,18 @@ function deepMerge(base, overlay) {
278
303
  baseVal,
279
304
  overVal
280
305
  );
306
+ } else if (Array.isArray(baseVal) && Array.isArray(overVal)) {
307
+ if (overVal.length === 0) {
308
+ result[key] = [];
309
+ } else {
310
+ const merged = [...baseVal];
311
+ for (const item of overVal) {
312
+ if (!merged.some((existing) => JSON.stringify(existing) === JSON.stringify(item))) {
313
+ merged.push(item);
314
+ }
315
+ }
316
+ result[key] = merged;
317
+ }
281
318
  } else {
282
319
  result[key] = overVal;
283
320
  }
@@ -292,8 +329,9 @@ function isDeepSubset(haystack, needle) {
292
329
  return Object.keys(n).every((key) => isDeepSubset(h[key], n[key]));
293
330
  }
294
331
  if (Array.isArray(needle) && Array.isArray(haystack)) {
295
- if (needle.length !== haystack.length) return false;
296
- return needle.every((item, i) => isDeepSubset(haystack[i], item));
332
+ return needle.every(
333
+ (needleItem) => haystack.some((haystackItem) => isDeepSubset(haystackItem, needleItem))
334
+ );
297
335
  }
298
336
  return JSON.stringify(haystack) === JSON.stringify(needle);
299
337
  }
@@ -429,6 +467,7 @@ function setNestedValue(obj, path3, value) {
429
467
 
430
468
  // src/commands/apply.ts
431
469
  async function applySettingsAgent(agent) {
470
+ let anyFailed = false;
432
471
  const name = agent.displayName ?? agent.cmd;
433
472
  console.log(chalk.bold.cyan(`# ${name}`));
434
473
  console.log(chalk.dim("This agent uses settings files instead of CLI flags.\n"));
@@ -444,60 +483,38 @@ async function applySettingsAgent(agent) {
444
483
  for (const s of statuses) {
445
484
  console.log(chalk.green(` \u2713 ${s.target.description ?? s.target.kind}`));
446
485
  }
447
- return;
486
+ return false;
448
487
  }
449
488
  for (const s of statuses) {
450
- const label2 = s.target.description ?? s.target.kind;
489
+ const label = s.target.description ?? s.target.kind;
451
490
  if (s.applied) {
452
- console.log(chalk.green(` \u2713 ${label2} (already applied)`));
491
+ console.log(chalk.green(` \u2713 ${label} (already applied)`));
453
492
  } else {
454
- console.log(chalk.yellow(` \u25CB ${label2} (not applied)`));
493
+ console.log(chalk.yellow(` \u25CB ${label} (not applied)`));
455
494
  }
456
495
  }
457
496
  console.log();
458
497
  const unapplied = statuses.filter((s) => !s.applied);
459
- let target;
460
- if (unapplied.length === 1) {
461
- target = unapplied[0].target;
462
- } else {
463
- const chosen = await select({
464
- message: "Select a target to apply:",
465
- choices: unapplied.map((s) => ({
466
- name: s.target.description ?? s.target.kind,
467
- value: s.target
468
- }))
469
- });
470
- target = chosen;
471
- }
472
- const label = target.description ?? target.kind;
473
- const ok = await confirm({
474
- message: `Apply settings to ${label}?`,
475
- default: true
476
- });
477
- if (!ok) {
478
- console.log(chalk.dim("Cancelled."));
479
- return;
480
- }
481
- try {
482
- applySettings(target);
483
- console.log(chalk.green(`
484
- \u2713 Applied settings to ${label}`));
485
- if (target.kind === "sqlite") {
486
- console.log(chalk.yellow("\nRestart the application for changes to take effect."));
498
+ for (const s of unapplied) {
499
+ const label = s.target.description ?? s.target.kind;
500
+ try {
501
+ applySettings(s.target);
502
+ console.log(chalk.green(` \u2713 Applied: ${label}`));
503
+ } catch (err) {
504
+ const msg = err instanceof Error ? err.message : String(err);
505
+ console.error(chalk.yellow(` \u26A0 Failed: ${label} \u2014 ${msg} (continuing anyway)`));
506
+ anyFailed = true;
487
507
  }
488
- } catch (err) {
489
- const msg = err instanceof Error ? err.message : String(err);
490
- console.error(chalk.red(`
491
- Failed to apply settings: ${msg}`));
492
- process.exitCode = 1;
493
508
  }
509
+ return anyFailed;
494
510
  }
495
511
 
496
512
  // src/commands/run.ts
497
513
  function execAgent(line, extraArgs = []) {
498
514
  const [cmd, ...args2] = line.split(/\s+/);
515
+ const { GH_TOKEN, ...cleanEnv } = process.env;
499
516
  return new Promise((resolve) => {
500
- const child = spawn(cmd, [...args2, ...extraArgs], { stdio: "inherit", shell: true });
517
+ const child = spawn(cmd, [...args2, ...extraArgs], { stdio: "inherit", shell: true, env: cleanEnv });
501
518
  child.on("close", (code) => resolve(code ?? 1));
502
519
  child.on("error", (err) => {
503
520
  console.error(chalk2.red(`Failed to start: ${err.message}`));
@@ -505,6 +522,35 @@ function execAgent(line, extraArgs = []) {
505
522
  });
506
523
  });
507
524
  }
525
+ function ensureCursorAgentTrust() {
526
+ const cwd = process.cwd();
527
+ const slug = cwd.replace(/^\//, "").replace(/[/.]/g, "-");
528
+ const dir = join(homedir(), ".cursor", "projects", slug);
529
+ const file = join(dir, ".workspace-trusted");
530
+ try {
531
+ readFileSync(file, "utf-8");
532
+ return;
533
+ } catch {
534
+ mkdirSync(dir, { recursive: true });
535
+ }
536
+ const content = JSON.stringify({ trustedAt: (/* @__PURE__ */ new Date()).toISOString(), workspacePath: cwd });
537
+ writeFileSync(file, content);
538
+ }
539
+ function ensureCodexTrust() {
540
+ const configPath = join(homedir(), ".codex", "config.toml");
541
+ const cwd = process.cwd();
542
+ const key = `[projects."${cwd}"]`;
543
+ try {
544
+ const content = readFileSync(configPath, "utf-8");
545
+ if (content.match(new RegExp(`^\\[projects\\."${cwd.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}"\\]`, "m"))) return;
546
+ } catch {
547
+ mkdirSync(join(homedir(), ".codex"), { recursive: true });
548
+ }
549
+ appendFileSync(configPath, `
550
+ ${key}
551
+ trust_level = "trusted"
552
+ `);
553
+ }
508
554
  async function runAgent(cmd, extraArgs = []) {
509
555
  const agent = resolveAgent(cmd);
510
556
  if (!agent) {
@@ -516,10 +562,13 @@ Run ${chalk2.yellow("bankai agents")} to see available agents, or ${chalk2.yello
516
562
  return;
517
563
  }
518
564
  if (agent.type === "settings") {
519
- await applySettingsAgent(agent);
520
- const code = await execAgent(agent.cmd, extraArgs);
521
- process.exitCode = code;
565
+ if (agent.cmd === "cursor-agent") ensureCursorAgentTrust();
566
+ const settingsFailed = await applySettingsAgent(agent);
567
+ const line = agent.lines?.[0] ?? agent.cmd;
568
+ const code = await execAgent(line, extraArgs);
569
+ process.exitCode = code || (settingsFailed ? 1 : 0);
522
570
  } else {
571
+ if (agent.cmd === "codex") ensureCodexTrust();
523
572
  const line = agent.lines[0];
524
573
  const code = await execAgent(line, extraArgs);
525
574
  process.exitCode = code;
@@ -665,7 +714,7 @@ function removeAgentCommand(cmd) {
665
714
 
666
715
  // src/commands/select.ts
667
716
  import chalk8 from "chalk";
668
- import select2 from "@inquirer/select";
717
+ import select from "@inquirer/select";
669
718
 
670
719
  // src/ui/fade.ts
671
720
  import chalk7 from "chalk";
@@ -769,7 +818,7 @@ async function selectAgent() {
769
818
  const agents = installed.length > 0 ? installed : all;
770
819
  const label = installed.length > 0 ? "Detected agents on this system" : "No agents detected \u2014 showing all supported agents";
771
820
  console.log(chalk8.dim(label));
772
- const chosen = await select2({
821
+ const chosen = await select({
773
822
  message: "Select an agent:",
774
823
  choices: agents.map((a) => ({
775
824
  name: a.displayName ?? a.cmd,
@@ -779,6 +828,31 @@ async function selectAgent() {
779
828
  await runAgent(chosen);
780
829
  }
781
830
 
831
+ // src/argv.ts
832
+ var RESERVED_TOP_LEVEL_COMMANDS = /* @__PURE__ */ new Set(["agents", "add", "edit", "remove", "help"]);
833
+ var RESERVED_TOP_LEVEL_FLAGS = /* @__PURE__ */ new Set(["-h", "--help", "-V", "--version"]);
834
+ function stripLeadingSeparator(args2) {
835
+ return args2[0] === "--" ? args2.slice(1) : args2;
836
+ }
837
+ function extractDirectAgentInvocation(argv) {
838
+ if (argv.length === 0) return null;
839
+ const [first, ...rest] = argv;
840
+ if (RESERVED_TOP_LEVEL_FLAGS.has(first)) return null;
841
+ if (RESERVED_TOP_LEVEL_COMMANDS.has(first)) return null;
842
+ if (first === "-a" || first === "--agent") {
843
+ const [cmd, ...extraArgs] = rest;
844
+ if (!cmd || cmd.startsWith("-")) return null;
845
+ return { cmd, extraArgs: stripLeadingSeparator(extraArgs) };
846
+ }
847
+ if (first.startsWith("--agent=")) {
848
+ const cmd = first.slice("--agent=".length).trim();
849
+ if (!cmd || cmd.startsWith("-")) return null;
850
+ return { cmd, extraArgs: stripLeadingSeparator(rest) };
851
+ }
852
+ if (first.startsWith("-")) return null;
853
+ return { cmd: first, extraArgs: stripLeadingSeparator(rest) };
854
+ }
855
+
782
856
  // src/main.ts
783
857
  var require2 = createRequire(import.meta.url);
784
858
  var { version } = require2("../package.json");
@@ -807,7 +881,15 @@ program.command("remove <cmd>").description("Remove a custom agent").action((cmd
807
881
  var args = process.argv.slice(2);
808
882
  var isTopLevelHelp = args.length <= 1 && (args.includes("--help") || args.includes("-h"));
809
883
  if (isTopLevelHelp) await showFade();
810
- program.parseAsync().catch((err) => {
884
+ var directInvocation = extractDirectAgentInvocation(args);
885
+ var run = async () => {
886
+ if (directInvocation) {
887
+ await runAgent(directInvocation.cmd, directInvocation.extraArgs);
888
+ return;
889
+ }
890
+ await program.parseAsync();
891
+ };
892
+ run().catch((err) => {
811
893
  if (err?.name === "ExitPromptError") {
812
894
  process.exit(130);
813
895
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bankai-cli",
3
- "version": "0.6.11",
3
+ "version": "0.6.13",
4
4
  "description": "Launch coding agent CLIs with approval-bypass flags",
5
5
  "repository": {
6
6
  "type": "git",