claudish 6.8.0 → 6.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/dist/index.js CHANGED
@@ -33064,6 +33064,16 @@ async function parseArgs(args) {
33064
33064
  if (["auto", "logfile", "off"].includes(mode)) {
33065
33065
  config3.diagMode = mode;
33066
33066
  }
33067
+ } else if (arg === "--team" && i + 1 < args.length) {
33068
+ const models = args[++i].split(",").map((m) => m.trim()).filter(Boolean);
33069
+ config3.team = models;
33070
+ } else if (arg === "--mode" && i + 1 < args.length) {
33071
+ const mode = args[++i].toLowerCase();
33072
+ if (["default", "interactive", "json"].includes(mode)) {
33073
+ config3.teamMode = mode;
33074
+ }
33075
+ } else if ((arg === "-f" || arg === "--file") && i + 1 < args.length) {
33076
+ config3.inputFile = args[++i];
33067
33077
  } else if (arg === "--") {
33068
33078
  config3.claudeArgs.push(...args.slice(i + 1));
33069
33079
  break;
@@ -33941,6 +33951,8 @@ claudish - Run Claude Code with any AI model (OpenRouter, Gemini, OpenAI, MiniMa
33941
33951
  USAGE:
33942
33952
  claudish # Interactive mode (default, shows model selector)
33943
33953
  claudish [OPTIONS] <claude-args...> # Single-shot mode (requires --model)
33954
+ claudish --team a,b,c "prompt" # Run models in parallel (magmux grid)
33955
+ claudish --team a,b,c -f input.md # Team mode with file input
33944
33956
 
33945
33957
  MODEL ROUTING:
33946
33958
  New syntax: provider@model[:concurrency]
@@ -34013,6 +34025,10 @@ OPTIONS:
34013
34025
  --models List ALL models (OpenRouter + OpenCode Zen + Ollama)
34014
34026
  --models <query> Fuzzy search all models by name, ID, or description
34015
34027
  --top-models List recommended/top programming models (curated)
34028
+ --team <models> Run multiple models in parallel (comma-separated)
34029
+ Example: --team minimax-m2.5,kimi-k2.5 "prompt"
34030
+ --mode <mode> Team mode: default (grid), interactive, json
34031
+ -f, --file <path> Read prompt from file (use with --team or single-shot)
34016
34032
  --probe <models...> Show fallback chain for each model (diagnostic)
34017
34033
  --json Output in JSON format (use with --models, --top-models, --probe)
34018
34034
  --force-update Force refresh model cache from OpenRouter API
@@ -34474,7 +34490,7 @@ async function fetchGLMCodingModels() {
34474
34490
  return [];
34475
34491
  }
34476
34492
  }
34477
- var __filename4, __dirname4, VERSION = "6.8.0", CACHE_MAX_AGE_DAYS2 = 2, CLAUDISH_CACHE_DIR2, BUNDLED_MODELS_PATH, CACHED_MODELS_PATH, ALL_MODELS_JSON_PATH;
34493
+ var __filename4, __dirname4, VERSION = "6.9.0", CACHE_MAX_AGE_DAYS2 = 2, CLAUDISH_CACHE_DIR2, BUNDLED_MODELS_PATH, CACHED_MODELS_PATH, ALL_MODELS_JSON_PATH;
34478
34494
  var init_cli = __esm(() => {
34479
34495
  init_config();
34480
34496
  init_model_loader();
@@ -95650,418 +95666,16 @@ var init_tui = __esm(async () => {
95650
95666
  }
95651
95667
  });
95652
95668
 
95653
- // src/team-grid.ts
95654
- var exports_team_grid = {};
95655
- __export(exports_team_grid, {
95656
- runWithGrid: () => runWithGrid
95657
- });
95658
- import { spawn as spawn3 } from "child_process";
95659
- import {
95660
- appendFileSync,
95661
- existsSync as existsSync26,
95662
- mkdirSync as mkdirSync14,
95663
- readFileSync as readFileSync21,
95664
- unlinkSync as unlinkSync8,
95665
- writeFileSync as writeFileSync15
95666
- } from "fs";
95667
- import { dirname as dirname6, join as join27 } from "path";
95668
- import { fileURLToPath as fileURLToPath6 } from "url";
95669
- import { execSync as execSync3 } from "child_process";
95670
- function formatElapsed(ms) {
95671
- const s = Math.floor(ms / 1000);
95672
- if (s < 60)
95673
- return `${s}s`;
95674
- const m2 = Math.floor(s / 60);
95675
- const rem = s % 60;
95676
- return `${m2}m ${rem}s`;
95677
- }
95678
- function findMagmuxBinary() {
95679
- const thisFile = fileURLToPath6(import.meta.url);
95680
- const thisDir = dirname6(thisFile);
95681
- const pkgRoot = join27(thisDir, "..");
95682
- const platform3 = process.platform;
95683
- const arch = process.arch;
95684
- const builtMagmux = join27(pkgRoot, "native", "magmux", "magmux");
95685
- if (existsSync26(builtMagmux))
95686
- return builtMagmux;
95687
- const bundledMagmux = join27(pkgRoot, "native", "magmux", `magmux-${platform3}-${arch}`);
95688
- if (existsSync26(bundledMagmux))
95689
- return bundledMagmux;
95690
- try {
95691
- const result = execSync3("which magmux", { encoding: "utf-8" }).trim();
95692
- if (result)
95693
- return result;
95694
- } catch {}
95695
- throw new Error(`magmux not found. Install it:
95696
- brew install MadAppGang/tap/magmux`);
95697
- }
95698
- function renderGridStatusBar(counts) {
95699
- const elapsed = formatElapsed(counts.elapsedMs);
95700
- const { done, running, failed, total, allDone } = counts;
95701
- if (allDone) {
95702
- if (failed > 0) {
95703
- return [
95704
- "C: claudish team",
95705
- `G: ${done} done`,
95706
- `R: ${failed} failed`,
95707
- `D: ${elapsed}`,
95708
- "R: \u2717 issues",
95709
- "D: ctrl-g q to quit"
95710
- ].join("\t");
95711
- }
95712
- return [
95713
- "C: claudish team",
95714
- `G: ${total} done`,
95715
- `D: ${elapsed}`,
95716
- "G: \u2713 complete",
95717
- "D: ctrl-g q to quit"
95718
- ].join("\t");
95719
- }
95720
- return [
95721
- "C: claudish team",
95722
- `G: ${done} done`,
95723
- `C: ${running} running`,
95724
- `R: ${failed} failed`,
95725
- `D: ${elapsed}`
95726
- ].join("\t");
95727
- }
95728
- function pollStatus(state) {
95729
- const { statusCache, statusPath, sessionPath, anonIds, startTime, timeoutMs, statusbarPath } = state;
95730
- const elapsedMs = Date.now() - startTime;
95731
- let changed = false;
95732
- let done = 0;
95733
- let running = 0;
95734
- let failed = 0;
95735
- for (const anonId of anonIds) {
95736
- const current = statusCache.models[anonId];
95737
- if (current.state === "COMPLETED" || current.state === "FAILED" || current.state === "TIMEOUT") {
95738
- if (current.state === "COMPLETED")
95739
- done++;
95740
- else
95741
- failed++;
95742
- continue;
95743
- }
95744
- const exitCodePath = join27(sessionPath, "work", anonId, ".exit-code");
95745
- if (existsSync26(exitCodePath)) {
95746
- const codeStr = readFileSync21(exitCodePath, "utf-8").trim();
95747
- const code = parseInt(codeStr, 10);
95748
- const isSuccess = code === 0;
95749
- const newState = {
95750
- ...current,
95751
- state: isSuccess ? "COMPLETED" : "FAILED",
95752
- exitCode: code,
95753
- startedAt: current.startedAt ?? new Date().toISOString(),
95754
- completedAt: new Date().toISOString(),
95755
- outputSize: 0
95756
- };
95757
- statusCache.models[anonId] = newState;
95758
- changed = true;
95759
- if (isSuccess)
95760
- done++;
95761
- else
95762
- failed++;
95763
- } else {
95764
- if (!state.interactive && elapsedMs > timeoutMs) {
95765
- const newState = {
95766
- ...current,
95767
- state: "TIMEOUT",
95768
- startedAt: current.startedAt ?? new Date().toISOString(),
95769
- completedAt: new Date().toISOString(),
95770
- outputSize: 0
95771
- };
95772
- statusCache.models[anonId] = newState;
95773
- changed = true;
95774
- failed++;
95775
- } else {
95776
- if (current.state === "PENDING" && elapsedMs > 1000) {
95777
- statusCache.models[anonId] = {
95778
- ...current,
95779
- state: "RUNNING",
95780
- startedAt: current.startedAt ?? new Date().toISOString()
95781
- };
95782
- changed = true;
95783
- }
95784
- running++;
95785
- }
95786
- }
95787
- }
95788
- if (changed) {
95789
- writeFileSync15(statusPath, JSON.stringify(statusCache, null, 2), "utf-8");
95790
- }
95791
- const total = anonIds.length;
95792
- const allDone = done + failed >= total;
95793
- if (allDone && !state.completedAtMs) {
95794
- state.completedAtMs = elapsedMs;
95795
- }
95796
- const counts = {
95797
- done,
95798
- running,
95799
- failed,
95800
- total,
95801
- elapsedMs: state.completedAtMs ?? elapsedMs,
95802
- allDone
95803
- };
95804
- appendFileSync(statusbarPath, renderGridStatusBar(counts) + `
95805
- `);
95806
- return allDone;
95807
- }
95808
- async function runWithGrid(sessionPath, models, input, opts) {
95809
- const timeoutMs = (opts?.timeout ?? 300) * 1000;
95810
- const interactive = opts?.interactive ?? false;
95811
- const manifest = setupSession(sessionPath, models, input);
95812
- mkdirSync14(join27(sessionPath, "errors"), { recursive: true });
95813
- for (const anonId of Object.keys(manifest.models)) {
95814
- const stale = join27(sessionPath, "work", anonId, ".exit-code");
95815
- try {
95816
- unlinkSync8(stale);
95817
- } catch {}
95818
- }
95819
- const gridfilePath = join27(sessionPath, "gridfile.txt");
95820
- const prompt = readFileSync21(join27(sessionPath, "input.md"), "utf-8").replace(/'/g, "'\\''");
95821
- const gridLines = Object.entries(manifest.models).map(([anonId]) => {
95822
- const errorLog = join27(sessionPath, "errors", `${anonId}.log`);
95823
- const exitCodeFile = join27(sessionPath, "work", anonId, ".exit-code");
95824
- const model = manifest.models[anonId].model;
95825
- const paneIndex = Object.keys(manifest.models).indexOf(anonId);
95826
- if (interactive) {
95827
- return `claudish --model ${model} --dangerously-skip-permissions '${prompt}'`;
95828
- }
95829
- return [
95830
- `claudish --model ${model} -y -v '${prompt}' 2>${errorLog};`,
95831
- `_ec=$?; echo $_ec > ${exitCodeFile};`,
95832
- `if [ -n "$MAGMUX_SOCK" ]; then`,
95833
- ` if [ $_ec -eq 0 ]; then`,
95834
- ` echo '{"cmd":"tint","pane":${paneIndex},"color":"green"}' | nc -U "$MAGMUX_SOCK" -w 1 2>/dev/null;`,
95835
- ` echo '{"cmd":"overlay","pane":${paneIndex},"text":"DONE","color":"green"}' | nc -U "$MAGMUX_SOCK" -w 1 2>/dev/null;`,
95836
- ` else`,
95837
- ` echo '{"cmd":"tint","pane":${paneIndex},"color":"red"}' | nc -U "$MAGMUX_SOCK" -w 1 2>/dev/null;`,
95838
- ` echo '{"cmd":"overlay","pane":${paneIndex},"text":"FAIL","color":"red"}' | nc -U "$MAGMUX_SOCK" -w 1 2>/dev/null;`,
95839
- ` fi;`,
95840
- `fi;`,
95841
- `exec sleep 86400`
95842
- ].join(" ");
95843
- });
95844
- writeFileSync15(gridfilePath, gridLines.join(`
95845
- `) + `
95846
- `, "utf-8");
95847
- const magmuxPath = findMagmuxBinary();
95848
- const statusbarPath = join27(sessionPath, "statusbar.txt");
95849
- const statusPath = join27(sessionPath, "status.json");
95850
- const statusCache = JSON.parse(readFileSync21(statusPath, "utf-8"));
95851
- const anonIds = Object.keys(manifest.models);
95852
- const startTime = Date.now();
95853
- appendFileSync(statusbarPath, renderGridStatusBar({
95854
- done: 0,
95855
- running: 0,
95856
- failed: 0,
95857
- total: anonIds.length,
95858
- elapsedMs: 0,
95859
- allDone: false
95860
- }) + `
95861
- `);
95862
- const pollState = {
95863
- statusCache,
95864
- statusPath,
95865
- sessionPath,
95866
- anonIds,
95867
- startTime,
95868
- timeoutMs,
95869
- statusbarPath,
95870
- completedAtMs: null,
95871
- interactive
95872
- };
95873
- const pollInterval = setInterval(() => {
95874
- pollStatus(pollState);
95875
- }, 500);
95876
- const spawnArgs = ["-g", gridfilePath, "-S", statusbarPath];
95877
- if (!interactive) {
95878
- spawnArgs.push("-w");
95879
- }
95880
- const proc = spawn3(magmuxPath, spawnArgs, {
95881
- stdio: "inherit",
95882
- env: { ...process.env }
95883
- });
95884
- await new Promise((resolve4) => {
95885
- proc.on("exit", () => resolve4());
95886
- proc.on("error", () => resolve4());
95887
- });
95888
- clearInterval(pollInterval);
95889
- pollStatus(pollState);
95890
- return JSON.parse(readFileSync21(statusPath, "utf-8"));
95891
- }
95892
- var init_team_grid = __esm(() => {
95893
- init_team_orchestrator();
95894
- });
95895
-
95896
- // src/team-cli.ts
95897
- var exports_team_cli = {};
95898
- __export(exports_team_cli, {
95899
- teamCommand: () => teamCommand
95900
- });
95901
- import { readFileSync as readFileSync22 } from "fs";
95902
- import { join as join28 } from "path";
95903
- function getFlag(args, flag) {
95904
- const idx = args.indexOf(flag);
95905
- if (idx === -1 || idx + 1 >= args.length)
95906
- return;
95907
- return args[idx + 1];
95908
- }
95909
- function hasFlag(args, flag) {
95910
- return args.includes(flag);
95911
- }
95912
- function printStatus(status) {
95913
- const modelIds = Object.keys(status.models).sort();
95914
- console.log(`
95915
- Team Status (started: ${status.startedAt})`);
95916
- console.log("\u2500".repeat(60));
95917
- for (const id of modelIds) {
95918
- const m2 = status.models[id];
95919
- const duration3 = m2.startedAt && m2.completedAt ? `${Math.round((new Date(m2.completedAt).getTime() - new Date(m2.startedAt).getTime()) / 1000)}s` : m2.startedAt ? "running" : "pending";
95920
- const size = m2.outputSize > 0 ? ` (${m2.outputSize} bytes)` : "";
95921
- console.log(` ${id} ${m2.state.padEnd(10)} ${duration3}${size}`);
95922
- }
95923
- console.log("");
95924
- }
95925
- function printHelp2() {
95926
- console.log(`
95927
- Usage: claudish team <subcommand> [options]
95928
-
95929
- Subcommands:
95930
- run Run multiple models on a task in parallel
95931
- judge Blind-judge existing model outputs
95932
- run-and-judge Run models then judge their outputs
95933
- status Show current session status
95934
-
95935
- Options (run / run-and-judge):
95936
- --path <dir> Session directory (default: .)
95937
- --models <a,b,...> Comma-separated model IDs to run
95938
- --input <text> Task prompt (or create input.md in --path beforehand)
95939
- --timeout <secs> Timeout per model in seconds (default: 300)
95940
- --grid Show all models in a magmux grid with live output + status bar
95941
-
95942
- Options (judge / run-and-judge):
95943
- --judges <a,b,...> Comma-separated judge model IDs (default: same as runners)
95944
-
95945
- Options (status):
95946
- --path <dir> Session directory (default: .)
95947
-
95948
- Examples:
95949
- claudish team run --path ./review --models minimax-m2.5,kimi-k2.5 --input "Review this code"
95950
- claudish team run --grid --models kimi-k2.5,gpt-5.4,gemini-3.1-pro --input "Solve this"
95951
- claudish team judge --path ./review
95952
- claudish team run-and-judge --path ./review --models gpt-5.4,gemini-3.1-pro-preview --input "Evaluate this design"
95953
- claudish team status --path ./review
95954
- `);
95955
- }
95956
- async function teamCommand(args) {
95957
- if (hasFlag(args, "--help") || hasFlag(args, "-h")) {
95958
- printHelp2();
95959
- process.exit(0);
95960
- }
95961
- const firstArg = args[0] ?? "";
95962
- const legacySubs = ["run", "judge", "run-and-judge", "status"];
95963
- const subcommand = legacySubs.includes(firstArg) ? firstArg : "run";
95964
- const rawSessionPath = getFlag(args, "--path") ?? ".";
95965
- let sessionPath;
95966
- try {
95967
- sessionPath = validateSessionPath(rawSessionPath);
95968
- } catch (err) {
95969
- console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);
95970
- process.exit(1);
95971
- }
95972
- const modelsRaw = getFlag(args, "--models");
95973
- const judgesRaw = getFlag(args, "--judges");
95974
- const mode = getFlag(args, "--mode") ?? "default";
95975
- const timeoutStr = getFlag(args, "--timeout");
95976
- const timeout = timeoutStr ? parseInt(timeoutStr, 10) : 300;
95977
- let input = getFlag(args, "--input");
95978
- if (!input) {
95979
- const flagsWithValues = ["--models", "--judges", "--mode", "--path", "--timeout", "--input"];
95980
- const positionals = args.filter((a, i) => {
95981
- if (legacySubs.includes(a) && i === 0)
95982
- return false;
95983
- if (a.startsWith("--"))
95984
- return false;
95985
- const prev = args[i - 1];
95986
- if (prev && flagsWithValues.includes(prev))
95987
- return false;
95988
- return true;
95989
- });
95990
- if (positionals.length > 0)
95991
- input = positionals.join(" ");
95992
- }
95993
- const models = modelsRaw ? modelsRaw.split(",").map((m2) => m2.trim()).filter(Boolean) : [];
95994
- const judges = judgesRaw ? judgesRaw.split(",").map((m2) => m2.trim()).filter(Boolean) : undefined;
95995
- const effectiveMode = hasFlag(args, "--interactive") ? "interactive" : hasFlag(args, "--grid") ? "default" : mode;
95996
- switch (subcommand) {
95997
- case "run": {
95998
- if (models.length === 0) {
95999
- console.error("Error: --models is required");
96000
- printHelp2();
96001
- process.exit(1);
96002
- }
96003
- if (effectiveMode === "json") {
96004
- setupSession(sessionPath, models, input);
96005
- const runStatus = await runModels(sessionPath, {
96006
- timeout,
96007
- onStatusChange: (id, s) => {
96008
- process.stderr.write(`[team] ${id}: ${s.state}
96009
- `);
96010
- }
96011
- });
96012
- printStatus(runStatus);
96013
- } else {
96014
- const { runWithGrid: runWithGrid2 } = await Promise.resolve().then(() => (init_team_grid(), exports_team_grid));
96015
- const interactive = effectiveMode === "interactive";
96016
- const gridStatus = await runWithGrid2(sessionPath, models, input ?? "", { timeout, interactive });
96017
- printStatus(gridStatus);
96018
- }
96019
- break;
96020
- }
96021
- case "judge": {
96022
- await judgeResponses(sessionPath, { judges });
96023
- console.log(readFileSync22(join28(sessionPath, "verdict.md"), "utf-8"));
96024
- break;
96025
- }
96026
- case "run-and-judge": {
96027
- if (models.length === 0) {
96028
- console.error("Error: --models is required");
96029
- process.exit(1);
96030
- }
96031
- setupSession(sessionPath, models, input);
96032
- const status = await runModels(sessionPath, {
96033
- timeout,
96034
- onStatusChange: (id, s) => {
96035
- process.stderr.write(`[team] ${id}: ${s.state}
96036
- `);
96037
- }
96038
- });
96039
- printStatus(status);
96040
- await judgeResponses(sessionPath, { judges });
96041
- console.log(readFileSync22(join28(sessionPath, "verdict.md"), "utf-8"));
96042
- break;
96043
- }
96044
- case "status": {
96045
- const statusResult = getStatus(sessionPath);
96046
- printStatus(statusResult);
96047
- break;
96048
- }
96049
- }
96050
- }
96051
- var init_team_cli = __esm(() => {
96052
- init_team_orchestrator();
96053
- });
96054
-
96055
95669
  // src/claude-runner.ts
96056
95670
  var exports_claude_runner = {};
96057
95671
  __export(exports_claude_runner, {
96058
95672
  runClaudeWithProxy: () => runClaudeWithProxy,
96059
95673
  checkClaudeInstalled: () => checkClaudeInstalled
96060
95674
  });
96061
- import { spawn as spawn4 } from "child_process";
96062
- import { writeFileSync as writeFileSync16, unlinkSync as unlinkSync9, mkdirSync as mkdirSync15, existsSync as existsSync28, readFileSync as readFileSync23 } from "fs";
95675
+ import { spawn as spawn3 } from "child_process";
95676
+ import { writeFileSync as writeFileSync15, unlinkSync as unlinkSync8, mkdirSync as mkdirSync14, existsSync as existsSync26, readFileSync as readFileSync21 } from "fs";
96063
95677
  import { tmpdir as tmpdir2, homedir as homedir25 } from "os";
96064
- import { join as join29 } from "path";
95678
+ import { join as join27 } from "path";
96065
95679
  function hasNativeAnthropicMapping(config3) {
96066
95680
  const models = [
96067
95681
  config3.model,
@@ -96077,9 +95691,9 @@ function isWindows2() {
96077
95691
  }
96078
95692
  function createStatusLineScript(tokenFilePath) {
96079
95693
  const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
96080
- const claudishDir = join29(homeDir, ".claudish");
95694
+ const claudishDir = join27(homeDir, ".claudish");
96081
95695
  const timestamp = Date.now();
96082
- const scriptPath = join29(claudishDir, `status-${timestamp}.js`);
95696
+ const scriptPath = join27(claudishDir, `status-${timestamp}.js`);
96083
95697
  const escapedTokenPath = tokenFilePath.replace(/\\/g, "\\\\");
96084
95698
  const script = `
96085
95699
  const fs = require('fs');
@@ -96168,18 +95782,18 @@ process.stdin.on('end', () => {
96168
95782
  }
96169
95783
  });
96170
95784
  `;
96171
- writeFileSync16(scriptPath, script, "utf-8");
95785
+ writeFileSync15(scriptPath, script, "utf-8");
96172
95786
  return scriptPath;
96173
95787
  }
96174
95788
  function createTempSettingsFile(modelDisplay, port) {
96175
95789
  const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
96176
- const claudishDir = join29(homeDir, ".claudish");
95790
+ const claudishDir = join27(homeDir, ".claudish");
96177
95791
  try {
96178
- mkdirSync15(claudishDir, { recursive: true });
95792
+ mkdirSync14(claudishDir, { recursive: true });
96179
95793
  } catch {}
96180
95794
  const timestamp = Date.now();
96181
- const tempPath = join29(claudishDir, `settings-${timestamp}.json`);
96182
- const tokenFilePath = join29(claudishDir, `tokens-${port}.json`);
95795
+ const tempPath = join27(claudishDir, `settings-${timestamp}.json`);
95796
+ const tokenFilePath = join27(claudishDir, `tokens-${port}.json`);
96183
95797
  let statusCommand;
96184
95798
  if (isWindows2()) {
96185
95799
  const scriptPath = createStatusLineScript(tokenFilePath);
@@ -96201,7 +95815,7 @@ function createTempSettingsFile(modelDisplay, port) {
96201
95815
  padding: 0
96202
95816
  };
96203
95817
  const settings = { statusLine };
96204
- writeFileSync16(tempPath, JSON.stringify(settings, null, 2), "utf-8");
95818
+ writeFileSync15(tempPath, JSON.stringify(settings, null, 2), "utf-8");
96205
95819
  return { path: tempPath, statusLine };
96206
95820
  }
96207
95821
  function mergeUserSettingsIfPresent(config3, tempSettingsPath, statusLine) {
@@ -96215,11 +95829,11 @@ function mergeUserSettingsIfPresent(config3, tempSettingsPath, statusLine) {
96215
95829
  if (userSettingsValue.trimStart().startsWith("{")) {
96216
95830
  userSettings = JSON.parse(userSettingsValue);
96217
95831
  } else {
96218
- const rawUserSettings = readFileSync23(userSettingsValue, "utf-8");
95832
+ const rawUserSettings = readFileSync21(userSettingsValue, "utf-8");
96219
95833
  userSettings = JSON.parse(rawUserSettings);
96220
95834
  }
96221
95835
  userSettings.statusLine = statusLine;
96222
- writeFileSync16(tempSettingsPath, JSON.stringify(userSettings, null, 2), "utf-8");
95836
+ writeFileSync15(tempSettingsPath, JSON.stringify(userSettings, null, 2), "utf-8");
96223
95837
  } catch {
96224
95838
  if (!config3.quiet) {
96225
95839
  console.warn(`[claudish] Warning: could not merge user settings: ${userSettingsValue}`);
@@ -96308,13 +95922,13 @@ async function runClaudeWithProxy(config3, proxyUrl, onCleanup) {
96308
95922
  console.error(`
96309
95923
  Or set CLAUDE_PATH to your custom installation:`);
96310
95924
  const home = homedir25();
96311
- const localPath = isWindows2() ? join29(home, ".claude", "local", "claude.exe") : join29(home, ".claude", "local", "claude");
95925
+ const localPath = isWindows2() ? join27(home, ".claude", "local", "claude.exe") : join27(home, ".claude", "local", "claude");
96312
95926
  console.error(` export CLAUDE_PATH=${localPath}`);
96313
95927
  process.exit(1);
96314
95928
  }
96315
95929
  const needsShell = isWindows2() && claudeBinary.endsWith(".cmd");
96316
95930
  const spawnCommand = needsShell ? `"${claudeBinary}"` : claudeBinary;
96317
- const proc = spawn4(spawnCommand, claudeArgs, {
95931
+ const proc = spawn3(spawnCommand, claudeArgs, {
96318
95932
  env: env2,
96319
95933
  stdio: "inherit",
96320
95934
  shell: needsShell
@@ -96326,7 +95940,7 @@ Or set CLAUDE_PATH to your custom installation:`);
96326
95940
  });
96327
95941
  });
96328
95942
  try {
96329
- unlinkSync9(tempSettingsPath);
95943
+ unlinkSync8(tempSettingsPath);
96330
95944
  } catch {}
96331
95945
  return exitCode;
96332
95946
  }
@@ -96345,7 +95959,7 @@ function setupSignalHandlers(proc, tempSettingsPath, quiet, onCleanup) {
96345
95959
  } catch {}
96346
95960
  }
96347
95961
  try {
96348
- unlinkSync9(tempSettingsPath);
95962
+ unlinkSync8(tempSettingsPath);
96349
95963
  } catch {}
96350
95964
  process.exit(0);
96351
95965
  });
@@ -96354,23 +95968,23 @@ function setupSignalHandlers(proc, tempSettingsPath, quiet, onCleanup) {
96354
95968
  async function findClaudeBinary() {
96355
95969
  const isWindows3 = process.platform === "win32";
96356
95970
  if (process.env.CLAUDE_PATH) {
96357
- if (existsSync28(process.env.CLAUDE_PATH)) {
95971
+ if (existsSync26(process.env.CLAUDE_PATH)) {
96358
95972
  return process.env.CLAUDE_PATH;
96359
95973
  }
96360
95974
  }
96361
95975
  const home = homedir25();
96362
- const localPath = isWindows3 ? join29(home, ".claude", "local", "claude.exe") : join29(home, ".claude", "local", "claude");
96363
- if (existsSync28(localPath)) {
95976
+ const localPath = isWindows3 ? join27(home, ".claude", "local", "claude.exe") : join27(home, ".claude", "local", "claude");
95977
+ if (existsSync26(localPath)) {
96364
95978
  return localPath;
96365
95979
  }
96366
95980
  if (isWindows3) {
96367
95981
  const windowsPaths = [
96368
- join29(home, "AppData", "Roaming", "npm", "claude.cmd"),
96369
- join29(home, ".npm-global", "claude.cmd"),
96370
- join29(home, "node_modules", ".bin", "claude.cmd")
95982
+ join27(home, "AppData", "Roaming", "npm", "claude.cmd"),
95983
+ join27(home, ".npm-global", "claude.cmd"),
95984
+ join27(home, "node_modules", ".bin", "claude.cmd")
96371
95985
  ];
96372
95986
  for (const path2 of windowsPaths) {
96373
- if (existsSync28(path2)) {
95987
+ if (existsSync26(path2)) {
96374
95988
  return path2;
96375
95989
  }
96376
95990
  }
@@ -96378,21 +95992,21 @@ async function findClaudeBinary() {
96378
95992
  const commonPaths = [
96379
95993
  "/usr/local/bin/claude",
96380
95994
  "/opt/homebrew/bin/claude",
96381
- join29(home, ".npm-global/bin/claude"),
96382
- join29(home, ".local/bin/claude"),
96383
- join29(home, "node_modules/.bin/claude"),
95995
+ join27(home, ".npm-global/bin/claude"),
95996
+ join27(home, ".local/bin/claude"),
95997
+ join27(home, "node_modules/.bin/claude"),
96384
95998
  "/data/data/com.termux/files/usr/bin/claude",
96385
- join29(home, "../usr/bin/claude")
95999
+ join27(home, "../usr/bin/claude")
96386
96000
  ];
96387
96001
  for (const path2 of commonPaths) {
96388
- if (existsSync28(path2)) {
96002
+ if (existsSync26(path2)) {
96389
96003
  return path2;
96390
96004
  }
96391
96005
  }
96392
96006
  }
96393
96007
  try {
96394
96008
  const shellCommand = isWindows3 ? "where claude" : "command -v claude";
96395
- const proc = spawn4(shellCommand, [], {
96009
+ const proc = spawn3(shellCommand, [], {
96396
96010
  stdio: "pipe",
96397
96011
  shell: true
96398
96012
  });
@@ -96434,18 +96048,18 @@ __export(exports_diag_output, {
96434
96048
  NullDiagOutput: () => NullDiagOutput,
96435
96049
  LogFileDiagOutput: () => LogFileDiagOutput
96436
96050
  });
96437
- import { createWriteStream as createWriteStream3, mkdirSync as mkdirSync16, writeFileSync as writeFileSync17, unlinkSync as unlinkSync10 } from "fs";
96051
+ import { createWriteStream as createWriteStream3, mkdirSync as mkdirSync15, writeFileSync as writeFileSync16, unlinkSync as unlinkSync9 } from "fs";
96438
96052
  import { homedir as homedir26 } from "os";
96439
- import { join as join30 } from "path";
96053
+ import { join as join28 } from "path";
96440
96054
  function getClaudishDir() {
96441
- const dir = join30(homedir26(), ".claudish");
96055
+ const dir = join28(homedir26(), ".claudish");
96442
96056
  try {
96443
- mkdirSync16(dir, { recursive: true });
96057
+ mkdirSync15(dir, { recursive: true });
96444
96058
  } catch {}
96445
96059
  return dir;
96446
96060
  }
96447
96061
  function getDiagLogPath() {
96448
- return join30(getClaudishDir(), `diag-${process.pid}.log`);
96062
+ return join28(getClaudishDir(), `diag-${process.pid}.log`);
96449
96063
  }
96450
96064
 
96451
96065
  class LogFileDiagOutput {
@@ -96454,7 +96068,7 @@ class LogFileDiagOutput {
96454
96068
  constructor() {
96455
96069
  this.logPath = getDiagLogPath();
96456
96070
  try {
96457
- writeFileSync17(this.logPath, `--- claudish diag session ${new Date().toISOString()} ---
96071
+ writeFileSync16(this.logPath, `--- claudish diag session ${new Date().toISOString()} ---
96458
96072
  `);
96459
96073
  } catch {}
96460
96074
  this.stream = createWriteStream3(this.logPath, { flags: "a" });
@@ -96473,7 +96087,7 @@ class LogFileDiagOutput {
96473
96087
  this.stream.end();
96474
96088
  } catch {}
96475
96089
  try {
96476
- unlinkSync10(this.logPath);
96090
+ unlinkSync9(this.logPath);
96477
96091
  } catch {}
96478
96092
  }
96479
96093
  getLogPath() {
@@ -96497,18 +96111,274 @@ function createDiagOutput(options) {
96497
96111
  }
96498
96112
  var init_diag_output = () => {};
96499
96113
 
96114
+ // src/team-grid.ts
96115
+ var exports_team_grid = {};
96116
+ __export(exports_team_grid, {
96117
+ runWithGrid: () => runWithGrid
96118
+ });
96119
+ import { spawn as spawn4 } from "child_process";
96120
+ import {
96121
+ appendFileSync,
96122
+ existsSync as existsSync28,
96123
+ mkdirSync as mkdirSync16,
96124
+ readFileSync as readFileSync22,
96125
+ unlinkSync as unlinkSync10,
96126
+ writeFileSync as writeFileSync17
96127
+ } from "fs";
96128
+ import { dirname as dirname6, join as join29 } from "path";
96129
+ import { fileURLToPath as fileURLToPath6 } from "url";
96130
+ import { execSync as execSync3 } from "child_process";
96131
+ function formatElapsed(ms) {
96132
+ const s = Math.floor(ms / 1000);
96133
+ if (s < 60)
96134
+ return `${s}s`;
96135
+ const m2 = Math.floor(s / 60);
96136
+ const rem = s % 60;
96137
+ return `${m2}m ${rem}s`;
96138
+ }
96139
+ function findMagmuxBinary() {
96140
+ const thisFile = fileURLToPath6(import.meta.url);
96141
+ const thisDir = dirname6(thisFile);
96142
+ const pkgRoot = join29(thisDir, "..");
96143
+ const platform3 = process.platform;
96144
+ const arch = process.arch;
96145
+ const builtMagmux = join29(pkgRoot, "native", "magmux", "magmux");
96146
+ if (existsSync28(builtMagmux))
96147
+ return builtMagmux;
96148
+ const bundledMagmux = join29(pkgRoot, "native", "magmux", `magmux-${platform3}-${arch}`);
96149
+ if (existsSync28(bundledMagmux))
96150
+ return bundledMagmux;
96151
+ try {
96152
+ const pkgName = `@claudish/magmux-${platform3}-${arch}`;
96153
+ let searchDir = pkgRoot;
96154
+ for (let i = 0;i < 5; i++) {
96155
+ const candidate = join29(searchDir, "node_modules", pkgName, "bin", "magmux");
96156
+ if (existsSync28(candidate))
96157
+ return candidate;
96158
+ const parent = dirname6(searchDir);
96159
+ if (parent === searchDir)
96160
+ break;
96161
+ searchDir = parent;
96162
+ }
96163
+ } catch {}
96164
+ try {
96165
+ const result = execSync3("which magmux", { encoding: "utf-8" }).trim();
96166
+ if (result)
96167
+ return result;
96168
+ } catch {}
96169
+ throw new Error(`magmux not found. Install it:
96170
+ brew install MadAppGang/tap/magmux`);
96171
+ }
96172
+ function renderGridStatusBar(counts) {
96173
+ const elapsed = formatElapsed(counts.elapsedMs);
96174
+ const { done, running, failed, total, allDone } = counts;
96175
+ if (allDone) {
96176
+ if (failed > 0) {
96177
+ return [
96178
+ "C: claudish team",
96179
+ `G: ${done} done`,
96180
+ `R: ${failed} failed`,
96181
+ `D: ${elapsed}`,
96182
+ "R: \u2717 issues",
96183
+ "D: ctrl-g q to quit"
96184
+ ].join("\t");
96185
+ }
96186
+ return [
96187
+ "C: claudish team",
96188
+ `G: ${total} done`,
96189
+ `D: ${elapsed}`,
96190
+ "G: \u2713 complete",
96191
+ "D: ctrl-g q to quit"
96192
+ ].join("\t");
96193
+ }
96194
+ return [
96195
+ "C: claudish team",
96196
+ `G: ${done} done`,
96197
+ `C: ${running} running`,
96198
+ `R: ${failed} failed`,
96199
+ `D: ${elapsed}`
96200
+ ].join("\t");
96201
+ }
96202
+ function pollStatus(state) {
96203
+ const { statusCache, statusPath, sessionPath, anonIds, startTime, timeoutMs, statusbarPath } = state;
96204
+ const elapsedMs = Date.now() - startTime;
96205
+ let changed = false;
96206
+ let done = 0;
96207
+ let running = 0;
96208
+ let failed = 0;
96209
+ for (const anonId of anonIds) {
96210
+ const current = statusCache.models[anonId];
96211
+ if (current.state === "COMPLETED" || current.state === "FAILED" || current.state === "TIMEOUT") {
96212
+ if (current.state === "COMPLETED")
96213
+ done++;
96214
+ else
96215
+ failed++;
96216
+ continue;
96217
+ }
96218
+ const exitCodePath = join29(sessionPath, "work", anonId, ".exit-code");
96219
+ if (existsSync28(exitCodePath)) {
96220
+ const codeStr = readFileSync22(exitCodePath, "utf-8").trim();
96221
+ const code = parseInt(codeStr, 10);
96222
+ const isSuccess = code === 0;
96223
+ const newState = {
96224
+ ...current,
96225
+ state: isSuccess ? "COMPLETED" : "FAILED",
96226
+ exitCode: code,
96227
+ startedAt: current.startedAt ?? new Date().toISOString(),
96228
+ completedAt: new Date().toISOString(),
96229
+ outputSize: 0
96230
+ };
96231
+ statusCache.models[anonId] = newState;
96232
+ changed = true;
96233
+ if (isSuccess)
96234
+ done++;
96235
+ else
96236
+ failed++;
96237
+ } else {
96238
+ if (!state.interactive && elapsedMs > timeoutMs) {
96239
+ const newState = {
96240
+ ...current,
96241
+ state: "TIMEOUT",
96242
+ startedAt: current.startedAt ?? new Date().toISOString(),
96243
+ completedAt: new Date().toISOString(),
96244
+ outputSize: 0
96245
+ };
96246
+ statusCache.models[anonId] = newState;
96247
+ changed = true;
96248
+ failed++;
96249
+ } else {
96250
+ if (current.state === "PENDING" && elapsedMs > 1000) {
96251
+ statusCache.models[anonId] = {
96252
+ ...current,
96253
+ state: "RUNNING",
96254
+ startedAt: current.startedAt ?? new Date().toISOString()
96255
+ };
96256
+ changed = true;
96257
+ }
96258
+ running++;
96259
+ }
96260
+ }
96261
+ }
96262
+ if (changed) {
96263
+ writeFileSync17(statusPath, JSON.stringify(statusCache, null, 2), "utf-8");
96264
+ }
96265
+ const total = anonIds.length;
96266
+ const allDone = done + failed >= total;
96267
+ if (allDone && !state.completedAtMs) {
96268
+ state.completedAtMs = elapsedMs;
96269
+ }
96270
+ const counts = {
96271
+ done,
96272
+ running,
96273
+ failed,
96274
+ total,
96275
+ elapsedMs: state.completedAtMs ?? elapsedMs,
96276
+ allDone
96277
+ };
96278
+ appendFileSync(statusbarPath, renderGridStatusBar(counts) + `
96279
+ `);
96280
+ return allDone;
96281
+ }
96282
+ async function runWithGrid(sessionPath, models, input, opts) {
96283
+ const timeoutMs = (opts?.timeout ?? 300) * 1000;
96284
+ const interactive = opts?.interactive ?? false;
96285
+ const manifest = setupSession(sessionPath, models, input);
96286
+ mkdirSync16(join29(sessionPath, "errors"), { recursive: true });
96287
+ for (const anonId of Object.keys(manifest.models)) {
96288
+ const stale = join29(sessionPath, "work", anonId, ".exit-code");
96289
+ try {
96290
+ unlinkSync10(stale);
96291
+ } catch {}
96292
+ }
96293
+ const gridfilePath = join29(sessionPath, "gridfile.txt");
96294
+ const prompt = readFileSync22(join29(sessionPath, "input.md"), "utf-8").replace(/'/g, "'\\''").replace(/\n/g, " ");
96295
+ const gridLines = Object.entries(manifest.models).map(([anonId]) => {
96296
+ const errorLog = join29(sessionPath, "errors", `${anonId}.log`);
96297
+ const exitCodeFile = join29(sessionPath, "work", anonId, ".exit-code");
96298
+ const model = manifest.models[anonId].model;
96299
+ const paneIndex = Object.keys(manifest.models).indexOf(anonId);
96300
+ if (interactive) {
96301
+ return `claudish --model ${model} --dangerously-skip-permissions '${prompt}'`;
96302
+ }
96303
+ return [
96304
+ `claudish --model ${model} -y -v '${prompt}' 2>${errorLog};`,
96305
+ `_ec=$?; echo $_ec > ${exitCodeFile};`,
96306
+ `if [ -n "$MAGMUX_SOCK" ]; then`,
96307
+ ` if [ $_ec -eq 0 ]; then`,
96308
+ ` echo '{"cmd":"tint","pane":${paneIndex},"color":"green"}' | nc -U "$MAGMUX_SOCK" -w 1 2>/dev/null;`,
96309
+ ` echo '{"cmd":"overlay","pane":${paneIndex},"text":"DONE","color":"green"}' | nc -U "$MAGMUX_SOCK" -w 1 2>/dev/null;`,
96310
+ ` else`,
96311
+ ` echo '{"cmd":"tint","pane":${paneIndex},"color":"red"}' | nc -U "$MAGMUX_SOCK" -w 1 2>/dev/null;`,
96312
+ ` echo '{"cmd":"overlay","pane":${paneIndex},"text":"FAIL","color":"red"}' | nc -U "$MAGMUX_SOCK" -w 1 2>/dev/null;`,
96313
+ ` fi;`,
96314
+ `fi;`,
96315
+ `exec sleep 86400`
96316
+ ].join(" ");
96317
+ });
96318
+ writeFileSync17(gridfilePath, gridLines.join(`
96319
+ `) + `
96320
+ `, "utf-8");
96321
+ const magmuxPath = findMagmuxBinary();
96322
+ const statusbarPath = join29(sessionPath, "statusbar.txt");
96323
+ const statusPath = join29(sessionPath, "status.json");
96324
+ const statusCache = JSON.parse(readFileSync22(statusPath, "utf-8"));
96325
+ const anonIds = Object.keys(manifest.models);
96326
+ const startTime = Date.now();
96327
+ appendFileSync(statusbarPath, renderGridStatusBar({
96328
+ done: 0,
96329
+ running: 0,
96330
+ failed: 0,
96331
+ total: anonIds.length,
96332
+ elapsedMs: 0,
96333
+ allDone: false
96334
+ }) + `
96335
+ `);
96336
+ const pollState = {
96337
+ statusCache,
96338
+ statusPath,
96339
+ sessionPath,
96340
+ anonIds,
96341
+ startTime,
96342
+ timeoutMs,
96343
+ statusbarPath,
96344
+ completedAtMs: null,
96345
+ interactive
96346
+ };
96347
+ const pollInterval = setInterval(() => {
96348
+ pollStatus(pollState);
96349
+ }, 500);
96350
+ const spawnArgs = ["-g", gridfilePath, "-S", statusbarPath];
96351
+ if (!interactive) {
96352
+ spawnArgs.push("-w");
96353
+ }
96354
+ const proc = spawn4(magmuxPath, spawnArgs, {
96355
+ stdio: "inherit",
96356
+ env: { ...process.env }
96357
+ });
96358
+ await new Promise((resolve4) => {
96359
+ proc.on("exit", () => resolve4());
96360
+ proc.on("error", () => resolve4());
96361
+ });
96362
+ clearInterval(pollInterval);
96363
+ pollStatus(pollState);
96364
+ return JSON.parse(readFileSync22(statusPath, "utf-8"));
96365
+ }
96366
+ var init_team_grid = __esm(() => {
96367
+ init_team_orchestrator();
96368
+ });
96369
+
96500
96370
  // src/index.ts
96501
96371
  var import_dotenv3 = __toESM(require_main(), 1);
96502
- import { existsSync as existsSync29, readFileSync as readFileSync24 } from "fs";
96372
+ import { existsSync as existsSync29, readFileSync as readFileSync23 } from "fs";
96503
96373
  import { homedir as homedir27 } from "os";
96504
- import { join as join31 } from "path";
96374
+ import { join as join30 } from "path";
96505
96375
  import_dotenv3.config({ quiet: true });
96506
96376
  function loadStoredApiKeys() {
96507
96377
  try {
96508
- const configPath = join31(homedir27(), ".claudish", "config.json");
96378
+ const configPath = join30(homedir27(), ".claudish", "config.json");
96509
96379
  if (!existsSync29(configPath))
96510
96380
  return;
96511
- const raw2 = readFileSync24(configPath, "utf-8");
96381
+ const raw2 = readFileSync23(configPath, "utf-8");
96512
96382
  const cfg = JSON.parse(raw2);
96513
96383
  if (cfg.apiKeys) {
96514
96384
  for (const [envVar, value] of Object.entries(cfg.apiKeys)) {
@@ -96543,7 +96413,6 @@ var firstPositional = args.find((a) => !a.startsWith("-"));
96543
96413
  var isTelemetryCommand = firstPositional === "telemetry";
96544
96414
  var isStatsCommand = firstPositional === "stats";
96545
96415
  var isConfigCommand = firstPositional === "config";
96546
- var isTeamCommand = firstPositional === "team";
96547
96416
  var isLoginCommand = firstPositional === "login";
96548
96417
  var isLogoutCommand = firstPositional === "logout";
96549
96418
  var isQuotaCommand = firstPositional === "quota" || firstPositional === "usage";
@@ -96592,8 +96461,6 @@ if (isMcpMode) {
96592
96461
  });
96593
96462
  } else if (isConfigCommand) {
96594
96463
  init_tui().then(() => exports_tui).then((m2) => m2.startConfigTui().catch(handlePromptExit));
96595
- } else if (isTeamCommand) {
96596
- Promise.resolve().then(() => (init_team_cli(), exports_team_cli)).then((m2) => m2.teamCommand(args.slice(1)));
96597
96464
  } else {
96598
96465
  runCli();
96599
96466
  }
@@ -96622,6 +96489,32 @@ async function runCli() {
96622
96489
  }
96623
96490
  try {
96624
96491
  const cliConfig = await parseArgs2(process.argv.slice(2));
96492
+ if (cliConfig.team && cliConfig.team.length > 0) {
96493
+ const { runWithGrid: runWithGrid2 } = await Promise.resolve().then(() => (init_team_grid(), exports_team_grid));
96494
+ let prompt = cliConfig.claudeArgs.join(" ");
96495
+ if (cliConfig.inputFile) {
96496
+ prompt = readFileSync23(cliConfig.inputFile, "utf-8");
96497
+ }
96498
+ if (!prompt.trim()) {
96499
+ console.error("Error: --team requires a prompt (positional args or -f <file>)");
96500
+ process.exit(1);
96501
+ }
96502
+ const interactive = cliConfig.teamMode !== "json";
96503
+ const sessionPath = join30(process.cwd(), `.claudish-team-${Date.now()}`);
96504
+ const status = await runWithGrid2(sessionPath, cliConfig.team, prompt, {
96505
+ timeout: 300,
96506
+ interactive
96507
+ });
96508
+ const modelIds = Object.keys(status.models).sort();
96509
+ console.log(`
96510
+ Team Status`);
96511
+ for (const id of modelIds) {
96512
+ const m2 = status.models[id];
96513
+ const duration3 = m2.startedAt && m2.completedAt ? `${Math.round((new Date(m2.completedAt).getTime() - new Date(m2.startedAt).getTime()) / 1000)}s` : "pending";
96514
+ console.log(` ${id} ${m2.state.padEnd(10)} ${duration3}`);
96515
+ }
96516
+ process.exit(0);
96517
+ }
96625
96518
  const rawArgs = process.argv.slice(2);
96626
96519
  const explicitNoAutoApprove = rawArgs.includes("--no-auto-approve");
96627
96520
  if (cliConfig.autoApprove && !explicitNoAutoApprove && !cliConfig.stdin) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "6.8.0",
3
+ "version": "6.9.0",
4
4
  "description": "Run Claude Code with any model - OpenRouter, Ollama, LM Studio & local models",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -39,7 +39,6 @@
39
39
  },
40
40
  "files": [
41
41
  "dist/",
42
- "native/magmux/magmux-*",
43
42
  "AI_AGENT_GUIDE.md",
44
43
  "recommended-models.json",
45
44
  "skills/"
@@ -59,6 +58,12 @@
59
58
  "model-context-protocol",
60
59
  "ai"
61
60
  ],
61
+ "optionalDependencies": {
62
+ "@claudish/magmux-darwin-arm64": "6.9.0",
63
+ "@claudish/magmux-darwin-x64": "6.9.0",
64
+ "@claudish/magmux-linux-arm64": "6.9.0",
65
+ "@claudish/magmux-linux-x64": "6.9.0"
66
+ },
62
67
  "author": "Jack Rudenko <i@madappgang.com>",
63
68
  "license": "MIT",
64
69
  "repository": {
Binary file
Binary file
Binary file
Binary file