@baleen37/ars 1.1.0 → 2.0.0
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 +157 -52
- package/package.json +1 -1
- package/vendor/ars-darwin-arm64 +0 -0
- package/vendor/ars-linux-amd64 +0 -0
- package/vendor/ars-linux-arm64 +0 -0
package/README.md
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
# ars
|
|
2
2
|
|
|
3
|
-
`ars`
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
`ars` is a full-screen Claude Code and Codex session navigator for the current
|
|
4
|
+
computer and explicitly configured SSH peers. Selecting a row creates or
|
|
5
|
+
attaches to a provider process in an ARS-owned tmux server. `Ctrl+Q` detaches
|
|
6
|
+
the terminal client, keeps that provider process alive on its original host,
|
|
7
|
+
and returns to the same refreshed TUI.
|
|
8
|
+
|
|
9
|
+
ARS is one local Go binary. Peers need no `ars` install, daemon, database,
|
|
10
|
+
cache, index, or background helper. Collection uses a private, one-shot,
|
|
11
|
+
version-matched ARS/2 helper over the user's existing OpenSSH configuration.
|
|
7
12
|
|
|
8
13
|
## Install
|
|
9
14
|
|
|
@@ -22,11 +27,13 @@ Prerequisites:
|
|
|
22
27
|
|
|
23
28
|
- Go as declared by `go.mod`, for building from source
|
|
24
29
|
- OpenSSH `ssh` locally and an OpenSSH-compatible server on each remote host
|
|
25
|
-
- `
|
|
30
|
+
- `tmux` on every managed computer, including the current one
|
|
26
31
|
- a POSIX `/bin/sh` plus `uname`, `mkdir`, `cat`, `chmod`, `rm`, and `rmdir` on
|
|
27
32
|
each remote host
|
|
28
|
-
- `claude` and/or `codex` on
|
|
29
|
-
|
|
33
|
+
- `claude` and/or `codex` on each node's `PATH`, with native session metadata
|
|
34
|
+
under that user's home directory
|
|
35
|
+
|
|
36
|
+
`fzf` is not used or required.
|
|
30
37
|
|
|
31
38
|
Build the three collector assets and the local executable:
|
|
32
39
|
|
|
@@ -40,11 +47,14 @@ local `ars` build: `darwin/arm64`, `linux/amd64`, and `linux/arm64`. Generated
|
|
|
40
47
|
collector blobs and the root `ars` build artifact are local build outputs and
|
|
41
48
|
must not be committed.
|
|
42
49
|
|
|
43
|
-
##
|
|
50
|
+
## Localhost and remote inventory
|
|
44
51
|
|
|
45
52
|
The default inventory is `${XDG_CONFIG_HOME}/ars/hosts` when
|
|
46
|
-
`XDG_CONFIG_HOME` is set, otherwise `~/.config/ars/hosts`.
|
|
47
|
-
|
|
53
|
+
`XDG_CONFIG_HOME` is set, otherwise `~/.config/ars/hosts`. The current computer
|
|
54
|
+
is always included as `localhost`; it requires no configuration. The hosts file
|
|
55
|
+
contains only OpenSSH peers. A missing hosts file is a valid local-only
|
|
56
|
+
configuration. Put one peer target on each line, in the order it should be
|
|
57
|
+
reported:
|
|
48
58
|
|
|
49
59
|
```text
|
|
50
60
|
# ~/.config/ars/hosts
|
|
@@ -53,35 +63,71 @@ deploy@example.internal
|
|
|
53
63
|
agent-mac
|
|
54
64
|
```
|
|
55
65
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
66
|
+
`ars localhost` opens only current-computer sessions. `localhost` is reserved
|
|
67
|
+
and cannot be added with `ars remote add`.
|
|
68
|
+
|
|
69
|
+
When upgrading an existing installation, read the exact value from its
|
|
70
|
+
`${XDG_CONFIG_HOME}/ars/local-host` file, or `~/.config/ars/local-host` when
|
|
71
|
+
`XDG_CONFIG_HOME` is unset. Remove that exact entry and any literal `localhost`
|
|
72
|
+
entry from `hosts`, leaving only SSH peers. ARS does not read or delete the
|
|
73
|
+
legacy `local-host` file.
|
|
74
|
+
|
|
75
|
+
Blank lines and comments in `hosts` are ignored. Targets may use names and
|
|
76
|
+
aliases from the user's SSH config. Duplicates, whitespace, control characters,
|
|
77
|
+
a leading dash, and targets over 255 bytes make the entire inventory invalid.
|
|
60
78
|
|
|
61
79
|
`ars remote add <host>` creates the inventory and its parent directory when
|
|
62
80
|
missing, preserves existing comments, entries, and order, and rejects invalid
|
|
63
|
-
or duplicate targets.
|
|
64
|
-
|
|
81
|
+
or duplicate targets. It also rejects the reserved `localhost` target. A target
|
|
82
|
+
beginning with `#` is rejected because inventory loading would interpret it as
|
|
83
|
+
a comment. The command does not edit `~/.ssh/config`.
|
|
65
84
|
|
|
66
85
|
## Commands
|
|
67
86
|
|
|
68
87
|
The supported command forms are:
|
|
69
88
|
|
|
70
89
|
```sh
|
|
71
|
-
ars # search
|
|
72
|
-
ars
|
|
90
|
+
ars # search localhost and every configured SSH peer
|
|
91
|
+
ars localhost # search only current-computer sessions
|
|
92
|
+
ars devbox # search one configured SSH peer
|
|
73
93
|
ars list --json # return all hosts, sessions, and errors as JSON
|
|
74
94
|
ars remote add devbox # add an SSH target to the ARS inventory
|
|
75
95
|
ars --help # show all command forms
|
|
76
96
|
ars remote --help # show remote command help
|
|
77
97
|
```
|
|
78
98
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
99
|
+
`ars` and `ars <host>` require a TTY. Use `ars list --json` for a headless,
|
|
100
|
+
one-shot result.
|
|
101
|
+
|
|
102
|
+
## TUI
|
|
103
|
+
|
|
104
|
+
The screen has one line per session:
|
|
105
|
+
|
|
106
|
+
```text
|
|
107
|
+
state | title | provider | location | project | runtime | activity age
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The location column is blank for current-computer sessions and shows the
|
|
111
|
+
configured SSH target for peers.
|
|
112
|
+
|
|
113
|
+
`Active` contains ARS-owned runtimes: `attached(n)` has one or more terminal
|
|
114
|
+
clients and `running` has none. `Recent` contains saved provider histories with
|
|
115
|
+
no ARS runtime. The footer shows the selected row's full CWD, native ID, and
|
|
116
|
+
exact update time. Search is a Unicode-aware, case-insensitive substring match;
|
|
117
|
+
there is no fuzzy ranker.
|
|
118
|
+
|
|
119
|
+
Keys:
|
|
120
|
+
|
|
121
|
+
- `Up`, `Down`, `j`, `k`: move
|
|
122
|
+
- `/`: search
|
|
123
|
+
- `Enter`: start or attach
|
|
124
|
+
- `r`: refresh
|
|
125
|
+
- `q`, `Ctrl+C`: quit ARS
|
|
126
|
+
- `Ctrl+Q`: detach only while inside an attached ARS tmux client
|
|
127
|
+
|
|
128
|
+
The screen collects at startup, on `r`, and after attach returns. It does not
|
|
129
|
+
poll, watch, or cache in the background. Canonical host/provider/native-ID data,
|
|
130
|
+
never rendered row text, determines the attach command.
|
|
85
131
|
|
|
86
132
|
## Session inclusion
|
|
87
133
|
|
|
@@ -102,6 +148,26 @@ metadata file modification time as `updated_at`, validate canonical UUIDs, and
|
|
|
102
148
|
deduplicate by host, provider, and native ID. A missing executable or metadata
|
|
103
149
|
tree is a healthy absent-provider result, not a host failure.
|
|
104
150
|
|
|
151
|
+
## Persistent provider runtime
|
|
152
|
+
|
|
153
|
+
ARS uses a dedicated versioned, per-user tmux server (`ars-v1`) with
|
|
154
|
+
`-f /dev/null`. It does not use, configure, rename, attach, or bind keys in the
|
|
155
|
+
user's default tmux server. It creates exactly one hashed runtime for the
|
|
156
|
+
selected `(provider, native ID)` and rechecks after a concurrent create instead
|
|
157
|
+
of starting a duplicate provider process.
|
|
158
|
+
|
|
159
|
+
On first selection, ARS starts the adapter's fixed native resume command in the
|
|
160
|
+
saved CWD. Later selections attach that same runtime. `Ctrl+Q` is a prefix-free
|
|
161
|
+
binding in the ARS server and runs `detach-client`; it is not delivered to
|
|
162
|
+
Claude or Codex. When another computer attaches with `ssh -tt`, tmux detaches
|
|
163
|
+
the previous client back to its TUI and hands the same provider process to the
|
|
164
|
+
new client.
|
|
165
|
+
|
|
166
|
+
If the provider exits, its tmux session ends and the native history remains in
|
|
167
|
+
`Recent`. A host reboot or loss of the ARS tmux server ends the live process but
|
|
168
|
+
does not remove native history. ARS does not discover or adopt providers that
|
|
169
|
+
were started outside its own tmux server.
|
|
170
|
+
|
|
105
171
|
## JSON schema version 1
|
|
106
172
|
|
|
107
173
|
Public JSON uses dedicated DTOs and always ends with a newline:
|
|
@@ -110,12 +176,12 @@ Public JSON uses dedicated DTOs and always ends with a newline:
|
|
|
110
176
|
{
|
|
111
177
|
"schema_version": 1,
|
|
112
178
|
"hosts": [
|
|
113
|
-
{"target": "
|
|
179
|
+
{"target": "localhost", "status": "ok"},
|
|
114
180
|
{"target": "down", "status": "error"}
|
|
115
181
|
],
|
|
116
182
|
"sessions": [
|
|
117
183
|
{
|
|
118
|
-
"host": "
|
|
184
|
+
"host": "localhost",
|
|
119
185
|
"provider": "claude",
|
|
120
186
|
"native_id": "123e4567-e89b-42d3-a456-426614174000",
|
|
121
187
|
"updated_at": "2026-07-19T01:02:03Z",
|
|
@@ -130,14 +196,14 @@ Public JSON uses dedicated DTOs and always ends with a newline:
|
|
|
130
196
|
```
|
|
131
197
|
|
|
132
198
|
`schema_version` is `1`. Timestamps are UTC-capable RFC3339Nano strings.
|
|
133
|
-
`hosts` records every selected
|
|
199
|
+
`hosts` records every selected target exactly once. `status=ok` with
|
|
134
200
|
an empty `sessions` array distinguishes a healthy empty host from an
|
|
135
201
|
unreachable host. Stable error codes are `ssh_timeout`, `ssh_failed`,
|
|
136
202
|
`unsupported_target`, `protocol_error`, and `resource_limit`.
|
|
137
203
|
|
|
138
|
-
## SSH and failure behavior
|
|
204
|
+
## SSH and partial-failure behavior
|
|
139
205
|
|
|
140
|
-
Collection and
|
|
206
|
+
Collection and attach deliberately use separate SSH modes:
|
|
141
207
|
|
|
142
208
|
- Collection is non-interactive (`BatchMode=yes`, no agent/X11/port
|
|
143
209
|
forwarding), uses separate probe and upload invocations that each make one
|
|
@@ -145,23 +211,25 @@ Collection and resume deliberately use separate SSH modes:
|
|
|
145
211
|
`StrictHostKeyChecking=yes`, uses a 5-second connect timeout, and gives the
|
|
146
212
|
full probe/upload/protocol flow 60 seconds per host. Unknown hosts fail; ars
|
|
147
213
|
never accepts or rewrites `known_hosts` entries.
|
|
148
|
-
-
|
|
149
|
-
authentication, and
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
214
|
+
- Attach runs `ssh -tt` with the user's normal OpenSSH configuration,
|
|
215
|
+
authentication, and host-key verification. The bounded fixed remote script
|
|
216
|
+
checks or creates the exact ARS tmux runtime, reapplies `Ctrl+Q`, and attaches
|
|
217
|
+
with previous-client detachment. ARS does not weaken host-key checking or
|
|
218
|
+
write SSH configuration.
|
|
153
219
|
|
|
154
220
|
Hosts are collected with at most four workers. One failed host produces a
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
221
|
+
bounded visible error while healthy local and peer sessions remain searchable
|
|
222
|
+
and attachable. A provider or runtime warning is shown beside otherwise healthy
|
|
223
|
+
sessions. If every selected host fails, the TUI still permits refresh and quit;
|
|
224
|
+
JSON mode writes the structured result and exits non-zero. A healthy empty host
|
|
225
|
+
is success. Provider-level corrupt records can yield a warning without
|
|
226
|
+
discarding valid sessions.
|
|
159
227
|
|
|
160
228
|
## Bounds and cleanup
|
|
161
229
|
|
|
162
230
|
Collection is bounded and fail-closed:
|
|
163
231
|
|
|
164
|
-
- 64 KiB startup noise and 64 KiB per ARS/
|
|
232
|
+
- 64 KiB startup noise and 64 KiB per ARS/2 protocol line
|
|
165
233
|
- 16 MiB total collector stdout and 64 KiB diagnostic stderr
|
|
166
234
|
- 10,000 sessions total; provider traversal also caps discovered sessions at
|
|
167
235
|
10,000
|
|
@@ -178,13 +246,16 @@ that exact leftover.
|
|
|
178
246
|
|
|
179
247
|
## Privacy
|
|
180
248
|
|
|
181
|
-
The collector returns validated metadata only: provider, native
|
|
182
|
-
modification time, saved CWD,
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
249
|
+
The private ARS/2 collector returns validated metadata only: provider, native
|
|
250
|
+
UUID, modification time, saved CWD, native title, runtime state, attached-client
|
|
251
|
+
count, and runtime start time. Prompts, responses, tool input or output,
|
|
252
|
+
credentials, raw transcript lines, provider source paths, filenames, pane
|
|
253
|
+
content, and attached terminal output never cross the collection boundary.
|
|
254
|
+
Host diagnostics are bounded and sanitized before display.
|
|
255
|
+
|
|
256
|
+
Public JSON schema v1 deliberately omits all runtime fields and remains the
|
|
257
|
+
provider-history view. Saved CWD and native title are still potentially
|
|
258
|
+
sensitive metadata, so protect JSON output and terminal history accordingly.
|
|
188
259
|
|
|
189
260
|
## Verification
|
|
190
261
|
|
|
@@ -196,20 +267,54 @@ go test ./...
|
|
|
196
267
|
go test -race ./...
|
|
197
268
|
go vet ./...
|
|
198
269
|
go run ./cmd/ars-build
|
|
270
|
+
go test ./internal/runtime -run TestDisposableTmux -count=1 -v
|
|
271
|
+
go test ./internal/tui -run TestPTYAttachDetachRestoresTUI -count=1 -v
|
|
272
|
+
npm test
|
|
273
|
+
git diff --check
|
|
199
274
|
```
|
|
200
275
|
|
|
201
276
|
The ephemeral loopback sshd integration is disposable and opt-in:
|
|
202
277
|
|
|
203
278
|
```sh
|
|
204
|
-
ARS_RUN_SSHD_INTEGRATION=1 go test ./internal/ssh -run
|
|
279
|
+
ARS_RUN_SSHD_INTEGRATION=1 go test ./internal/ssh -run TestEphemeralSSHDCollectsAndAttaches -count=1 -v
|
|
205
280
|
```
|
|
206
281
|
|
|
207
282
|
It generates temporary host/client keys, `authorized_keys`, `known_hosts`, and
|
|
208
|
-
configs,
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
283
|
+
configs, logs, provider fixture, and isolated tmux socket. It verifies strict
|
|
284
|
+
host-key checking, remote create/detach with the same provider PID, and
|
|
285
|
+
second-client handoff without modifying system sshd, persistent SSH state, or
|
|
286
|
+
the default tmux server.
|
|
287
|
+
|
|
288
|
+
### Real two-host acceptance
|
|
289
|
+
|
|
290
|
+
Automated evidence is separate from real-host acceptance. Before release, use
|
|
291
|
+
two genuinely ready hosts with the same ARS build and reciprocal peer
|
|
292
|
+
inventories: host A's `hosts` file contains only host B's configured SSH target,
|
|
293
|
+
and host B's contains only host A's. Neither file lists its own computer.
|
|
294
|
+
|
|
295
|
+
Identity is intentionally observer-relative: a computer is `localhost` to
|
|
296
|
+
itself and its configured SSH target to its peer. Verify:
|
|
297
|
+
|
|
298
|
+
1. Compare the two computers' visible session sets by `(provider, native ID)`,
|
|
299
|
+
not by host label or canonical session key.
|
|
300
|
+
2. On host A, start a local Claude session, press `Ctrl+Q`, and confirm its PID
|
|
301
|
+
remains alive after A returns to its TUI.
|
|
302
|
+
3. From A's TUI, attach to that local Claude runtime so A is actually attached.
|
|
303
|
+
While A is attached, select the same provider and native ID on B under A's
|
|
304
|
+
configured SSH target. Confirm A is forced back to its TUI and B attaches to
|
|
305
|
+
the same runtime and PID.
|
|
306
|
+
4. While B remains attached, select that same local runtime on A again. Confirm
|
|
307
|
+
B is forced back to its TUI and A attaches to the same PID.
|
|
308
|
+
5. Repeat steps 2–4 for a B-hosted Claude runtime, with A and B reversed.
|
|
309
|
+
6. Repeat steps 2–5 for Codex.
|
|
310
|
+
7. Network loss returns to the TUI without killing the provider, and an
|
|
311
|
+
unreachable peer remains visible beside healthy sessions.
|
|
312
|
+
8. The user's default tmux server, configuration, keys, and sessions are
|
|
313
|
+
unchanged.
|
|
314
|
+
|
|
315
|
+
If inventory, SSH, DNS, tmux, or provider readiness is missing, record this
|
|
316
|
+
manual gate as incomplete. Disposable or simulated results are never a real
|
|
317
|
+
two-host pass.
|
|
213
318
|
|
|
214
319
|
## Release
|
|
215
320
|
|
package/package.json
CHANGED
package/vendor/ars-darwin-arm64
CHANGED
|
Binary file
|
package/vendor/ars-linux-amd64
CHANGED
|
Binary file
|
package/vendor/ars-linux-arm64
CHANGED
|
Binary file
|