peakypanes 0.0.3 → 0.0.5

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/README.md CHANGED
@@ -6,12 +6,12 @@
6
6
  █ █████ █ █ █ ██ █ █ █ █ █ ██ █████ █████
7
7
  ```
8
8
 
9
- **Tmux layout manager with YAML-based configuration.**
9
+ **Terminal dashboard with YAML-based layouts, native live previews, and persistent native sessions.**
10
10
 
11
- ![Peaky Panes Preview](assets/peakypanes-preview.jpg)
11
+ ![Peaky Panes Preview](assets/preview-peakypanes-v2.jpg)
12
12
 
13
13
 
14
- Define your tmux layouts in YAML, share them with your team via git, and get consistent development environments everywhere.
14
+ Define your layouts in YAML, share them with your team via git, and get consistent development environments everywhere. Sessions are owned by a **native daemon** so they keep running after the UI exits.
15
15
 
16
16
  ## Features
17
17
 
@@ -21,9 +21,11 @@ Define your tmux layouts in YAML, share them with your team via git, and get con
21
21
  - 🏠 **Global config** - Define layouts once, use everywhere
22
22
  - 🔄 **Variable expansion** - Use `${EDITOR}`, `${PROJECT_PATH}`, etc.
23
23
  - 🎯 **Zero config** - Just run `peakypanes` in any directory
24
- - ⚙️ **Session-scoped tmux options** - Configure tmux per-session without affecting global config
25
- - 🪟 **Popup dashboard** - Open the UI as a tmux popup when available
26
- - **Command palette** - Quick actions, including renaming sessions/windows
24
+ - 🧠 **Native live previews** - Full TUI support (vim/htop) with live panes
25
+ - 🧭 **Persistent native daemon** - Sessions keep running after the UI exits
26
+ - 📜 **Scrollback + copy mode** - Navigate output and yank from native panes
27
+ - ⌘ **Command palette** - Quick actions, including renaming sessions/panes
28
+ - 🖱️ **Mouse support** - Click to select panes, double-click to focus a pane
27
29
 
28
30
  ## Quick Start
29
31
 
@@ -36,21 +38,31 @@ npm i -g peakypanes
36
38
  peakypanes
37
39
  ```
38
40
 
39
- > [!TIP]
40
- > Run `peakypanes setup` to check dependencies
41
-
42
41
  **Run once with npx**
43
42
 
44
43
  ```bash
45
44
  npx -y peakypanes
46
45
  ```
47
46
 
47
+ **Using Homebrew**
48
+
49
+ ```bash
50
+ brew tap regenrek/tap
51
+ brew install regenrek/tap/peakypanes
52
+ ```
53
+
48
54
  Using Go
49
55
 
50
56
  ```bash
51
57
  go install github.com/regenrek/peakypanes/cmd/peakypanes@latest
52
58
  ```
53
59
 
60
+ **Hot reload (from repo)**
61
+
62
+ ```bash
63
+ scripts/dev-watch -- --layout dev-3
64
+ ```
65
+
54
66
  ### Usage
55
67
 
56
68
  **Start a session (auto-detect layout):**
@@ -72,9 +84,14 @@ peakypanes init --local
72
84
  git add .peakypanes.yml # Share with team
