@puddle-code/cli 0.0.1 → 0.0.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 (54) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +112 -0
  3. package/dist/index.js +825 -165
  4. package/dist/install.sh +8 -0
  5. package/dist/public/assets/Dashboard-zbeaP4WM.js +1 -0
  6. package/dist/public/assets/EditorTabClose-Bujs4cab.js +1 -0
  7. package/dist/public/assets/ModelRefcount-BN4jRD-x.js +1 -0
  8. package/dist/public/assets/PaneEditorBody-COdCF9BY.js +1 -0
  9. package/dist/public/assets/SettingsDialog-CKW2AM11.js +1 -0
  10. package/dist/public/assets/{Terminal-CuEf-GeX.js → Terminal-hw3UjYEu.js} +2 -2
  11. package/dist/public/assets/Workspace-DrDkPyrd.js +6 -0
  12. package/dist/public/assets/api-BJKPJeFZ.js +73 -0
  13. package/dist/public/assets/buffer-logic-BrpRsL1b.js +1 -0
  14. package/dist/public/assets/buffer-store-BGy4Fj9o.js +16 -0
  15. package/dist/public/assets/context-menu-CnHdXMkI.js +1 -0
  16. package/dist/public/assets/createLucideIcon-DyMAgLa3.js +1 -0
  17. package/dist/public/assets/cssMode-DuLDfCcC.js +1 -0
  18. package/dist/public/assets/debounce-B9DrqirV.js +1 -0
  19. package/dist/public/assets/dialog-B43iKmfK.js +41 -0
  20. package/dist/public/assets/dist-fdPAlKke.js +1 -0
  21. package/dist/public/assets/editor-sync-F3Wyveaa.js +1 -0
  22. package/dist/public/assets/editor-tabs-Cw21CVB0.js +1 -0
  23. package/dist/public/assets/htmlMode-DaGDGb6z.js +1 -0
  24. package/dist/public/assets/index-wPaOVZ8U.js +10 -0
  25. package/dist/public/assets/index-y2Zzy0lJ.css +2 -0
  26. package/dist/public/assets/{jsonMode-BijgXT6I.js → jsonMode-Ekn8HPfg.js} +1 -1
  27. package/dist/public/assets/jsx-runtime-ffCh33zF.js +1 -0
  28. package/dist/public/assets/react-CZI7_Jkm.js +1 -0
  29. package/dist/public/assets/ssh-mode-CghPpMrk.js +1 -0
  30. package/dist/public/assets/switch-CQITZ7yg.js +1 -0
  31. package/dist/public/assets/{tsMode-B7q3gz7a.js → tsMode-CsjWL1Qz.js} +1 -1
  32. package/dist/public/assets/useMutation-Da9b4jwS.js +1 -0
  33. package/dist/public/assets/utils-B6KiDbIe.js +1 -0
  34. package/dist/public/index.html +9 -4
  35. package/package.json +14 -3
  36. package/dist/index.d.ts +0 -3
  37. package/dist/index.d.ts.map +0 -1
  38. package/dist/index.js.map +0 -1
  39. package/dist/public/assets/Dashboard-B1JE6YHV.js +0 -1
  40. package/dist/public/assets/EditorZone-BO-Ob9Td.js +0 -16
  41. package/dist/public/assets/SettingsDialog-CVcCiV13.js +0 -1
  42. package/dist/public/assets/Workspace-DctKubgC.js +0 -2
  43. package/dist/public/assets/api-DeKerbkb.js +0 -64
  44. package/dist/public/assets/cssMode-CSjHtANE.js +0 -1
  45. package/dist/public/assets/dialog-VTyOt2M_.js +0 -41
  46. package/dist/public/assets/folder-git-2-DX3SNYUW.js +0 -1
  47. package/dist/public/assets/history-logic-B2ZKE3AW.js +0 -1
  48. package/dist/public/assets/htmlMode-CIHMS93l.js +0 -1
  49. package/dist/public/assets/index-CXBMvmhw.css +0 -2
  50. package/dist/public/assets/index-ZcdMfr13.js +0 -10
  51. package/dist/public/assets/monaco.contribution-C0TYpF88.js +0 -2
  52. package/dist/public/assets/ssh-mode-BR2ZdOHI.js +0 -1
  53. package/dist/public/assets/switch-Ck_7k8fh.js +0 -1
  54. package/dist/public/assets/workers-Ck67TJT4.js +0 -1
