@puddle-code/cli 0.0.1 → 0.0.2

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 +51 -0
  2. package/README.md +78 -0
  3. package/dist/index.js +758 -155
  4. package/dist/install.sh +8 -0
  5. package/dist/public/assets/Dashboard-CcpYaLlK.js +1 -0
  6. package/dist/public/assets/EditorTabClose-Dal7HKgg.js +1 -0
  7. package/dist/public/assets/ModelRefcount-B12_Xdv2.js +1 -0
  8. package/dist/public/assets/PaneEditorBody-D1npLlye.js +1 -0
  9. package/dist/public/assets/SettingsDialog-Cp_1M1k7.js +1 -0
  10. package/dist/public/assets/{Terminal-CuEf-GeX.js → Terminal-D03wYX9q.js} +2 -2
  11. package/dist/public/assets/Workspace-d0mqka1w.js +6 -0
  12. package/dist/public/assets/api-DnhKCI2U.js +73 -0
  13. package/dist/public/assets/buffer-logic-BrpRsL1b.js +1 -0
  14. package/dist/public/assets/buffer-store-CJsO7gGE.js +16 -0
  15. package/dist/public/assets/context-menu-BWOPZx3M.js +1 -0
  16. package/dist/public/assets/createLucideIcon-DyMAgLa3.js +1 -0
  17. package/dist/public/assets/cssMode-D1iXtOo8.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-DHG9ShX4.js +1 -0
  23. package/dist/public/assets/htmlMode-CBFRVNoG.js +1 -0
  24. package/dist/public/assets/index-BcSTVRMs.js +10 -0
  25. package/dist/public/assets/index-D9uQqhHq.css +2 -0
  26. package/dist/public/assets/{jsonMode-BijgXT6I.js → jsonMode-CpQhQE0R.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-C_dNI0ql.js +1 -0
  30. package/dist/public/assets/switch-RkFdxF0W.js +1 -0
  31. package/dist/public/assets/{tsMode-B7q3gz7a.js → tsMode-ET2kHbb0.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,51 @@
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.2] — 2026-07-15
11
+
12
+ ### Added
13
+
14
+ - The npm page for **`@puddle-code/cli`** now renders this repository's `README.md` and links back to the repo — the package gains `homepage`, `repository`, and `bugs` fields, and the build copies the root README into the package at publish time (npm only renders a README that sits in the package directory). The README gains an npm version badge and a licence badge.
15
+ - Profiles can now be **renamed** in Settings → Profile — the Name field is editable (previously read-only). The name is a display label that keys nothing on disk (directories are id-keyed), so a rename touches no files; it stays letters/digits/dot/underscore/hyphen and must be unique (a clash is rejected). `PATCH /api/profiles/:id` now accepts an optional `name` alongside `branch_prefix` (additive; `PROTOCOL_VERSION` minor bump) — SPEC §6.
16
+ - The right sidebar now shows **every project's sessions**, grouped by project (a header per project when expanded, a divider between groups on the collapsed rail), with the project order inheriting the homescreen's — clicking a session jumps into its own project. A per-browser toggle (Settings → Appearance, on by default) reverts to the current-project-only view. The list scrolls without a visible scrollbar so a long list still works while the new-terminal/new-session controls stay fixed, and a collapsed dot's tooltip now shows the session name over its branch. New query `GET /api/sessions?profile=…` (SPEC §12).
17
+ - Homescreen projects can now be **renamed**, **archived**, and **reordered**. Hover a card (or right-click it) for rename/archive; archiving is a reversible hide — the project drops into a collapsed "Archived" disclosure at the bottom, keeping every session and worktree, and reopening restores it. Drag cards to reorder (newest first until dragged); the order persists per profile (`profileSettings.projectOrder`) and the cross-project session sidebar inherits it. New endpoint `PATCH /api/projects/:id {name?, archived?}` + `projects.archived` column (migration 011; additive `PROTOCOL_VERSION` minor bump) — SPEC §11.
18
+ - The workspace centre is now a **free-form tiling area** (SPEC §8): editor tabs (files, diffs, media) and agent terminals share one space — drag any tab onto a pane to reorder it, or onto a pane's edge to split it into an arbitrary grid of resizable panes (VSCode editor-groups style). Terminals stay mounted and their DOM is adopted into whichever pane shows them, so moving one never drops its PTY/scrollback; the same file may open in two panes sharing one editor model. The layout persists as a recursive tree in `ui_state.layout_tree` (legacy layouts migrate automatically; additive `PROTOCOL_VERSION` minor bump).
19
+ - Cmd/Ctrl+click now opens more terminal paths: extensionless directories and files with path structure (`.worktrees/hil-demos`, `~/.claude/prompts/up-fix`, `/home/bios/waddle`), not just paths ending in a recognised extension. A leading `@` (Claude Code's file-ref syntax) is stripped. The daemon's `/resolve` check still gates underlining (SPEC §7).
20
+ - macOS copy/paste in terminals: **⌘C** copies the terminal's selection to the clipboard (`Ctrl-C` stays the interrupt), and **⌘V** pastes. Only on Mac clients (SPEC §7).
21
+ - The file explorer is now VSCode-grade (SPEC §8): git decorations (a status colour + one-letter badge — **U**ntracked/**M**odified/**A**dded/**D**eleted/**R**enamed/**C**onflict, git-ignored files greyed, folders tinted by their most-significant descendant), colourful per-type file icons, rich right-click menus on files, folders and empty space, a cut/copy/paste clipboard with drag-to-move, multi-select (⌘/⇧-click), full arrow-key navigation with type-to-jump, inline create/rename with a delete confirmation, and a header utility bar (New File · New Folder · Refresh · Collapse Folders) whose branch title eases sideways on hover to reveal the tail the icons occlude. Backed by new daemon endpoints — `GET /git-status` and `POST /create|/rename|/copy|/delete` on `/api/worktrees/:sid`, every path confined to the worktree (additive; `PROTOCOL_VERSION` minor bump).
22
+ - Images, video, audio and PDFs now open as an inline preview tab instead of the "Binary — use Download" fallback. A new `GET /api/worktrees/:sid/media` streams the file with its real content-type (`image/*`, `video/*`, `audio/*`, `application/pdf`) and an `inline` disposition; the viewer fetches it through the authed API and renders from an object URL, so no token ever rides in an element `src`. Unknown binaries keep the download fallback (SPEC §8; additive `PROTOCOL_VERSION` minor bump).
23
+ - The file editor gained VSCode keybindings: **⌥Z** toggles line wrap (it flips the `editorWordWrap` client setting, so every open editor follows and the choice persists). ⌘/Ctrl+S still saves; Monaco's stock multi-cursor / comment / find bindings are unchanged (SPEC §8).
24
+ - Right-click a session — its sidebar row, its collapsed status dot, or its tab in the top strip — to open the same kill / resume / rename / archive / move menu as the row's ellipsis (SPEC §12).
25
+ - Settings → **Sessions** (renamed from Permissions & Safety) now edits the launch-text templates an agent receives when it starts a freshly created worktree (`{{rules}}` injects the repo's onboarding notes) or joins an existing/shared one. Either template may be cleared to send no preamble, or reset to the built-in default (SPEC §4).
26
+ - Archived sessions are no longer hidden away: they collapse under an **Archived** header at the bottom of the sessions sidebar and reopen (view-only, to read their terminal history) — archiving is not deletion (SPEC §4).
27
+ - `puddle start` and `puddle connect` now run the cockpit **in the background** once ready: the command bootstraps interactively (ssh prompts still land on your terminal), detaches, prints the URL, and exits — the terminal may close. `--foreground` keeps the old attached behaviour. New commands: `puddle list` shows running cockpits (verified by pid + a per-instance nonce the UI server echoes as `X-Puddle-Cockpit`, never by reachability alone) and `puddle kill [local | user@host | --all]` stops one — sessions keep running on the host. Cockpit records live in `~/.puddle/cockpits/`, background logs in `~/.puddle/logs/cockpit-<target>.log` (SPEC §10).
28
+
29
+ ### Changed
30
+
31
+ - **Protocol major bump 5.9 → 6.0**, on purpose and with no schema shape change: a major mismatch makes every connected CLI auto-upgrade its daemon on the next handshake, so this release forces every host onto the new daemon (`packages/shared/src/protocol.ts`; PROTOCOL.md, "The rule").
32
+ - GitHub release notes are now taken from the release's changelog (`docs/changelogs/CHANGELOG-v<version>.md` via `scripts/extract-changelog.mjs`) instead of being auto-derived from commits, and `@puddle-code/cli` now ships that same changelog as its `CHANGELOG.md` — one changelog drives the release notes and the npm package.
33
+ - The Worktrees navigator's status badges are terser, matching VSCode: a dirty worktree shows a yellow **M** (the explorer's modified-decoration colour) instead of "uncommitted", and a worktree with live sessions shows a green count (e.g. **3**) instead of "3 running". Both keep the full text on hover.
34
+ - The top bar is slimmer — a shorter header with a smaller mark sized inline with the title — reclaiming vertical space for the workspace.
35
+ - The daemon no longer crashes (or crash-loops under its supervisor) when its configured port is already in use: it now **falls back to an OS-assigned free port** and records where it actually bound in `~/.puddle/runtime.json`. `puddle connect`/`start` discover the daemon from that file (falling back to `config.json`, then 7434), always revalidating by token, so a busy 7434 no longer breaks a connection. Every start still prefers the configured port, so the daemon returns to it once the conflict clears (SPEC §10).
36
+ - A session's default display name is now the agent's own session name (for Claude Code, the transcript's ai-title / agent-name — what its resume picker shows) instead of the leading hex block of the puddle session id. A user rename still overrides it, and clearing the rename reverts to the agent's name (then the id). This retires the `.puddle/session-title` marker file, which could not work once several agents shared one worktree. Additive protocol change: the `sessions.agent_title` field and the `renamed` WS event's `agent_title` (`PROTOCOL_VERSION` minor bump).
37
+ - Releases no longer publish a `darwin-x64` daemon tarball: GitHub's last Intel Mac runner (`macos-13`) queues so long it blocked the whole release. Intel Mac hosts are unsupported until the entry is restored (or built under Rosetta); Apple-silicon Macs and Linux are unaffected.
38
+
39
+ ### Fixed
40
+
41
+ - Client-side navigation now updates the view immediately instead of only after a page reload. react-router v7+ wraps every location update in `React.startTransition` by default, so under React 19 clicking a session, creating one, or clicking the logo changed the URL synchronously while the matched route stayed deferred as a pending transition — the view appeared frozen until a reload. The router is now mounted with `useTransitions={false}`, making navigation an urgent, synchronous update.
42
+ - Clicking a file (editor) tab that shares a pane with the bound session's terminal no longer flips straight back to the terminal. The workspace's deep-link effect — which ensures and focuses the URL session's terminal — was keyed on the ui-state handle, a fresh object every render, so it re-ran on **every** re-render (each agent status tick, each keystroke) and kept re-asserting the terminal as the pane's active tab. It now fires once per genuine session navigation, so a file tab you open stays open and a new tab/session lands in the currently focused pane rather than being yanked to the session's terminal (SPEC §8).
43
+ - Account login (and agent spawning generally) failed when the agent CLI lived in a dir the supervisor's bare PATH omits — notably Claude Code's native-installer `~/.local/bin`, which launchd's `/usr/bin:/bin:/usr/sbin:/sbin` doesn't include: the daemon couldn't find `claude`, so the login terminal was blank and accounts read as logged-out. The install now bakes a richer PATH into the systemd unit and launchd plist, and the daemon prepends `config.json`'s new `agentPath` (default covers `~/.local/bin`, `~/bin`, Homebrew, `/usr/local/bin`; editable in Settings → Terminal & editor) to its PATH at boot. Additive `PROTOCOL_VERSION` minor bump (SPEC §5, §10).
44
+ - A remote `puddle connect` no longer risks making a later local `puddle start` report a spurious port conflict. Its UI server was told to avoid the *remote* daemon's port when auto-picking, but the port a local `start` actually probes is *this* machine's daemon port — the two coincide only when the remote daemon runs on the default 7434. A connect cockpit's proxy could therefore land on the local daemon's port and be mistaken for it. The avoided port is now discovered from this machine the same way `start` finds its own daemon, so they can never collide (SPEC §10).
45
+ - "Skip permission prompts" now actually skips them for Claude Code. The `--dangerously-skip-permissions` flag was delivered correctly but Claude 2.1.x silently downgraded it to normal prompts because its bypass-mode disclaimer had never been accepted in puddle's managed config dir (that acceptance is only offered interactively, which a non-interactive PTY can't do). Opening the profile skip gate — the existing typed-confirmation dialogue in Settings → Sessions — now records that acceptance (`bypassPermissionsModeAccepted`) for the profile's skip-capable accounts, as does opting an individual account in afterwards, so the flag takes effect. Verified against Claude Code 2.1.210.
46
+ - Renaming a session now sticks. The `.puddle/session-title` marker sync used to re-apply the agent's on-disk title over a UI rename on the next `.puddle` change; that title mechanism is gone, so a rename persists.
47
+ - Proxied apps with absolute asset paths (any Vite/CRA-style build) no longer render a blank page through `/proxy/<sid>/<port>/`. Their `/assets/…` and `fetch('/api/…')` requests used to escape the proxy prefix and receive puddle's own `index.html` (the "Failed to load module script … MIME type of text/html" console error); the cockpit origin now 307-redirects any stray request whose `Referer` is a proxied page back under that page's prefix, and the static handler 404s missing assets instead of SPA-falling-back to HTML. WS handshakes and `no-referrer` apps still need the per-port `ssh -L` fallback (SPEC §9, §15.5 resolved).
48
+ - A request with a malformed percent-escape (e.g. `/100%_done.png`) no longer crashes the whole cockpit process: the static handler answers 404 instead of letting `decodeURIComponent` throw through the request listener.
49
+ - `puddle connect` no longer loops "tunnel lost — reconnecting… / tunnel restored". Three causes: the ssh forward ran with no keepalives, so idle NAT/firewall timeouts felled it on every quiet spell (`ServerAliveInterval=15`/`ServerAliveCountMax=3` on every ssh spawn now); a forward child killed after a failed readiness probe re-triggered the exit handler and spawned a second reconnect loop racing the first; and every sub-second blip printed a lost/restored pair (outages healing within a 2s grace window are now silent, unless the tunnel is genuinely flapping — a drop within 30s of a restore — which announces immediately). The forward also runs with `ExitOnForwardFailure=yes` so a failed `-L` bind dies visibly.
50
+ - `puddle start` can no longer be fooled by another cockpit's UI server sitting on the daemon's port. The UI server never auto-picks the daemon's own port (a `puddle connect` launched while 7433 was busy used to land exactly on 7434), and the daemon probe now verifies identity — only a 200 with this host's token counts; a 401/403 is reported as a clear port conflict instead of "token rejected" (or, worse, silently wiring the local cockpit to a remote daemon). A state directory without a managed install now bootstraps one rather than refusing (`start`/`connect` promise a running daemon — SPEC §10; the existing db/token/worktrees are untouched).
51
+ - The CLI build wipes `dist/` before bundling, so the published npm package can no longer pick up leftovers from earlier builds (v0.0.1 shipped three stray tsc artefacts from the pre-Phase-6 stub this way); the `bin` path is normalised to the form npm was auto-correcting at publish time. No protocol change.
package/README.md ADDED
@@ -0,0 +1,78 @@
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
+ ## Licence
77
+
78
+ Puddle is licensed under the [MIT License](LICENSE). Copyright (c) 2026 Yiding Song.