@vibelord/lanes 1.0.0 → 1.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.
- package/package.json +1 -1
- package/payload/lanes/README.md +92 -7
- package/payload/lanes/VERSION +1 -1
- package/payload/lanes/bin/lanes +928 -150
- package/payload/lanes/client/ghostty/common.conf +3 -0
- package/payload/lanes/client/ghostty/lanes-palette-light.conf +25 -0
- package/payload/lanes/client/ghostty/lanes-palette.conf +25 -0
- package/payload/lanes/client/ghostty/omarchy.conf +3 -2
- package/payload/lanes/client/lanes-launch +62 -5
- package/payload/lanes/client/lanes-window +17 -1
- package/payload/lanes/container/env.sh +8 -0
- package/payload/lanes/container/hooks/claude-settings.json +10 -0
- package/payload/lanes/container/hooks/codex-hooks.json +22 -0
- package/payload/lanes/container/lane +326 -25
- package/payload/lanes/container/lane-signal +173 -0
- package/payload/lanes/docs/ARCHITECTURE.md +158 -6
- package/payload/lanes/docs/DESIGN.md +250 -0
- package/payload/lanes/docs/INSTALL.md +39 -0
- package/payload/lanes/docs/RUNBOOK.md +507 -24
- package/payload/lanes/docs/SHARING.md +1 -1
- package/payload/lanes/holders/exec.sh +2 -5
- package/payload/lanes/holders/ssh.sh +18 -0
- package/payload/lanes/holders.lock +3 -0
- package/payload/lanes/install/enable-phone.sh +15 -6
- package/payload/lanes/install/enable-web.sh +19 -6
- package/payload/lanes/install/host-install.sh +10 -1
- package/payload/lanes/install/services.py +30 -3
- package/payload/lanes/install.sh +108 -3
- package/payload/lanes/libexec/agent_state.py +246 -0
- package/payload/lanes/libexec/connection.py +178 -0
- package/payload/lanes/libexec/cursor_sync.py +147 -6
- package/payload/lanes/libexec/device_sync.py +134 -0
- package/payload/lanes/libexec/economy_poll.py +685 -0
- package/payload/lanes/libexec/guard.py +27 -1
- package/payload/lanes/libexec/lanes_lib.py +436 -36
- package/payload/lanes/libexec/notify.py +317 -0
- package/payload/lanes/libexec/registrations.py +148 -0
- package/payload/lanes/libexec/session_actions.py +53 -22
- package/payload/lanes/libexec/sidebar.py +1190 -186
- package/payload/lanes/libexec/statusd.py +352 -90
- package/payload/lanes/libexec/tokens.py +310 -0
- package/payload/lanes/libexec/tokens.sh +11 -0
- package/payload/lanes/libexec/view.sh +22 -11
- package/payload/lanes/systemd/lanes-economy.service +20 -0
- package/payload/lanes/systemd/lanes-notify.service +19 -0
- package/payload/lanes/systemd/lanes-sync.service +3 -0
- package/payload/lanes/web/README.md +96 -2
- package/payload/lanes/web/browser.css +22 -0
- package/payload/lanes/web/browser.js +73 -0
- package/payload/lanes/web/index.html +2 -1
- package/payload/lanes/web/mobile.css +108 -221
- package/payload/lanes/web/mobile.js +105 -55
- package/payload/lanes/workspaces.example/README.md +9 -3
- package/payload/lanes/zellij/config.kdl +128 -19
- package/payload/manifest.json +7 -3
- package/payload/lanes/libexec/legacy_sessions.py +0 -130
package/package.json
CHANGED
package/payload/lanes/README.md
CHANGED
|
@@ -51,6 +51,12 @@ profile). Ghostty is recommended for a separate window; `lanes-launch` works in
|
|
|
51
51
|
The installer uses an existing SSH key or creates a dedicated one. An administrator authorizes its **public**
|
|
52
52
|
key on the server. Re-run `./install.sh --check` after authorization. Your selected site is remembered.
|
|
53
53
|
|
|
54
|
+
When an ended view was rebuilt on the server, the client probes that state and reconnects
|
|
55
|
+
automatically. The probe's watchdog cancels and reaps its timer when the probe completes;
|
|
56
|
+
a hung probe still times out. This avoids waiting for the watchdog's full ten seconds
|
|
57
|
+
after a successful response. Existing installations receive the fix by re-running the
|
|
58
|
+
client installer after updating their checkout.
|
|
59
|
+
|
|
54
60
|
**Setting up a server:** on a Linux x86_64 Docker host, as the workspace account:
|
|
55
61
|
|
|
56
62
|
```sh
|
|
@@ -70,20 +76,35 @@ The installer starts an empty catalog safely; it does not assume anyone's contai
|
|
|
70
76
|
| Independent second view | `lanes-window 2` |
|
|
71
77
|
| Two or three panes per workspace | `lanes-window w2` / `lanes-window w3` |
|
|
72
78
|
| Switch workspace | Ctrl–Alt–Left / Right |
|
|
73
|
-
| Next or previous lane | Ctrl–Alt–Down / Up, or tap the sidebar |
|
|
79
|
+
| Next or previous lane | Ctrl–Alt–Down / Up (the focused pane moves to the next / previous lane of its workspace; nothing is typed, the focus stays), or tap the sidebar |
|
|
80
|
+
| Plain-ASCII glyphs, light or dark tokens | `lanes-window --ascii`, `lanes-window --light` / `--dark` (remembered per device in `devices/<device>.json`; a running sidebar picks it up within one tick) |
|
|
81
|
+
| Lock the view (every key reaches the lane) | Ctrl–Alt–G, again to unlock; the bar shows LOCKED in red. Ctrl–G itself always reaches the lane (Claude Code's editor key) |
|
|
74
82
|
| Search lanes | Ctrl–Alt–/ |
|
|
75
83
|
| Select a lane for pane 2 or 3 | `2` / `3` in the sidebar of a wide view |
|
|
76
84
|
| Open one lane directly | `lanes-launch lane <lane-id>`; find IDs with `lanes-launch ls` |
|
|
77
|
-
|
|
|
78
|
-
|
|
|
79
|
-
|
|
|
85
|
+
| Read a markdown file a lane mentioned | Ctrl–Alt–M opens a floating **Preview** pane over the focused lane: the `.md` paths it printed in its last 300 lines that exist in its container (relative ones resolved against its working directory). One is shown at once; several give a numbered menu, newest first (Enter = the newest, `q` closes). Rendered by `glow` in the view's dark/light theme (the server installer adds a pinned glow unless the view server's PATH — `~/.local/share/lanes/bin`, the checkout's `bin`, `/usr/local/bin`, `/usr/bin`, `/bin` — already has one; a glow only in `~/.local/bin` or `~/go/bin` does not count), else `less -R`; `lanes doctor` names which (`preview renderer:`); quitting the pager closes the pane |
|
|
86
|
+
| Create a persistent workspace shell | **+ New shell** under **Unregistered** (**New +** on the phone), or `+` in the sidebar |
|
|
87
|
+
| Register an existing session | **+** beside an unregistered session, or select it and press `a`; choose a workspace |
|
|
88
|
+
| See which agents need you | The sidebar sorts **Needs you** (◆ approval, ✗ error, ◇ waiting for a prompt), **Working** (▸) and **Done** (✓, until you open the lane) above the rest; the header counts them in the same glyphs (`◆1 ◇2 ▸6 ✓1`, zeros left out; `N lanes` when no lane runs an agent) |
|
|
89
|
+
| Read a sidebar row | `▌` cursor · agent glyph · `›` the lane this pane shows (`²`/`³`: shown in pane 2/3) · the name (`·` per other viewer, `…` when clipped) · an **age column** on every row (agent turn, else last output: `45s`, ` 3m`, ` 2h`, ` 4d`; amber in **Needs you**) · stream glyph · one tail cell by priority (`?` not observed right now > `⚠` starving: producing output but no request for over 10 min, or a 429 > `↓` downgraded > `$` mostly paid — the economy cells need the opt-in economy poller; a dim `⚠`/`↓` is a frozen last-known figure, not a live alarm) · `×` close. `⋮ N more` ends a list that continues below |
|
|
90
|
+
| End an unregistered session and its jobs | **×** beside the session, or select it and press `x`; confirm with `y` (any other key cancels) |
|
|
91
|
+
| Every sidebar key | `?` replaces the list with the key sheet until the next key (that key only closes it). The footer legend says ` ⏎ open · / find · x close · ? keys`; prompts share one shape (` › close ‘name’? y/n`, ` › Rename: …█`, ` › Register ‘name’? y/n`) and a filter counts its matches (` /abc · 3 matches`) |
|
|
92
|
+
| Jump to the next lane that needs you | `Tab` / `Shift-Tab` in the sidebar (cycles **Needs you** from the lane the pane shows; the pane title carries the counts and a lane that starts needing you raises one OSC 9 desktop notification — `LANES_NOTIFY=0` silences it) |
|
|
93
|
+
| Other workspaces that need you | The row above the footer rule: ` ◆1 Worlds · ◇2 Code` (blank and absent when none; panes of 18 rows or more) |
|
|
94
|
+
| What the fleet spends | With the opt-in economy poller ([RUNBOOK](docs/RUNBOOK.md#economy-projection-opt-in)) the same row is the fleet economy strip instead: ` $8.5k/16k 53% · F2 S1 · spill 76% · free 3/19` — overflow spend against the daily cap (amber at the alert level), new upstream 429s, this workspace's lanes by model tier (`F` fable, `O` opus, `S` sonnet, `H` haiku, `G` gpt), the pool's spill fraction, free accounts and the next 5 h reset, whole parts dropped from the end to fit; a leading `?` means the figures are frozen — the poller could not reach the daemon, or it stopped (no rewrite for over 3 min) |
|
|
95
|
+
| Upload | Click the one-row upload strip above the footer (` ↑ uploads · click, then drop (U)`) or press `U`, then drop anywhere on the window; or use `~/Lanes Uploads/<workspace>/`, or `lanes-upload <files>` |
|
|
80
96
|
| Phone setup from a client | `sh install/enable-phone.sh --host lanes` |
|
|
97
|
+
| Laptop or tablet browser view | `lanes web <device> --desktop [--token]` on the server, or `sh install/enable-phone.sh --host lanes --desktop <device>` ([guide](docs/INSTALL.md#laptop-and-tablet-browser)) |
|
|
98
|
+
| Switch workspace or lane in a laptop browser | The **Lanes** chip (top right) opens the workspace and lane pickers |
|
|
81
99
|
| Detach | Close the window; the agents keep running |
|
|
82
100
|
|
|
83
101
|
Unregistered sessions also appear when they use shared or previously unlisted tmux servers. Reopening a
|
|
84
|
-
session reuses it; closing a view leaves it running. Registered lanes have no **×** control.
|
|
85
|
-
|
|
86
|
-
|
|
102
|
+
session reuses it; closing a view leaves it running. Registered lanes have no **×** control. See the
|
|
103
|
+
[runbook](docs/RUNBOOK.md) for details.
|
|
104
|
+
|
|
105
|
+
**Add to workspace** keeps the session running and moves it into the selected workspace's registered list.
|
|
106
|
+
The picker offers workspaces using the same container. Registration keeps its name and open views, persists
|
|
107
|
+
across sync/reconnects, and removes its close control. On a phone, tap the **+** and a workspace; no typing is needed.
|
|
87
108
|
|
|
88
109
|
On iPhone, open the printed private HTTPS URL in Safari and choose **Share → Add to Home Screen**.
|
|
89
110
|
The interface provides Workspaces, Lanes and Panes controls, safe areas, portrait/landscape layout and adjustable
|
|
@@ -93,6 +114,21 @@ On macOS, allow **Lanes Helper** to read Downloads/Desktop/Documents when prompt
|
|
|
93
114
|
errors are retained; an active large transfer is not cut off by a total-duration timeout. Files are read only
|
|
94
115
|
from allowed folders and land in the selected workspace's `uploads/` directory.
|
|
95
116
|
|
|
117
|
+
### Legend
|
|
118
|
+
|
|
119
|
+
Column 2 of every row says what the agent needs; column 33 says what the terminal is doing; the right edge says how
|
|
120
|
+
long (agent since-time, or last output). Glyph then ASCII twin (`LANES_GLYPHS=ascii`):
|
|
121
|
+
|
|
122
|
+
| Agent (column 2) | | Terminal (column 33) | | Marks |
|
|
123
|
+
| --- | --- | --- | --- | --- |
|
|
124
|
+
| `◆` `!` needs approval | `◇` `?` needs input | `●` `*` output in the last 20 s | `○` `o` quiet | `▌` `\|` cursor · `›` `=` viewing · `²` `2` / `³` `3` shown in viewport 2/3 |
|
|
125
|
+
| `▸` `>` working | `✓` `v` done (until viewed) | `–` `-` no session right now | `!` `!` pane dead | `·` `.` viewers · `…` `~` clipped · `×` `x` close |
|
|
126
|
+
| `✗` `X` errored | `_` `_` shell · `·` `.` idle | `✗` `x` container down | `?` `?` not observed · `·` `.` helper | `⋮` `:` more rows · `↑` `^` uploads · `↓` `v` drop now |
|
|
127
|
+
|
|
128
|
+
Column 34 is one tail cell: `?` stale (last known state shown) > `⚠` `!` starving > `↓` `v` downgraded > `$` mostly
|
|
129
|
+
paid. Colour is reinforcement, never the only signal; `LANES_COLOR=none` keeps every glyph. Full tables, tokens and
|
|
130
|
+
modes: [`docs/DESIGN.md`](docs/DESIGN.md).
|
|
131
|
+
|
|
96
132
|
## Share with your team
|
|
97
133
|
|
|
98
134
|
Throttle's **Shared lanes** console provides an SSO-protected, read-only overview
|
|
@@ -103,10 +139,18 @@ platform/Host version, configuration, access rules and output limits.
|
|
|
103
139
|
## Screenshots
|
|
104
140
|
|
|
105
141
|
**Desktop:** workspace tabs, registered and unregistered lanes, and uploads alongside the active terminal.
|
|
142
|
+
Captured before v2: the v2 sidebar shows attention sections, an agent glyph per row, the age column and a one-row
|
|
143
|
+
upload strip (see [docs/DESIGN.md](docs/DESIGN.md)). It also adds one economy tail cell per lane (column 34: `?` >
|
|
144
|
+
`⚠` > `↓` > `$`) and, with the opt-in economy poller, the fleet economy strip above the footer rule. The image is
|
|
145
|
+
user-supplied and not regenerated.
|
|
106
146
|
|
|
107
147
|

|
|
108
148
|
|
|
109
149
|
**iPhone in Safari:** the lane picker and touch controls for workspaces, panes, and explicit text input.
|
|
150
|
+
Captured before v2: the v2 sidebar shows attention sections, an agent glyph per row, the age column and a one-row
|
|
151
|
+
upload strip (see [docs/DESIGN.md](docs/DESIGN.md)). On the phone the picker gives each lane three rows (name,
|
|
152
|
+
status and age, the agent's task) without the upload strip, and view tabs gain the quick-key row; the image is not
|
|
153
|
+
regenerated.
|
|
110
154
|
|
|
111
155
|
<img src="docs/images/iphone.png" alt="Lanes on iPhone in Safari, showing the lane picker and Workspaces, Lanes, Panes, and Type here controls" width="360">
|
|
112
156
|
|
|
@@ -119,6 +163,8 @@ It retains the previous lanes if a repository's registry is temporarily invalid.
|
|
|
119
163
|
`lanes cursor-sync --diff` previews editor integration. `lanes cursor-sync --write` backs up and normalizes
|
|
120
164
|
terminal commands to `lane open <id>`, retaining each original create recipe. Cursor and Lanes then attach
|
|
121
165
|
to the same terminal. Registry sync does not copy repositories between machines or automatically create agents.
|
|
166
|
+
Sessions added through the picker are saved in the site's `registered-sessions.json` and included by sync.
|
|
167
|
+
These registrations attach to existing sessions; they do not invent a restart command or edit editor terminal lists.
|
|
122
168
|
See [workspace configuration](workspaces.example/README.md) and the [architecture](docs/ARCHITECTURE.md).
|
|
123
169
|
|
|
124
170
|
## What is included
|
|
@@ -150,3 +196,42 @@ python3 -m unittest discover -s tests/unit # no Docker or live server needed
|
|
|
150
196
|
|
|
151
197
|
For integration tests and browser verification, see [tests/README.md](tests/README.md).
|
|
152
198
|
For recovery, service updates and troubleshooting, see the [runbook](docs/RUNBOOK.md).
|
|
199
|
+
|
|
200
|
+
### Register a workspace once
|
|
201
|
+
|
|
202
|
+
The host's site catalog (`LANES_WORKSPACES/catalog.json`, normally
|
|
203
|
+
`~/.config/lanes/workspaces/catalog.json`) is the workspace authority. Add its
|
|
204
|
+
manifest there and run `lanes sync`. The existing sync timer refreshes it every
|
|
205
|
+
2 minutes; the ensure timer also reconciles known device sessions every minute.
|
|
206
|
+
New desktop and phone tabs appear without rebuilding sessions or restarting
|
|
207
|
+
agents. Changing a catalog title renames the existing tab using its workspace ID.
|
|
208
|
+
Phone workspaces receive both their full-width picker and terminal tabs.
|
|
209
|
+
When a device has no attached client, new tabs wait for its next connection and
|
|
210
|
+
the next ensure tick (within a minute). This avoids empty background tabs in
|
|
211
|
+
Zellij 0.45.1; existing workspace names can still update while disconnected.
|
|
212
|
+
|
|
213
|
+
Fixed terminals on another host can use an optional `sshWorkspaces` entry:
|
|
214
|
+
|
|
215
|
+
```json
|
|
216
|
+
{
|
|
217
|
+
"id": "maintenance",
|
|
218
|
+
"title": "Maintenance",
|
|
219
|
+
"host": "maintenance-views",
|
|
220
|
+
"command": "/home/operator/.local/bin/workspace-session",
|
|
221
|
+
"layout": "lanes",
|
|
222
|
+
"position": "workspace",
|
|
223
|
+
"panes": [{"id": "fixes", "name": "Fixes"}]
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Put this object in the catalog's `sshWorkspaces` array. Configure the host SSH
|
|
228
|
+
alias with its dedicated key and pinned host key. The command must attach to an
|
|
229
|
+
existing persistent session. Lanes does not provision or terminate remote agents.
|
|
230
|
+
`layout: "lanes"` uses the standard sidebar; `position: "before-host"` places a
|
|
231
|
+
control workspace immediately before Host. Existing `split` layouts stay supported.
|
|
232
|
+
Split workspaces can share an SSH host and helper when their pane IDs are distinct.
|
|
233
|
+
An endpoint assigned to multiple split workspaces is ambiguous and refuses sync.
|
|
234
|
+
|
|
235
|
+
While a viewer connects or reconnects, it shows a Syncing indicator and discards
|
|
236
|
+
pending input. Mouse reporting is reset before and after the attach client, so
|
|
237
|
+
queued escape sequences cannot become shell input during the connection wait.
|
package/payload/lanes/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.2
|