package/CHANGELOG.md ADDED
@@ -0,0 +1,36 @@
1
+ <!--
2
+ Rolling changelog for the NEXT release. Governance lives in CLAUDE.md §"Changelog discipline".
3
+ On publish: retitle [Unreleased] to [X.Y.Z] — date, archive a copy to
4
+ docs/changelogs/CHANGELOG-vX.Y.Z.md, then reset this file to this template.
5
+ Past releases: see docs/changelogs/.
6
+ -->
7
+
8
+ # Changelog
9
+
10
+ ## [0.0.3] — 2026-07-15
11
+
12
+ ### Added
13
+
14
+ - **Unarchive a session** (protocol 6.2, `POST /api/sessions/:id/unarchive`). Archiving is now a **reversible hide**, not a teardown: it keeps the worktree, its branch, and the agent conversation, so archived rows carry the same ⋯ menu and can be brought straight back. If the worktree still exists the session resumes with its history; if it was pruned (or its branch deleted) the session returns visible for its history only, with resume disabled. Archiving itself no longer pops a dialog — one click hides it, and because nothing is destroyed a dirty worktree is safe (SPEC §4).
15
+ - **VSCode-style preview tabs** (SPEC §8): single-clicking a file, session, or terminal opens it in one reusable _preview_ tab (shown in italics) that the next single-click replaces; double-clicking the item — or its preview tab — pins it as a permanent tab.
16
+ - A third **launch-text template** in Settings → Sessions, "Resume after restart", sent when a session is resumed after a daemon restart or machine reboot (previously a fixed built-in note). Editable per profile; empty sends nothing (protocol 6.2, profile setting `restartTemplate`).
17
+ - The **Files** and **Search** navigator headers now name the worktree's **absolute path** (what they operate over), while Changes keeps naming the branch.
18
+ - `README.md` gained a **Development & teardown** section: running a local dev build (`--tarball`/`--foreground`) versus the published CLI, killing the cockpit vs. stopping the daemon service (launchd/systemd/nohup), and a full uninstall.
19
+ - A per-profile **tab-title template** (Settings → Sessions) composes each session's tab/sidebar label from `${…}` parts — `${name}`, `${branch}`, `${sequence}`, `${status}`, a conditional `${separator}`, and more — with a live preview; the default `${name}` reproduces the previous label. Terminals and agents without their own name now also take a name from the terminal-title escape the process sets (the `${sequence}` value). Protocol 6.0 → 6.1 (additive).
20
+
21
+ ### Changed
22
+
23
+ - **Sidebar colours**: hint/metadata text (gitignored files, placeholders, search & empty-state hints, commit metadata, branch/path labels, setting descriptions) is now a neutral **grey** instead of the distracting warm golden bark. The gold survives as a deliberate accent — a new `--text-gold` token (gold in both themes) — for the sidebar's **glyph icons** and its **ALL-CAPS section headings**. Dark theme's muted was already grey.
24
+ - The left navigator header (Files/Search/Changes) no longer auto-scrolls its title on hover (distracting); it's a plain horizontally-scrollable strip **anchored to the right**, so the deepest part of an absolute path stays visible. The Worktrees tab keeps its calmer per-item hover-scroll.
25
+ - **Top bar** revamp: the puddle mark shrank and now sits beside the daemon's **host name** as one click-home block; the centre is a dimmed command field (hinting the active project name + ⌘K) that opens the palette; the separate ⌘K button is gone.
26
+ - The empty workspace pane no longer reserves a blank tab bar; it shows a large, muted puddle mark and a dimmed **⌘K** button that opens the command palette.
27
+
28
+ ### Fixed
29
+
30
+ - On a **brand-new project**, the first file/terminal you opened could show a blank pane until a reload: the one-time layout-tree migration effect persisted an _empty_ tree and, because it re-ran on every render (its dep changed identity each time), could commit **after** that first open and overwrite it. It now fires exactly once and skips persisting an empty tree, so it can't race — nor clobber — the first open.
31
+ - Creating a session or terminal now appears in the sidebar **immediately** instead of only after a reload: the create/rename/archive/kill/migrate mutations invalidated only the per-project session list, never the cross-project sidebar's `['sessions', 'profile', …]` query.
32
+ - The **Settings** dialog no longer intermittently fails to open (or silently closes) and need a reload: its open section is now a controlled store rather than being read live from `window.location.hash` — assigning the fragment its current value fires no `hashchange`, and react-router navigations can clear the fragment with no event at all. The URL `#settings/<section>` stays as a deep-link mirror, resynced on back/forward.
33
+ - A rename made **inside the agent** (e.g. claude-code's `/rename`) now propagates to the session's display name live, **including while the session sits idle**. Such renames are client-side (they rewrite the agent's transcript title) and change no puddle status, so the daemon re-reads the agent's own name on each status change, when the agent emits a terminal-title escape (OSC 0/1/2, throttled), and — the reliable path for an idle rename, which emits neither — on a low-frequency timer (a cheap tail read that early-returns when unchanged). The transcript stays the source of truth and a user rename still wins (SPEC §4).
34
+ - Filetree header: the branch title now uses the full sidebar width at rest. The utility, pin, and worktree-picker controls surfaced from an overlay on hover/focus instead of reserving (and so occluding) width while hidden — the title was clipped even when no icons showed (SPEC §12).
35
+ - Worktrees list: rows now extend to the sidebar's right edge — the hover-only prune control no longer reserves an empty gap after the badges.
36
+ - `puddle connect` / `status` no longer fail with "could not open a tunnel" against hosts reached over **Tailscale SSH** (or other non-OpenSSH servers). Over a multiplexed master such servers install the `-L` forward on the master and the spawned `ssh` client exits immediately while the forward keeps carrying traffic; the tunnel wrongly treated that client's exit — and required it to stay alive for readiness — as the tunnel dying. The forward is now judged by the **forward itself**: readiness is its local listener accepting plus an end-to-end probe the daemon answers `/api/version` through, and liveness is a periodic check of that listener — never the spawned client's fate. The `ExitOnForwardFailure=yes` flag (which the same servers trip) was dropped, and forwards abandoned on the master are cleaned up with `ssh -O cancel` since they outlive the client and would otherwise leak the port. Automatic remote-daemon port discovery (runtime.json → config.json → 7434) is unchanged (SPEC §10).
package/README.md ADDED
@@ -0,0 +1,112 @@
1
+ # Puddle
2
+
3
+ [![npm](https://img.shields.io/npm/v/@puddle-code/cli?logo=npm)](https://www.npmjs.com/package/@puddle-code/cli)
4
+ [![Licence: MIT](https://img.shields.io/badge/licence-MIT-blue)](LICENSE)
5
+
6
+ Puddle is an open-source, multi-account coding agent orchestrator with first-class SSH support and a lightweight GUI. With a single command,
7
+
8
+ ```bash
9
+ puddle connect <user>@<host>
10
+ ```
11
+
12
+ Puddle manages parallel agents anywhere you SSH into, insulates agents in dedicated worktrees, and keeps your agents alive across disconnects and restarts.
13
+
14
+ ## Quick start
15
+
16
+ **On your local machine where you will be using the GUI, run:**
17
+
18
+ ```sh
19
+ npm install -g @puddle-code/cli
20
+ ```
21
+
22
+ **To launch agents on a remote host:**
23
+
24
+ ```sh
25
+ puddle connect <user>@<host>
26
+ ```
27
+
28
+ This connects Puddle to the remote host over SSH, bootstrapping the Puddle daemon on first contact and enabling you to begin development.
29
+
30
+ Puddle works using your system `ssh`, so `~/.ssh/config`, agents, and jump hosts apply.
31
+
32
+ **For development on your own machine:**
33
+
34
+ ```sh
35
+ puddle start
36
+ ```
37
+
38
+ This installs the Puddle daemon under `~/.puddle` and serves the GUI at `http://localhost:7433`.
39
+
40
+ Note that Ctrl-C closes the GUI only, while agent sessions keep running.
41
+
42
+ **Daemon-only installs:**
43
+
44
+ Daemon-only installs (no CLI) use the `install.sh` attached to each release — see the Releases page of this repository:
45
+
46
+ ```sh
47
+ curl -fsSL https://github.com/PerceptronV/puddle-code/releases/latest/download/install.sh | sh
48
+ ```
49
+
50
+ **Host requirements**: Linux (glibc — Ubuntu 22.04+, Debian 12+, RHEL 9+; Alpine is not supported) or macOS, with `git` and `curl`, plus whichever agent CLIs you want on `PATH`. The client side works from any OS with a browser and `ssh` (Windows works, with repeated auth prompts unless you use a key).
51
+
52
+ ## How it works
53
+
54
+ - **The Puddle daemon works anywhere you can SSH into.** It is installed on your host during every fresh connect, relaying information across SSH to your local GUI. The daemon is the parent of every agent process, keeping sessions running when your laptop sleeps, the window closes, or the SSH connection drops. Puddle also maintains a stateful memory of your conversations to survive machine reboots.
55
+ - **Puddle orchestrates parallel isolated agents** each working in a unique git worktree and branch. You can choose the branch and worktree during session creation.
56
+ - **Puddle's lightweight GUI** allows you to track agent progress, session usage, and active worktrees.
57
+ - **Puddle's philosophy is that any good developer must stay grounded in their code.** Puddle natively integrates live terminals, file editing in Monaco, git commit grahps, diff views, and opens worktrees in your favourite IDE.
58
+ - **Multiple profiles and accounts** enable several collaborators to collaborate on a shared remote host. Puddle manages multiple accounts per agent type and profile, symlinking conversation histories so you can run from multiple Claude Code accounts at once and move your conversations between each.
59
+
60
+ ```
61
+ client machine host machine (local or remote)
62
+ ┌──────────────────────────────┐ ┌───────────────────────────────────┐
63
+ │ browser ── localhost:7433 │ │ puddled (systemd user service) │
64
+ │ │ │ local: │ ├─ REST + WS API │
65
+ │ puddle CLI ◄─┘ │ direct │ ├─ PTY manager │
66
+ │ ├─ static web UI assets │───────►│ ├─ git worktree manager │
67
+ │ └─ /api + /ws proxy │ remote:│ ├─ per-agent adapters │
68
+ └──────────────────────────────┘ ssh -L │ └─ SQLite + append-only logs │
69
+ └───────────────────────────────────┘
70
+ ```
71
+
72
+ The CLI serves the UI at a stable local origin and reverse-proxies the API to the daemon, directly in local mode, through the tunnel in SSH mode. The daemon is headless and host-agnostic on `127.0.0.1:7434`. UI updates ship with the CLI (`npm update -g @puddle-code/cli` refreshes the cockpit for every host); the daemon only has to update when the versioned protocol breaks, and the CLI does that automatically. A mandatory bearer token plus Host/Origin validation guard the localhost API against malicious web pages.
73
+
74
+ Everything lives under `~/.puddle` on the host, installed without sudo. Uninstalling is stopping the service and deleting that directory.
75
+
76
+ ## Development & teardown
77
+
78
+ **One daemon, many clients.** There is a single local daemon per machine, living under `~/.puddle` and run by one supervised service (launchd's `dev.puddle.puddled` on macOS, systemd's `puddled` on Linux). The global `puddle` and a repo-run `node packages/cli/dist/index.js` are **both just clients** that talk to — and, when needed, install — that same daemon. They never run side by side, and there is no separate "dev daemon" alongside a "production daemon".
79
+
80
+ **Dev build vs. production.** `npm i -g @puddle-code/cli` is the production path — its `puddle` fetches and upgrades the daemon from this repo's GitHub Releases. To exercise uncommitted changes, build and run from the repo:
81
+
82
+ ```sh
83
+ pnpm build && pnpm build:tarball
84
+ node packages/cli/dist/index.js start --tarball dist-release/puddled-v*.tar.gz --foreground
85
+ ```
86
+
87
+ `--tarball` sets the install _source_ only, and is consulted **only when the CLI actually installs the daemon** — when none is running, the daemon is stopped, or a protocol-major upgrade fires. If a compatible daemon (same protocol major) is already up, `start` just serves the cockpit against it and **the tarball is ignored** (even a newer app version — nothing compares app versions). So to load a fresh dev build over a running daemon you must **stop it first** (see _Kill_ below), then re-run `start --tarball …`. `--foreground` keeps the cockpit attached (`connect <user>@<host> --tarball …` is the remote form). Both clients share one `~/.puddle` daemon and cockpit registry, so `puddle list` / `puddle kill` see either — don't point both at the same host at once. (Never launch the daemon from inside a coding-agent shell: it inherits the agent's env and breaks conversation resume — use a plain terminal.)
88
+
89
+ **Kill.** `puddle kill --all` (or Ctrl-C in a `--foreground` run) stops the local cockpit UI only; the daemon and its agent sessions keep running. The daemon is auto-restarting (launchd `KeepAlive`, systemd `Restart=always`), so a plain `kill <pid>` bounces straight back — stop it through its supervisor:
90
+
91
+ ```sh
92
+ launchctl bootout gui/$(id -u)/dev.puddle.puddled # macOS (launchd)
93
+ systemctl --user disable --now puddled # Linux (systemd user unit)
94
+ kill "$(cat ~/.puddle/puddled.pid)" # nohup fallback (no supervisor)
95
+ ```
96
+
97
+ **Restore the production daemon.** When you're done testing, put the release build back over your dev one: stop the daemon (above), clear the installed binaries with `rm -rf ~/.puddle/bin` (your `~/.puddle` state — profiles, sessions, worktrees — is untouched), then run the production `puddle start`, which refetches the daemon from GitHub Releases. (Clearing `bin` is what forces the refetch: the installer skips a version whose files are already present, so a dev build sharing the release's version number would otherwise stay put.)
98
+
99
+ **Uninstall.** Removing the CLI alone leaves the daemon installed and running — a full teardown stops the daemon, then removes its state, its service file, and the production CLI:
100
+
101
+ > ⚠️ `~/.puddle` **is** your local state — the SQLite database with every profile, account, and session (plus conversation history), the daemon's worktree tracking, and the auth token. Deleting it is irreversible and wipes all of it. Uninstall only when you mean to start clean.
102
+
103
+ ```sh
104
+ rm -rf ~/.puddle
105
+ rm ~/Library/LaunchAgents/dev.puddle.puddled.plist # macOS
106
+ rm ~/.config/systemd/user/puddled.service && systemctl --user daemon-reload # Linux
107
+ npm uninstall -g @puddle-code/cli
108
+ ```
109
+
110
+ ## Licence
111
+
112
+ Puddle is licensed under the [MIT License](LICENSE). Copyright (c) 2026 Yiding Song.