@ashrlabs/ashr 0.0.0-stage → 0.2.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.
Files changed (3) hide show
  1. package/README.md +338 -2
  2. package/dist/ashr.js +735 -0
  3. package/package.json +50 -4
package/README.md CHANGED
@@ -1,3 +1,339 @@
1
- # Temporary Holding Version
1
+ # ashr
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ The Ashr terminal for post-training models. The npm package is `ashr init`, which
4
+ connects a Docker host (your laptop or a cloud VM) and your ChatGPT plan to your Ashr
5
+ workspace, and the terminal to the hosted agent. The agent, its harness and its
6
+ built-in skills run on Ashr's side and are not in the package. The local agent
7
+ described below is in source and `ASHR_LOCAL=1 npm run build` builds only.
8
+
9
+ ## Install
10
+
11
+ ```
12
+ npm i -g @ashrlabs/ashr # then run: ashr init, then ashr
13
+ ```
14
+
15
+ The npm package needs Node 22.19 or newer. To build a standalone executable from
16
+ this checkout, use an official Node binary with single executable support
17
+ (Homebrew's Node does not provide it):
18
+
19
+ ```sh
20
+ cd cli
21
+ npm ci
22
+ ASHR_SEA_NODE=/path/to/official/node npm run build:binary
23
+ ```
24
+
25
+ `ASHR_SEA_NODE` defaults to the Node running the build. The build targets that
26
+ binary's platform and architecture and writes `dist-bin/ashr-<platform>-<arch>`.
27
+ Copy that executable into a directory on your `PATH` as `ashr`; it bundles the
28
+ Node runtime, JavaScript dependencies and subscription sign-in flows, so no
29
+ separate Node installation is needed to run it. Optional native clipboard and
30
+ image helpers are excluded. macOS builds also require `codesign`.
31
+
32
+ `ashr update` reruns the public install script into the directory of the running
33
+ binary (through symlinks), replacing it in place; restart ashr afterwards. It
34
+ refuses on npm or source installs, which update through npm or git. In a running
35
+ session, `/update` does the same and shows the installer's output. The binary
36
+ checks at most once a day whether the latest build's checksum differs from the
37
+ one the installer recorded, and if so shows a one-line notice at startup; a
38
+ failed check is silent.
39
+
40
+ Both the local agent and hosted workspace use the same TUI components: tool
41
+ arguments, highlighted code, file diffs, live command output and Markdown
42
+ subagent reports. Ctrl-T hides or shows reasoning. Ctrl-O expands or collapses
43
+ the most recently completed tool output or subagent report.
44
+
45
+ ## Hosted Manifold
46
+
47
+ The npm package always reaches Ashr's hosted workspace, where plain `ashr`
48
+ opens it (no `--hosted` needed). The standalone binary reaches it only when
49
+ built with `ASHR_HOSTED=1`; otherwise it uses these commands only against a
50
+ [self-hosted server](#self-hosted-server).
51
+
52
+ ```
53
+ ashr --hosted sign in (first run only) and open the hosted workspace
54
+ ashr --hosted -c reopen the most recently updated hosted chat
55
+ ashr --task support select a task
56
+ ashr --task support --chat ID open the same chat as the browser
57
+ ashr --service require MANIFOLD_API_KEY or a saved key; never opens a browser
58
+ ashr login sign in through the browser and exit
59
+ ashr login --key ask_… save a service key instead
60
+ ashr logout forget the saved sign-in
61
+ ```
62
+
63
+ On first launch `ashr --hosted` (or `ashr login`) opens the dashboard's `/terminal` page. Sign in, pick
64
+ the organization, and click **Connect terminal**. The dashboard mints a key for
65
+ this terminal (labelled `Terminal · <hostname>` under API keys) and hands it
66
+ back once to a loopback listener. The terminal saves it to
67
+ `~/.ashr/credentials.json` (mode 600), and you can close the tab. Later hosted
68
+ launches reuse the saved key; outside the npm package, plain `ashr` starts the local agent.
69
+ If the key is revoked, a hosted launch asks you to sign in again. If the browser
70
+ doesn't open, use the printed URL.
71
+
72
+ `--api-url`/`MANIFOLD_API_URL` and `--dashboard-url`/`MANIFOLD_DASHBOARD_URL`
73
+ select matching deployments. `MANIFOLD_API_KEY` or `--key` override the saved
74
+ sign-in.
75
+
76
+ `/account` shows who the terminal is signed in as. `/org` opens organization
77
+ settings in the browser. `/login` signs in again (for example to switch
78
+ organization) and clears the old task/chat selection. `/logout` forgets the
79
+ saved key.
80
+
81
+ `/github` opens GitHub's fine-grained token form to connect a repository for
82
+ cloning, branch pushes and pull requests. Select the repository, generate the
83
+ token and paste it into the terminal prompt. `/github off` removes the agent's
84
+ access; revoke the token in GitHub to invalidate the token itself.
85
+
86
+ A hosted launch opens the chat selected with `--chat ID`, or the most recently
87
+ updated chat in scope with `--continue` (`-c`). Otherwise the first message
88
+ starts a new chat named after its first line. `--chat` and `--continue` cannot
89
+ be combined. `/chats` opens a searchable picker; `/model`, `/thinking` and
90
+ `/fork` without arguments also open pickers.
91
+
92
+ Use `/help` for the complete command reference. Hosted controls include:
93
+
94
+ - `/tasks`, `/task NAME`, `/chats SEARCH`, `/new NAME`, `/open ID`, `/rename NAME`, `/fork NAME [SEQ]`.
95
+ - `/model PROVIDER/MODEL`, `/thinking LEVEL`, `/compact`, `/steer TEXT`, `/next TEXT`, `/queue`, `/stop`, `/approve ID`, `/reject ID`.
96
+ - `/files`, `/view PATH`, `/diff PATH`, `/download PATH LOCAL_FILE`, `/export LOCAL_FILE`.
97
+ - `/skills`, `/skill import LOCAL_FOLDER`, `/skill toggle NAME`, `/skill invoke NAME`, `/memory QUERY`.
98
+ - `/pipelines`, `/sources`, `/datasets`, `/evals`, `/benchmarks`, `/experiments`, `/models`, `/monitoring`, `/interactions`, `/uploads`, `/artifacts`, `/serving`, `/sdk`.
99
+
100
+ Hosted `!COMMAND` runs in the hosted workspace; `!!COMMAND` excludes its output
101
+ from model context.
102
+ Escape stops active hosted work or pauses a local transfer.
103
+ Ctrl-C stops active hosted work; when idle it disconnects. `/quit` disconnects
104
+ while leaving hosted jobs running. `/pending` and `/retry` recover uncertain
105
+ submissions without changing their request IDs. A busy-chat `409 Chat changed`
106
+ response is retried automatically with the same request ID. Upload receipts support resume.
107
+
108
+ Dashboard writes require the command's explicit `--confirm` flag. The terminal
109
+ covers serving, training and evaluation environments. Organization, member and
110
+ API-key administration stay in the dashboard; `/org` opens it.
111
+
112
+ ## Your own machines
113
+
114
+ To have the Ashr agent work on your own Docker host (your repo, data, checkpoints
115
+ and GPUs stay there), run this on that host; it needs no ashr CLI:
116
+
117
+ ```
118
+ curl -fsSL https://api.manifold.ashr.io/v1/runner/install.sh | ASHR_API_KEY=ask_… sh
119
+ ```
120
+
121
+ or, with the CLI installed:
122
+
123
+ ```
124
+ ashr init # uses ASHR_API_KEY, your `ashr login` key, else your personal workspace
125
+ ashr init --yes # no questions (no sign-in or ChatGPT connection), GPUs used if found
126
+ ```
127
+
128
+ With no organization key, `ashr init` uses your personal workspace through this
129
+ terminal's ashr account (signing in first) and connects your ChatGPT plan, which
130
+ its agent runs on ([`docs/personal-workspaces.md`](../docs/personal-workspaces.md)).
131
+ It checks Docker, Compose v2 and any NVIDIA GPUs, registers the host as the
132
+ workspace's runner, writes `~/.ashr/runner/` (`docker-compose.yml` and a
133
+ mode-0600 `.env` with the runner's token), pulls the runner and sandbox images
134
+ at this ashr's version from Ashr's private registry, starts the runner, and
135
+ checks one sandbox command end to end. The agent stays on Ashr; the runner dials
136
+ out to it and runs the agent's sandboxes on this host. Run it again with a newer
137
+ ashr to upgrade in place. Details in [`deploy/runner/README.md`](../deploy/runner/README.md).
138
+
139
+ ## Self-hosted server (air-gapped)
140
+
141
+ The full server on one host, for deployments that cannot reach Ashr at all, is set
142
+ up from a checkout by agreement: [`deploy/selfhost/README.md`](../deploy/selfhost/README.md).
143
+ ashr can also talk to an Ashr server running on your own host; a standalone
144
+ binary built without `ASHR_HOSTED=1` talks to no other. The server listens on `127.0.0.1:8080`
145
+ only, so from another machine forward the port first, then sign in once with the
146
+ server's admin key (`docker compose -p ashr exec -T api cat /state/admin-key` on
147
+ the host):
148
+
149
+ ```
150
+ ssh -L 8080:localhost:8080 <host> # keep this open
151
+ ashr login --key ask_… --api-url http://localhost:8080
152
+ ashr # opens the server's workspace
153
+ ashr --local # the local agent instead (not in the npm package)
154
+ ```
155
+
156
+ Once signed in, plain `ashr` opens the server's workspace, and the hosted
157
+ commands above (`--task`, `--chat`, `-c`, `/chats`, …) work against it.
158
+ `MANIFOLD_API_URL` works in place of `--api-url`. Plain `http` is refused for
159
+ anything but `localhost`: use the port-forward, or put TLS in front of the
160
+ server and pass its `https` URL. There is no browser sign-in, and `/github` is
161
+ not available on self-hosted servers yet.
162
+
163
+ ## Your account
164
+
165
+ The first time you run `ashr` in a terminal it opens your browser to sign in (any email; no organization). The
166
+ terminal keeps its own key in `~/.ashr/credentials.json` and doesn't ask again. The account page,
167
+ https://manifold.ashr.io/cli (or `/account` in a session), shows your sessions, turns, tokens and cost over the last
168
+ 30 days, and has a button for booking an upgrade call. Print mode (`ashr -p`) and scripts without a terminal never
169
+ stop to sign in.
170
+
171
+ Over SSH the browser can't reach the terminal, so `ashr` prints a link to open on any machine instead; after you
172
+ connect, the page shows a code to paste back into the terminal. In a container or any other terminal the browser
173
+ can't reach, press Enter while `ashr` waits to switch to that link and code. If sign-in fails (offline, say), `ashr` starts
174
+ without an account and asks again next run.
175
+
176
+ The account is who you are, not your model: sign in to a model below. Usage on the account page comes from the usage
177
+ data ashr sends (see [Usage data](#usage-data)); with it off, nothing is recorded there.
178
+
179
+ ## Your model
180
+
181
+ Sign in with the subscription you already have:
182
+
183
+ ```
184
+ ashr login chatgpt # ChatGPT Plus/Pro, through OpenAI's Sign in with ChatGPT
185
+ ashr login codex # ChatGPT through the Codex sign-in
186
+ ashr login claude # Claude Pro/Max
187
+ ashr logout chatgpt
188
+ ```
189
+
190
+ The sign-in stays on your machine (`~/.ashr/agent/auth.json`) and goes only to the provider.
191
+ With a ChatGPT sign-in ashr runs GPT-6 Astra; with Claude or an Anthropic key, Claude Fable.
192
+ If your ChatGPT workspace blocks third-party apps but allows Codex, use
193
+ `ashr login codex`. Saved sign-ins are available when the local agent starts.
194
+
195
+ Or use a provider key. Set it in your shell, or store it once:
196
+
197
+ ```
198
+ export ANTHROPIC_API_KEY=sk-… # or OPENAI_API_KEY, GEMINI_API_KEY
199
+ ashr login --provider anthropic # stores it in ~/.ashr/credentials.json (readable only by you)
200
+ ```
201
+
202
+ A key set in your shell always wins over a stored one. Keys are never passed to the commands the agent runs.
203
+
204
+ `ashr login` without a provider does not store a model key: the published builds
205
+ refuse it with exit 2 and point at the model sign-ins above.
206
+
207
+ ## Using the local agent
208
+
209
+ ```
210
+ ashr new local session in this repo (--local is also accepted)
211
+ ashr -c continue the latest session here
212
+ ashr -r pick a session to resume
213
+ ashr -p "<prompt>" one turn, printed (for scripts and CI); waits for its subagents
214
+ ashr -c -p "<prompt>" continue the latest session in print mode
215
+ ashr init run the agent's sandboxes on this Docker host; see Your own machines
216
+ ```
217
+
218
+ To set a repo up, run `ashr` in it and type `/init`: the agent reads the repo, checks
219
+ this machine against the environment probe, asks you once for what it could not find,
220
+ and writes `## Commands` and `## Setup` in `ASHR.md`. It asks before installing
221
+ anything, creating environments, downloading models or data, or submitting jobs
222
+ (`/init` is refused while the agent is working).
223
+
224
+ The local agent is the same durable harness as the hosted one. A session's transcript is a SQLite file, so a session
225
+ you quit (or that was killed) picks up where it stopped with `ashr -c`, work in flight included.
226
+
227
+ ### Subagents
228
+
229
+ The agent can hand independent pieces of work to subagents that run in parallel on your machine. Each subagent works
230
+ in its own git worktree, a snapshot of the agent's working tree (uncommitted and untracked files included, ignored files
231
+ left out) on its own branch `ashr/<session>-<name>-<id>`, so subagents change code without touching your checkout or each
232
+ other's. Each one commits on its branch and reports back; the agent reviews the branches and merges what works. The
233
+ worktrees live under `~/.ashr/worktrees/`, outside your repo; `git worktree list` shows them and `git worktree remove`
234
+ cleans one up. Subagents need the repo to be a git repository. A subagent runs the executor model of the agent's
235
+ maker (Claude Sonnet under Claude, GPT-6.1 Sol under ChatGPT or OpenAI), on the same subscription or key. `/rewind`
236
+ stops the subagents of the turns it drops, and `/fork` is refused until the agent and its subagents are done.
237
+
238
+ While the agent works, Enter steers it, Option-Enter queues a message for when it finishes, and Esc stops it. When an approval is waiting, `a` approves, `r` rejects and `A` always allows; Tab switches to the input box so you can type a message instead. Type `/` for commands: `/init`, `/usage`, `/account`, `/permissions` (and `/permissions remove <rule>`), `/resume`, `/fork`, `/rewind`, `/compact`, `/model`, `/mode`, `/add-dir`, `/update`, `/help`.
239
+
240
+ ### Skills and GPU setup
241
+
242
+ Local sessions include the hosted skill catalog in the CLI bundle; no separate
243
+ skill installation is needed. Add your own skills as `<name>/SKILL.md` inside
244
+ your repo's `.ashr/skills/` or `~/.ashr/skills/` (`$ASHR_HOME/skills/` when set).
245
+ For the same name, the repo wins over your personal directory, which wins over
246
+ the built-in skill, including references from other built-in skills. The agent
247
+ receives each available skill's name, description and `SKILL.md` path; subagents
248
+ use the same skill roots. Built-in files are unpacked into a private temporary
249
+ directory (mode `0700`) for each session and removed when it closes.
250
+
251
+ At session start, the agent receives an environment summary of local GPUs
252
+ (via `nvidia-smi` or Apple Silicon detection), profilers, job launchers and cloud
253
+ CLIs on `PATH`, and concrete host names in `~/.ssh/config`. Discovery does not
254
+ log in to cloud services or contact SSH hosts. Before the first GPU, training or
255
+ profiling run, the agent is instructed to check `ASHR.md` for your setup. If it
256
+ is missing, it asks one short question based on the probe and records your
257
+ answer under `## Setup` in `ASHR.md`; later sessions reuse that answer.
258
+
259
+ ## Local permissions
260
+
261
+ Like pi, ashr runs the agent's tools without asking by default (Auto mode),
262
+ including outside-repo access, `git push`, force operations, `sudo` and downloaded
263
+ scripts. Deny rules still block matching actions. Spending money on Manifold
264
+ (data copies, GPU runs, evaluations, deploys) always requires approval.
265
+
266
+ In ask and edit modes, outside-repo reads and writes require approval, as do
267
+ dangerous shell commands. Outside-repo checks cover shell paths and redirects
268
+ (for example `cat ~/.ssh/id_rsa` or `--out=/tmp/x`), except directories you added
269
+ with `/add-dir` or device files under `/dev`.
270
+
271
+ Prefer to approve more? Shift-Tab cycles the mode:
272
+
273
+ | Mode | Runs without asking | Asks first |
274
+ |---|---|---|
275
+ | auto (default) | everything not denied, except spending | spending on Manifold |
276
+ | ask | reading and read-only commands (`ls`, `cat`, `grep`, `git log` …) | edits, other shell commands, connector tools |
277
+ | edit | reads, read-only commands and edits inside the repo | other shell commands, connector tools |
278
+
279
+ In ask and edit mode, changes to the repo's own `.git/` files always ask, since git settings there can run commands.
280
+
281
+ Set your own default with `"defaultMode": "ask"` in `~/.ashr/settings.json`. A repo's committed settings can make you stricter but never move you to Auto.
282
+
283
+ These stops catch an agent's honest mistakes. They are not a security boundary: in Auto the agent can run any program, and a program can do anything your user account can. For untrusted repos, run ashr in a container or a separate user account.
284
+
285
+ Answering `A` on an approval saves an "always allow" rule. Rules live in three files; any deny rule wins:
286
+
287
+ - `~/.ashr/settings.json` — yours, everywhere
288
+ - `.ashr/settings.json` — the team's, committed
289
+ - `.ashr/settings.local.json` — yours, for this repo (gitignored; "always allow" writes here)
290
+
291
+ ```json
292
+ { "permissions": { "allow": ["shell:pytest *", "edit:src/**"], "deny": ["shell:git push *", "edit:.env*"] } }
293
+ ```
294
+
295
+ A repo's committed rules apply only after you trust them; ashr asks the first time and again whenever they change.
296
+
297
+ In print mode nothing can be approved interactively: a run that needs approval exits 3 and names the rule to add, for example `--allow "edit:a.txt"` (one `--allow` per part of a compound shell command), or the mode that would allow it (`--mode edit|auto` for edits, `--mode auto` otherwise). Spending needs an interactive run because it asks in every mode.
298
+
299
+ ## Where local things live
300
+
301
+ - Sessions: `~/.ashr/sessions/<org>/<repo>/<session>/` (`session.sqlite`, the transcript of the agent and its subagents; `meta.json`; file snapshots for `/fork` and `/rewind`)
302
+ - Subagent worktrees: `~/.ashr/worktrees/<repo>/<session>/<name>-<id>/`
303
+ - `ASHR.md` in your repo and `~/.ashr/memory.md` are read into every session.
304
+ - Set `ASHR_HOME` to keep all of this somewhere else.
305
+
306
+ ## Usage data
307
+
308
+ ashr sends usage data so we can see which features work and where runs fail: the commands you run, which tools the agent used and for how long, token counts and cost, errors, the model, your ashr version and OS, and a random install id. Once you are signed in, it is also sent with your account key so the account page can add up your daily totals; only those totals are kept with your account. It never sends your prompts, the agent's replies, tool arguments or tool output unless you turn each one on:
309
+
310
+ | Setting | Sends |
311
+ |---|---|
312
+ | `ASHR_TELEMETRY_LOG_PROMPTS=1` | your prompts and the agent's replies |
313
+ | `ASHR_TELEMETRY_LOG_TOOL_DETAILS=1` | tool arguments (commands, paths) |
314
+ | `ASHR_TELEMETRY_LOG_TOOL_OUTPUT=1` | tool output and subagent reports |
315
+
316
+ The same switches can go in `~/.ashr/settings.json` as `"telemetry": { "logPrompts": true, … }`. Before anything leaves your machine, ashr removes the secrets in its environment, API keys and tokens, emails, phone numbers, card numbers, IP addresses and your home directory; the Ashr API removes them again before storing anything.
317
+
318
+ - `ashr telemetry` says what is sent and where; `ashr telemetry show` prints what was last sent.
319
+ - `ashr telemetry off`, `ASHR_TELEMETRY=off` or `DO_NOT_TRACK=1` turns it off.
320
+ - `ASHR_TELEMETRY_ENDPOINT` (and `ASHR_TELEMETRY_HEADERS`, `name=value,…`) sends the same OpenTelemetry traces to your own collector, Langfuse, Arize or Datadog instead of Ashr.
321
+
322
+ ## Parity checks
323
+
324
+ Run `npm test`, `npm run typecheck`, and `npm run build` from `cli/`. `npm run build`
325
+ makes the published package and fails if it would bundle agent code;
326
+ `ASHR_LOCAL=1 npm run build` makes the full ashr with the local agent.
327
+ `npm run test:parity` starts a disposable SQLite backend and verifies both
328
+ client contracts against real routes. Set `MANIFOLD_TEST_PYTHON` to a Python
329
+ environment with the repository's backend test dependencies installed.
330
+
331
+ `npm run test:parity:browser` builds the actual React/TUI fixtures, starts
332
+ loopback-only servers on ports 3192, 3194 and 3195, then runs Chromium acceptance
333
+ and saves video/screenshots under `.artifacts/parity/`. It needs Playwright and
334
+ its Chromium browser installed; `PLAYWRIGHT_MODULE` may point to an existing
335
+ Playwright ESM entry. It refuses occupied fixture ports and stops its own servers.
336
+
337
+ These tests simulate Clerk identity and model/compute responses explicitly.
338
+ They do not verify deployed Clerk configuration, paid compute or external
339
+ storage. See `docs/terminal-parity-audit.md` for coverage and remaining live checks.