73
85
  ```
74
86
 
87
+ **Run the daemon in the foreground (optional):**
88
+ ```bash
89
+ peakypanes daemon
90
+ ```
91
+
75
92
  ## Configuration
76
93
 
77
- > 📖 **[Layout Builder Guide](docs/layout-builder.md)** - Detailed documentation on creating custom layouts, pane arrangements, and tmux options.
94
+ > 📖 **[Layout Builder Guide](docs/layout-builder.md)** - Detailed documentation on creating custom layouts, pane arrangements, and configuration.
78
95
 
79
96
  ### Project-Local (`.peakypanes.yml`)
80
97
 
@@ -85,28 +102,22 @@ Create in your project root for team-shared layouts:
85
102
  session: my-project
86
103
 
87
104
  layout:
88
- windows:
89
- - name: dev
90
- panes:
91
- - title: editor
92
- cmd: "${EDITOR:-}"
93
- size: "60%"
94
- - title: server
95
- cmd: "npm run dev"
96
- split: horizontal
97
- - title: shell
98
- cmd: ""
99
- split: vertical
100
-
101
- - name: logs
102
- panes:
103
- - title: docker
104
- cmd: "docker compose logs -f"
105
+ panes:
106
+ - title: editor
107
+ cmd: "${EDITOR:-}"
108
+ size: "60%"
109
+ - title: server
110
+ cmd: "npm run dev"
111
+ split: horizontal
112
+ - title: shell
113
+ cmd: ""
114
+ split: vertical
115
+ - title: docker
116
+ cmd: "docker compose logs -f"
105
117
 
106
118
  # Or use exact grids
107
119
  # layout:
108
120
  # grid: 2x3
109
- # window: codex
110
121
  # commands:
111
122
  # - "${SHELL:-bash}"
112
123
  # - "codex"
@@ -128,12 +139,6 @@ layout:
128
139
  For personal layouts and multi-project management:
129
140
 
130
141
  ```yaml
131
- # Global settings
132
- tmux:
133
- # Optional: source a custom tmux config when starting sessions.
134
- # (tmux already reads ~/.tmux.conf or ~/.config/tmux/tmux.conf by default)
135
- config: ~/.config/tmux/tmux.conf
136
-
137
142
  # Dashboard UI settings (optional)
138
143
  # dashboard:
139
144
  # project_roots:
@@ -143,13 +148,11 @@ tmux:
143
148
  # Custom layouts
144
149
  layouts:
145
150
  my-custom:
146
- windows:
147
- - name: main
148
- panes:
149
- - title: code
150
- cmd: nvim
151
- - title: term
152
- cmd: ""
151
+ panes:
152
+ - title: code
153
+ cmd: nvim
154
+ - title: term
155
+ cmd: ""
153
156
 
154
157
  # Projects for quick switching
155
158
  projects:
@@ -174,10 +177,8 @@ Use variables in your layouts:
174
177
  layout:
175
178
  vars:
176
179
  log_file: "${HOME}/logs/${PROJECT_NAME}.log"
177
- windows:
178
- - name: dev
179
- panes:
180
- - cmd: "tail -f ${log_file}"
180
+ panes:
181
+ - cmd: "tail -f ${log_file}"
181
182
  ```
182
183
 
183
184
  ## Commands
@@ -185,23 +186,39 @@ layout:
185
186
  ```bash
186
187
  peakypanes # Open dashboard (direct)
187
188
  peakypanes dashboard # Open dashboard (direct)
188
- peakypanes dashboard --tmux-session # Host dashboard in tmux session
189
- peakypanes dashboard --popup # Open dashboard as a tmux popup
190
- peakypanes popup # Open dashboard as a tmux popup
191
- peakypanes open # Start/attach session in current directory
189
+ peakypanes open # Start session and open dashboard
192
190
  peakypanes start # Same as open
193
191
  peakypanes start --layout X # Use specific layout
194
- peakypanes start --detach # Create session without attaching
195
- peakypanes kill [session] # Kill a tmux session
196
192
  peakypanes init # Create global config
197
193
  peakypanes init --local # Create .peakypanes.yml
198
194
  peakypanes layouts # List available layouts
199
195
  peakypanes layouts export X # Export layout YAML
200
196
  peakypanes clone user/repo # Clone from GitHub and start session
201
- peakypanes setup # Check external dependencies
202
197
  peakypanes version # Show version
