@ogpoyraz/wtx 0.8.5 → 0.8.6

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 (2) hide show
  1. package/dist/cli.mjs +122 -13
  2. package/package.json +1 -1
package/dist/cli.mjs CHANGED
@@ -32912,21 +32912,130 @@ function registerSkillCommand(program2) {
32912
32912
  }
32913
32913
 
32914
32914
  // src/commands/terminal.ts
32915
+ import { spawnSync as spawnSync3 } from "node:child_process";
32916
+ import fs33 from "node:fs";
32917
+ import path37 from "node:path";
32918
+ import { fileURLToPath as fileURLToPath4 } from "node:url";
32919
+ function findEntry() {
32920
+ const candidates = [];
32921
+ if (process.argv[1])
32922
+ candidates.push(process.argv[1]);
32923
+ try {
32924
+ const thisPath = fileURLToPath4(import.meta.url);
32925
+ candidates.push(thisPath);
32926
+ candidates.push(path37.resolve(path37.dirname(thisPath), "../../dist/cli.mjs"));
32927
+ candidates.push(path37.resolve(path37.dirname(thisPath), "../cli.mjs"));
32928
+ } catch {}
32929
+ for (const p of candidates) {
32930
+ try {
32931
+ if (p.endsWith(".mjs") || p.endsWith(".js")) {
32932
+ if (fs33.existsSync(p) && fs33.statSync(p).isFile())
32933
+ return p;
32934
+ } else if (fs33.existsSync(p)) {
32935
+ const stat = fs33.statSync(p);
32936
+ if (stat.isFile()) {
32937
+ const head = fs33.readFileSync(p, "utf8").slice(0, 1024);
32938
+ if (head.includes("cli.mjs") || head.includes("#!/usr/bin/env node")) {
32939
+ if (p.endsWith("wtx") || p.endsWith("cli.mjs")) {
32940
+ const dir = path37.dirname(fs33.realpathSync(p));
32941
+ const cli = path37.join(dir, "cli.mjs");
32942
+ if (fs33.existsSync(cli))
32943
+ return cli;
32944
+ const cli2 = path37.resolve(dir, "../dist/cli.mjs");
32945
+ if (fs33.existsSync(cli2))
32946
+ return cli2;
32947
+ if (head.includes("import") || head.includes("commander"))
32948
+ return p;
32949
+ }
32950
+ }
32951
+ }
32952
+ }
32953
+ } catch {}
32954
+ }
32955
+ try {
32956
+ const thisPath = fileURLToPath4(import.meta.url);
32957
+ const pkgRoot = path37.resolve(path37.dirname(thisPath), "../..");
32958
+ const cli = path37.join(pkgRoot, "dist", "cli.mjs");
32959
+ if (fs33.existsSync(cli))
32960
+ return cli;
32961
+ } catch {}
32962
+ return null;
32963
+ }
32964
+ function tryRelaunchViaBun(forwardedArgs) {
32965
+ if (process.env.WTX_BUN_RERUN === "1")
32966
+ return null;
32967
+ const env2 = { ...process.env, WTX_BUN_RERUN: "1" };
32968
+ const entry = findEntry();
32969
+ if (entry) {
32970
+ const result = spawnSync3("bun", [entry, ...forwardedArgs], {
32971
+ stdio: "inherit",
32972
+ env: env2
32973
+ });
32974
+ if (!result.error) {
32975
+ process.exit(result.status ?? 0);
32976
+ }
32977
+ if (result.error.code !== "ENOENT") {
32978
+ process.stderr.write(`✗ Failed to relaunch via Bun: ${result.error.message}
32979
+ `);
32980
+ process.exit(1);
32981
+ }
32982
+ }
32983
+ const attempts = [
32984
+ { cmd: "bunx", args: ["--bun", "wtx", ...forwardedArgs] },
32985
+ { cmd: "bun", args: ["x", "--bun", "wtx", ...forwardedArgs] }
32986
+ ];
32987
+ for (const { cmd, args } of attempts) {
32988
+ const result = spawnSync3(cmd, args, { stdio: "inherit", env: env2 });
32989
+ if (!result.error) {
32990
+ process.exit(result.status ?? 0);
32991
+ }
32992
+ if (result.error.code !== "ENOENT") {
32993
+ process.stderr.write(`✗ Failed to relaunch via ${cmd}: ${result.error.message}
32994
+ `);
32995
+ process.exit(1);
32996
+ }
32997
+ }
32998
+ return null;
32999
+ }
32915
33000
  function registerTerminalCommand(program2) {
32916
33001
  program2.command("terminal").description("Interactive worktree dashboard (requires Bun)").action(async () => {
32917
33002
  const opts = program2.optsWithGlobals();
32918
33003
  if (typeof Bun === "undefined") {
32919
- process.stderr.write(`✗ wtx terminal dashboard requires the Bun runtime
33004
+ const forwarded = process.argv.slice(2);
33005
+ const relaunched = tryRelaunchViaBun(forwarded);
33006
+ if (relaunched === null) {
33007
+ const probe2 = spawnSync3("bun", ["--version"], { stdio: "ignore" });
33008
+ const hasBun = !probe2.error && probe2.status === 0;
33009
+ if (!hasBun) {
33010
+ process.stderr.write(`✗ wtx terminal dashboard requires the Bun runtime
32920
33011
  `);
32921
- process.stderr.write(` The TUI relies on Bun's FFI and React renderer which cannot run in Node/compiled binary.
33012
+ process.stderr.write(` The TUI relies on Bun's FFI and React renderer which cannot run in Node/compiled binary.
32922
33013
  `);
32923
- process.stderr.write(` To use the dashboard, run it via Bun:
33014
+ process.stderr.write(` Bun was not found on your PATH. Install it from https://bun.sh, then run:
32924
33015
  `);
32925
- process.stderr.write(` bunx --bun wtx terminal
33016
+ process.stderr.write(` wtx terminal
32926
33017
 
32927
33018
  `);
32928
- process.stderr.write(" Note: `wtx ls` provides a fast list view and works everywhere.\n");
32929
- process.exit(1);
33019
+ process.stderr.write(" Note: `wtx ls` provides a fast list view and works everywhere.\n");
33020
+ process.exit(1);
33021
+ }
33022
+ process.stderr.write(`✗ wtx terminal dashboard requires the Bun runtime
33023
+ `);
33024
+ process.stderr.write(` The TUI relies on Bun's FFI and React renderer which cannot run in Node/compiled binary.
33025
+ `);
33026
+ process.stderr.write(` Automatic relaunch via Bun failed. Try running directly:
33027
+ `);
33028
+ process.stderr.write(` bunx --bun wtx terminal
33029
+ `);
33030
+ const entry = findEntry();
33031
+ if (entry) {
33032
+ process.stderr.write(` bun ${entry} terminal
33033
+ `);
33034
+ }
33035
+ process.stderr.write("\n Note: `wtx ls` provides a fast list view and works everywhere.\n");
33036
+ process.exit(1);
33037
+ }
33038
+ return;
32930
33039
  }
32931
33040
  if (!process.stdin.isTTY || !process.stdout.isTTY) {
32932
33041
  process.stderr.write(`✗ wtx terminal requires an interactive terminal
@@ -32947,7 +33056,7 @@ init_deps();
32947
33056
  import readline3 from "readline";
32948
33057
  init_path_safety();
32949
33058
  init_stack();
32950
- import fs33 from "fs";
33059
+ import fs34 from "fs";
32951
33060
  async function runMcpServer(opts = {}) {
32952
33061
  const input = opts.input ?? process.stdin;
32953
33062
  const output = opts.output ?? process.stdout;
@@ -33130,7 +33239,7 @@ async function handleToolCall(name, args, config2, _opts) {
33130
33239
  for (const wt of wts) {
33131
33240
  if (!wt.path.startsWith(repo.wtRoot))
33132
33241
  continue;
33133
- const dirtyCount = fs33.existsSync(wt.path) ? (await getDirtyFiles(wt.path)).length : 0;
33242
+ const dirtyCount = fs34.existsSync(wt.path) ? (await getDirtyFiles(wt.path)).length : 0;
33134
33243
  items.push({
33135
33244
  repo: repo.name,
33136
33245
  branch: wt.branch || null,
@@ -33158,7 +33267,7 @@ async function handleToolCall(name, args, config2, _opts) {
33158
33267
  }
33159
33268
  const repo = resolveRepos(config2, [args.repo])[0];
33160
33269
  const wtPath = getWorktreePath(repo, args.branch);
33161
- if (!fs33.existsSync(wtPath)) {
33270
+ if (!fs34.existsSync(wtPath)) {
33162
33271
  throw { isToolError: true, message: `Worktree not found for branch ${args.branch}` };
33163
33272
  }
33164
33273
  const mainBranch = await resolveMainBranch(repo, config2);
@@ -33277,7 +33386,7 @@ async function handleToolCall(name, args, config2, _opts) {
33277
33386
  if (children.length > 0 && args.force !== true) {
33278
33387
  throw { isToolError: true, message: `Branch has dependent worktrees: ${children.join(", ")}. Use force:true to override.` };
33279
33388
  }
33280
- if (!args.force && fs33.existsSync(wtPath)) {
33389
+ if (!args.force && fs34.existsSync(wtPath)) {
33281
33390
  const dirty = await getDirtyFiles(wtPath);
33282
33391
  if (dirty.length > 0) {
33283
33392
  throw { isToolError: true, message: `Worktree is dirty. Use force:true to remove it.` };
@@ -33296,7 +33405,7 @@ async function handleToolCall(name, args, config2, _opts) {
33296
33405
  }
33297
33406
  const repo = resolveRepos(config2, [args.repo])[0];
33298
33407
  const wtPath = getWorktreePath(repo, args.branch);
33299
- if (!fs33.existsSync(wtPath)) {
33408
+ if (!fs34.existsSync(wtPath)) {
33300
33409
  throw { isToolError: true, message: `Worktree not found for branch ${args.branch}` };
33301
33410
  }
33302
33411
  const mainBranch = await resolveMainBranch(repo, config2);
@@ -33518,7 +33627,7 @@ init_config();
33518
33627
  init_resolver();
33519
33628
  init_log();
33520
33629
  init_history();
33521
- import fs34 from "fs";
33630
+ import fs35 from "fs";
33522
33631
  var program2 = new Command;
33523
33632
  program2.name("wtx").description("Multi-repo git worktree manager").version(VERSION).option("-q, --quiet", "Suppress progress indicators", false).option("--verbose", "Show git commands as they run", false).option("--dry-run", "Show what would happen", false);
33524
33633
  var MUTATING_COMMANDS = new Set([
@@ -33622,7 +33731,7 @@ program2.command("_resolve-path <repo> <branch>", { hidden: true }).description(
33622
33731
  }
33623
33732
  const repo = repos[0];
33624
33733
  const wtPath = getWorktreePath(repo, branch);
33625
- if (!fs34.existsSync(wtPath)) {
33734
+ if (!fs35.existsSync(wtPath)) {
33626
33735
  process.stderr.write(`✗ No worktree at ${wtPath}
33627
33736
  `);
33628
33737
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ogpoyraz/wtx",
3
- "version": "0.8.5",
3
+ "version": "0.8.6",
4
4
  "description": "Multi-repo git worktree manager",
5
5
  "type": "module",
6
6
  "bin": {