@jx0/jmux 0.5.1 → 0.5.3

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 -1
  2. package/package.json +1 -1
  3. package/src/main.ts +78 -4
package/README.md CHANGED
@@ -4,7 +4,9 @@
4
4
 
5
5
  **The terminal workspace for agentic development.**
6
6
 
7
- Run coding agents in parallel from your terminal. A persistent sidebar shows every session, what's running, and what needs your attention — without leaving the tools you already use.
7
+ Agents, editors, servers, logs. All running. All visible. One terminal.
8
+
9
+ Run Claude Code, Codex, or aider in parallel — jmux shows you which agents are working, which finished, and which need your review. No Electron. No lock-in. Just your terminal.
8
10
 
9
11
  [![npm](https://img.shields.io/npm/v/@jx0/jmux)](https://www.npmjs.com/package/@jx0/jmux)
10
12
  [![license](https://img.shields.io/github/license/jarredkenny/jmux)](LICENSE)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jx0/jmux",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "description": "The terminal workspace for agentic development",
5
5
  "type": "module",
6
6
  "bin": {
package/src/main.ts CHANGED
@@ -12,9 +12,16 @@ import { homedir } from "os";
12
12
 
13
13
  // --- CLI commands (run and exit before TUI) ---
14
14
 
15
- const VERSION = "0.5.1";
15
+ const VERSION = "0.5.3";
16
16
 
17
- const HELP = `jmux — a persistent session sidebar for tmux
17
+ const HELP = `jmux — the terminal workspace for agentic development
18
+
19
+ Agents, editors, servers, logs.
20
+ All running. All visible. One terminal.
21
+
22
+ Run Claude Code, Codex, or aider in parallel — jmux shows you which
23
+ agents are working, which finished, and which need your review.
24
+ No Electron. No lock-in. Just your terminal.
18
25
 
19
26
  Usage:
20
27
  jmux [session-name] [options]
@@ -33,10 +40,13 @@ Examples:
33
40
 
34
41
  Keybindings:
35
42
  Ctrl-Shift-Up/Down Switch sessions
36
- Ctrl-a n New session (directory picker)
43
+ Ctrl-a n New session / worktree
44
+ Ctrl-a i Settings
37
45
  Ctrl-a j Window picker (fzf)
38
46
  Ctrl-a c New window
39
- Click sidebar Switch to session`;
47
+ Click sidebar Switch to session
48
+
49
+ https://github.com/jarredkenny/jmux`;
40
50
 
41
51
  if (process.argv.includes("-h") || process.argv.includes("--help")) {
42
52
  console.log(HELP);
@@ -154,6 +164,69 @@ for (let i = 2; i < process.argv.length; i++) {
154
164
  process.exit(1);
155
165
  }
156
166
  }
167
+ // Preflight checks — offer to install missing dependencies
168
+ async function preflight(): Promise<void> {
169
+ const missing: string[] = [];
170
+ if (Bun.spawnSync(["tmux", "-V"], { stdout: "pipe", stderr: "pipe" }).exitCode !== 0) {
171
+ missing.push("tmux");
172
+ }
173
+ if (Bun.spawnSync(["fzf", "--version"], { stdout: "pipe", stderr: "pipe" }).exitCode !== 0) {
174
+ missing.push("fzf");
175
+ }
176
+ if (missing.length === 0) return;
177
+
178
+ const isMac = process.platform === "darwin";
179
+ const hasBrew = isMac && Bun.spawnSync(["brew", "--version"], { stdout: "pipe", stderr: "pipe" }).exitCode === 0;
180
+ const hasApt = !isMac && Bun.spawnSync(["apt", "--version"], { stdout: "pipe", stderr: "pipe" }).exitCode === 0;
181
+
182
+ console.log(`\njmux requires ${missing.join(" and ")} to run.\n`);
183
+
184
+ if (hasBrew || hasApt) {
185
+ const pm = hasBrew ? "brew" : "sudo apt";
186
+ const installCmd = `${pm} install ${missing.join(" ")}`;
187
+ console.log(`Install with:\n\n ${installCmd}\n`);
188
+
189
+ // Prompt to install
190
+ process.stdout.write("Install now? [Y/n] ");
191
+ const response = await new Promise<string>((resolve) => {
192
+ process.stdin.setRawMode?.(false);
193
+ process.stdin.resume();
194
+ process.stdin.once("data", (data) => {
195
+ process.stdin.pause();
196
+ resolve(data.toString().trim().toLowerCase());
197
+ });
198
+ });
199
+
200
+ if (response === "" || response === "y" || response === "yes") {
201
+ console.log(`\nRunning: ${installCmd}\n`);
202
+ const args = hasBrew
203
+ ? ["brew", "install", ...missing]
204
+ : ["sudo", "apt", "install", "-y", ...missing];
205
+ const result = Bun.spawnSync(args, { stdout: "inherit", stderr: "inherit" });
206
+ if (result.exitCode !== 0) {
207
+ console.error("\nInstallation failed. Please install manually and try again.");
208
+ process.exit(1);
209
+ }
210
+ console.log("\nDependencies installed. Starting jmux...\n");
211
+ return;
212
+ }
213
+ } else {
214
+ // No package manager detected — just show instructions
215
+ if (isMac) {
216
+ console.log("Install Homebrew first: https://brew.sh");
217
+ console.log(`Then run: brew install ${missing.join(" ")}`);
218
+ } else {
219
+ console.log(`Install with your package manager, e.g.:`);
220
+ console.log(` apt install ${missing.join(" ")}`);
221
+ console.log(` dnf install ${missing.join(" ")}`);
222
+ console.log(` pacman -S ${missing.join(" ")}`);
223
+ }
224
+ }
225
+
226
+ process.exit(1);
227
+ }
228
+ await preflight();
229
+
157
230
  const cols = process.stdout.columns || 80;
158
231
  const rows = process.stdout.rows || 24;
159
232
  const sidebarVisible = cols >= 80;
@@ -591,6 +664,7 @@ async function start(): Promise<void> {
591
664
  // we attached to an existing server that loaded ~/.tmux.conf
592
665
  // Set JMUX_DIR in tmux's global environment so config bindings can reference it
593
666
  await control.sendCommand(`set-environment -g JMUX_DIR ${jmuxDir}`);
667
+ await control.sendCommand("set-environment -g JMUX 1");
594
668
  await control.sendCommand(`source-file ${configFile}`);
595
669
  // Re-enable automatic-rename on all windows — clears any application-set names
596
670
  try {