203
198
  ```
204
199
 
200
+ ## Troubleshooting: daemon stuck / restart
201
+
202
+ The daemon owns sessions and PTYs. If it becomes unresponsive, the only recovery
203
+ today is a manual restart, which **will terminate all running sessions**.
204
+
205
+ **Manual restart (macOS default path):**
206
+ ```bash
207
+ kill "$(cat "$HOME/Library/Application Support/peakypanes/daemon.pid")"
208
+ ```
209
+
210
+ **Manual restart (Linux default path):**
211
+ ```bash
212
+ kill "$(cat "$HOME/.config/peakypanes/daemon.pid")"
213
+ ```
214
+
215
+ You can also set `PEAKYPANES_DAEMON_PID` to control the pid file location.
216
+
217
+ ### Proposed UX (future)
218
+ If the app detects a hung daemon, it should show a dialog like:
219
+ **“Restart daemon? This will stop all running sessions and close their PTYs.”**
220
+ This makes the data-loss tradeoff explicit before taking action.
221
+
205
222
  ## Built-in Layouts
206
223
 
207
224
  Core (general) layouts:
@@ -216,7 +233,7 @@ Core (general) layouts:
216
233
  Additional built-ins (specialized):
217
234
  - `dev-2`: editor + shell
218
235
  - `dev-3`: editor + server + shell (default fallback)
219
- - `fullstack`: dev + logs
236
+ - `fullstack`: editor + server + shell + logs
220
237
  - `go-dev`: code/run/test + git
221
238
  - `codex-grid`: 2x4 grid running codex in every pane
222
239
 
@@ -231,49 +248,46 @@ peakypanes layouts export codex-dev > .peakypanes.yml
231
248
  ## Dashboard UI
232
249
 
233
250
  Running `peakypanes` with no subcommand opens the dashboard UI in the current terminal.
234
- Use `peakypanes dashboard --tmux-session` to host the dashboard in a dedicated tmux session.
235
- Use `peakypanes popup` (or `peakypanes dashboard --popup`) from inside tmux for a popup dashboard.
236
- If popups are unsupported, PeakyPanes opens a `peakypanes-dashboard` window in the current tmux session.
237
251
 
238
252
  The dashboard shows:
239
253
  - Projects on top (tabs)
240
- - Sessions on the left (with window counts and expandable windows)
241
- - Live pane preview on the right (window bar at the bottom)
242
- - Lightweight session thumbnails at the bottom (last activity per session)
254
+ - Sessions on the left (with pane counts and expandable panes)
255
+ - Live pane preview on the right (native panes are fully interactive)
243
256
  - Quick reply bar (always visible) and target pane highlight for follow-ups
244
257
 
245
258
  Navigation (always visible):
246
- - `ctrl+a/ctrl+d` project, `ctrl+w/ctrl+s` session, `tab/⇧tab` pane (across windows), `ctrl+g` help
259
+ - `ctrl+a/ctrl+d` project, `ctrl+w/ctrl+s` session/panes, `alt+w/alt+s` session only, `tab/⇧tab` pane, `ctrl+g` help
247
260
 
248
261
  Key bindings (also shown in the help view):
249
262
  Keymap overrides are available in the global config (`~/.config/peakypanes/config.yml`).
250
263
 
251
264
  Project
252
265
  - `ctrl+o` open project picker (creates session detached; stay in dashboard)
253
- - `ctrl+b` close project (kills all running sessions in project)
266
+ - `ctrl+b` close project (hides from tabs; sessions keep running; press k in the dialog to kill)
254
267
 
255
268
  Session
256
269
  - `enter` attach/start session (when reply is empty)
257
270
  - `ctrl+n` new session (pick layout)
258
- - `ctrl+t` open in new terminal window
259
271
  - `ctrl+x` kill session
260
272
  - rename session via command palette (`ctrl+p`)
261
273
 
262
274
  Window
263
- - `ctrl+u` toggle window list
264
- - rename window via command palette (`ctrl+p`)
275
+ Pane list
276
+ - `ctrl+u` toggle pane list
265
277
 
266
278
  Pane
267
279
  - rename pane via command palette (`ctrl+p`)
268
-
269
- Tmux (inside session)
270
- - `prefix+g` open dashboard popup (tmux prefix is yours)
280
+ - `ctrl+y` peek selected pane in new terminal
281
+ - `ctrl+\` toggle terminal focus (native only; configurable via `dashboard.keymap.terminal_focus`)
282
+ - mouse: single-click selects a pane; double-click toggles terminal focus (native only); `esc` exits focus
283
+ - `f7` scrollback mode (native only; configurable via `dashboard.keymap.scrollback`)
284
+ - `f8` copy mode (native only; configurable via `dashboard.keymap.copy_mode`)
271
285
 
272
286
  Other
273
287
  - `ctrl+p` command palette
274
288
  - `ctrl+r` refresh, `ctrl+e` edit config, `ctrl+f` filter, `ctrl+c` quit
275
289
 
276
- Quick reply details: the input is always active—type and press `enter` to send to the highlighted pane. Use `esc` to clear. `tab/⇧tab` still cycles panes while the input is focused.
290
+ Quick reply details: the input is always active—type and press `enter` to send to the highlighted pane. Use `esc` to clear. Toggle terminal focus to send raw keystrokes into the pane. Use scrollback (`f7`) to navigate output and copy mode (`f8`) to select/yank (`v` select, `y` yank, `esc/q` exit).
277
291
 
278
292
  ### Dashboard Config (optional)
279
293
 
@@ -282,19 +296,22 @@ dashboard:
282
296
  refresh_ms: 2000
283
297
  preview_lines: 12
284
298
  preview_compact: true
285
- thumbnail_lines: 1
286
299
  idle_seconds: 20
287
- show_thumbnails: true
288
300
  preview_mode: grid # grid | layout
289
- attach_behavior: new_terminal # current | new_terminal | detached
301
+ attach_behavior: current # current | detached
290
302
  keymap:
291
303
  project_left: ["ctrl+a"]
292
304
  project_right: ["ctrl+d"]
293
305
  session_up: ["ctrl+w"]
294
306
  session_down: ["ctrl+s"]
307
+ session_only_up: ["alt+w"]
308
+ session_only_down: ["alt+s"]
295
309
  pane_next: ["tab"]
296
310
  pane_prev: ["shift+tab"]
297
- toggle_windows: ["ctrl+u"]
311
+ terminal_focus: ["ctrl+\\"]
312
+ scrollback: ["f7"]
313
+ copy_mode: ["f8"]
314
+ toggle_panes: ["ctrl+u"]
298
315
  command_palette: ["ctrl+p"]
299
316
  help: ["ctrl+g"]
300
317
  quit: ["ctrl+c"]
@@ -307,13 +324,13 @@ dashboard:
307
324
  claude: true
308
325
  ```
309
326
 
310
- `attach_behavior` controls what the “attach/start” action does (default `new_terminal`): `current` switches the terminal running PeakyPanes into the session, `new_terminal` opens a fresh terminal to attach, and `detached` only creates the session.
327
+ `attach_behavior` controls what the “attach/start” action does (default `current`): `current` focuses the selected session in the dashboard, and `detached` creates the session without switching focus.
311
328
 
312
329
  ### Agent Status Detection (Codex & Claude Code)
313
330
 
314
331
  PeakyPanes can read per-pane JSON state files to show accurate running/idle/done status for Codex CLI and Claude Code TUI sessions. This is **on by default** and falls back to regex/idle detection if no state file is present. You can disable it via `dashboard.agent_detection`.
315
332
 
316
- State files are written under `${XDG_RUNTIME_DIR:-/tmp}/peakypanes/agent-state` and keyed by `TMUX_PANE` (override with `PEAKYPANES_AGENT_STATE_DIR`).
333
+ State files are written under `${XDG_RUNTIME_DIR:-/tmp}/peakypanes/agent-state` and keyed by `PEAKYPANES_PANE_ID` (override with `PEAKYPANES_AGENT_STATE_DIR`).
317
334
 
318
335
  **Codex CLI (TUI)**
319
336
 
@@ -338,23 +355,6 @@ Example hook command (wire it to each event above in Claude Code):
338
355
  python3 /absolute/path/to/peakypanes/scripts/agent-state/claude-hook.py
339
356
  ```
340
357
 
341
- ### Tmux Config & Key Bindings
342
-
343
- - PeakyPanes **never edits** your tmux config file.
344
- - tmux already reads `~/.tmux.conf` or `~/.config/tmux/tmux.conf` by default.
345
- - If you use a **custom tmux config path**, set `tmux.config` in `~/.config/peakypanes/config.yml`.
346
- PeakyPanes will **source** that file when starting sessions (no overwrite).
347
- - Per-layout tmux options and key bindings are supported:
348
-
349
- ```yaml
350
- settings:
351
- tmux_options:
352
- remain-on-exit: "on"
353
- bind_keys:
354
- - key: g
355
- action: "run-shell \"peakypanes popup\""
356
- ```
357
-
358
358
  ## How Layout Detection Works
359
359
 
360
360
  1. `--layout` flag (highest priority)
@@ -377,20 +377,14 @@ Race tests:
377
377
  go test ./... -race
378
378
  ```
379
379
 
380
- Tmux integration tests (requires tmux; opt-in):
381
-
382
- ```bash
383
- PEAKYPANES_INTEGRATION=1 go test ./internal/tmuxctl -run Integration -count=1
384
- ```
385
-
386
380
  Manual npm smoke run (fresh HOME/XDG config):
387
381
 
388
382
  ```bash
389
383
  scripts/fresh-run
390
- scripts/fresh-run 0.0.2 --with-project
384
+ scripts/fresh-run 0.0.5 --with-project
391
385
  ```
392
386
 
393
- GitHub Actions runs gofmt checks, go vet, go test with coverage, race, and tmux integration tests on Linux.
387
+ GitHub Actions runs gofmt checks, go vet, go test with coverage, and race on Linux.
394
388
 
395
389
  ## Release
396
390
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "peakypanes",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "Tmux layout manager with YAML based configuration.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/regenrek/peakypanes",
@@ -12,10 +12,10 @@
12
12
  "peakypanes": "bin/peakypanes.js"
13
13
  },
14
14
  "optionalDependencies": {
15
- "peakypanes-darwin-x64": "0.0.3",
16
- "peakypanes-darwin-arm64": "0.0.3",
17
- "peakypanes-linux-x64": "0.0.3",
18
- "peakypanes-linux-arm64": "0.0.3"
15
+ "peakypanes-darwin-x64": "0.0.5",
16
+ "peakypanes-darwin-arm64": "0.0.5",
17
+ "peakypanes-linux-x64": "0.0.5",
18
+ "peakypanes-linux-arm64": "0.0.5"
19
19
  },
20
20
  "engines": {
21
21
  "node": ">=18"
@@ -70,7 +70,7 @@ def map_event_to_state(event: str, payload: dict) -> str:
70
70
 
71
71
 
72
72
  def main() -> int:
73
- pane_id = os.environ.get("TMUX_PANE", "").strip()
73
+ pane_id = os.environ.get("PEAKYPANES_PANE_ID", "").strip()
74
74
  if not pane_id:
75
75
  return 0
76
76
  try:
@@ -36,7 +36,7 @@ def write_state(pane_id: str, state: str, tool: str, payload: dict) -> None:
36
36
 
37
37
 
38
38
  def main() -> int:
39
- pane_id = os.environ.get("TMUX_PANE", "").strip()
39
+ pane_id = os.environ.get("PEAKYPANES_PANE_ID", "").strip()
40
40
  if not pane_id:
41
41
  return 0
42
42
  if len(sys.argv) < 2: