nandi/oripublic Fork 0
f5c963a
Commits
Clone
git clone https://git.rickub.com/nandi/ori.git
git clone ssh://git@rickub.com/nandi/ori.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

forked from bots-garden/ori

🛟 Updated.

k33g committed 2026-09-18T07:56:09+02:00 Browse files
f5c963a parent: ca7e020
modified .gitignore +3 -0
@@ -25,3 +25,6 @@ ori-desktop/build/windows/installer/tmp/
2525 ori-desktop/frontend/wailsjs/
2626 ori-desktop/frontend/node_modules/
2727 ori-desktop/frontend/dist/
28+
29+# compiled AppleScript launcher (rebuild with osacompile, see quickstart.md)
30+scripts/*.app/
@@ -25,3 +25,6 @@ ori-desktop/build/windows/installer/tmp/
25 ori-desktop/frontend/wailsjs/25 ori-desktop/frontend/wailsjs/
26 ori-desktop/frontend/node_modules/26 ori-desktop/frontend/node_modules/
27 ori-desktop/frontend/dist/27 ori-desktop/frontend/dist/
28+
29+# compiled AppleScript launcher (rebuild with osacompile, see quickstart.md)
30+scripts/*.app/
added .memory/handoffs/2026-09-18-launch-ori-applescript.md +25 -0
new file mode 100644
@@ -0,0 +1,25 @@
1+# 2026-09-18 — AppleScript launcher (`scripts/launch-ori.applescript`)
2+
3+## State
4+
5+Written, compile-checked, handlers tested in isolation. **Not yet run end to end** — that needs Docker Desktop + a real `sbx run`, which creates the sandbox and starts Claude inside it. First real run to do by the user: `osascript scripts/launch-ori.applescript`.
6+
7+## Things to confirm on the first real run
8+
9+- Behaviour of `sbx run -d --name ori` when the sandbox is already **running** (unknown: no-op or error?). The script only notifies on error there and relies on the health check, so either way the app should open; tighten if the notification is noisy.
10+- Time for the kit to start the server after `sbx run -d` returns; budget is 90 s (`healthTimeoutSeconds`), adjust if the template pull makes the first launch slower.
11+- `display notification` from a compiled app may need notification permission the first time.
12+
13+## Traps
14+
15+- `do shell script` PATH: fine from a terminal (inherits the shell), minimal from Finder — hence the explicit `export PATH`.
16+- `sbx inspect`/`sbx ports` on a missing sandbox print `ERROR:` but their exit code was masked in my probe; `sbx ls -q` (names only) is the reliable existence test.
17+- Handlers can be tested without running `on run`: `osacompile -o /tmp/x.scpt …` then `load script` + call `s's waitForServer(...)`.
18+
19+## Update (same day) — double-clickable app
20+
21+`scripts/Launch Ori.app` built with `osacompile -o "scripts/Launch Ori.app" scripts/launch-ori.applescript`; gitignored (`scripts/*.app/`), rebuild after editing the `.applescript`. `path to me` then resolves to the `.app` bundle inside `scripts/`, so the repo root still derives correctly. The app has no quarantine attribute (built locally), so Gatekeeper does not block it. Still not run end to end.
22+
23+## Update — README
24+
25+`scripts/README.md` (EN) and `scripts/README.fr.md` (FR) document the launcher; keep them in sync with the `property` defaults at the top of the script if those change.
new file mode 100644
@@ -0,0 +1,25 @@
1+# 2026-09-18 — AppleScript launcher (`scripts/launch-ori.applescript`)
2+
3+## State
4+
5+Written, compile-checked, handlers tested in isolation. **Not yet run end to end** — that needs Docker Desktop + a real `sbx run`, which creates the sandbox and starts Claude inside it. First real run to do by the user: `osascript scripts/launch-ori.applescript`.
6+
7+## Things to confirm on the first real run
8+
9+- Behaviour of `sbx run -d --name ori` when the sandbox is already **running** (unknown: no-op or error?). The script only notifies on error there and relies on the health check, so either way the app should open; tighten if the notification is noisy.
10+- Time for the kit to start the server after `sbx run -d` returns; budget is 90 s (`healthTimeoutSeconds`), adjust if the template pull makes the first launch slower.
11+- `display notification` from a compiled app may need notification permission the first time.
12+
13+## Traps
14+
15+- `do shell script` PATH: fine from a terminal (inherits the shell), minimal from Finder — hence the explicit `export PATH`.
16+- `sbx inspect`/`sbx ports` on a missing sandbox print `ERROR:` but their exit code was masked in my probe; `sbx ls -q` (names only) is the reliable existence test.
17+- Handlers can be tested without running `on run`: `osacompile -o /tmp/x.scpt …` then `load script` + call `s's waitForServer(...)`.
18+
19+## Update (same day) — double-clickable app
20+
21+`scripts/Launch Ori.app` built with `osacompile -o "scripts/Launch Ori.app" scripts/launch-ori.applescript`; gitignored (`scripts/*.app/`), rebuild after editing the `.applescript`. `path to me` then resolves to the `.app` bundle inside `scripts/`, so the repo root still derives correctly. The app has no quarantine attribute (built locally), so Gatekeeper does not block it. Still not run end to end.
22+
23+## Update — README
24+
25+`scripts/README.md` (EN) and `scripts/README.fr.md` (FR) document the launcher; keep them in sync with the `property` defaults at the top of the script if those change.
added .memory/handoffs/2026-09-18-ticket-0005-format.md +22 -0
new file mode 100644
@@ -0,0 +1,22 @@
1+# 2026-09-18 — Ticket 0005 task format
2+
3+## Done
4+
5+`.tickets/issues/0005-create-a-native-ui-to-connect-the-webapp.yaml` tasks rewritten from a hand-made `text/done` shape to IssueSpec's task schema. Verified with IssueSpec's own parser (all 15 tickets parse). Ticket stays `open`: task 8 (launch the window with the GUI toolchain and confirm the iframe embed) is still open — see `summary.md` "Not yet established".
6+
7+## How to validate a ticket file (recipe)
8+
9+```bash
10+cat > /tmp/v.mjs <<'EOF2'
11+import { parseIssueDocument } from '/Users/k33g/CodeBerg/issuespec/src/core/yaml.ts';
12+import { readFileSync } from 'node:fs';
13+const f = process.argv[2]; try { const r = parseIssueDocument(readFileSync(f,'utf8'), f); console.log('OK', r.tasks.length, 'tasks'); } catch (e) { console.log('INVALID:', e.message); process.exitCode = 1; }
14+EOF2
15+(cd ~/CodeBerg/issuespec && npx --no-install esbuild /tmp/v.mjs --bundle --platform=node --format=cjs --outfile=/tmp/v.cjs)
16+for f in .tickets/issues/*.yaml; do printf '%s: ' "$f"; node /tmp/v.cjs "$f"; done
17+```
18+`--format=esm` fails ("Dynamic require of process") because of the `yaml` package; use cjs.
19+
20+## Trap
21+
22+When closing a ticket's checklist by hand, copy the shape from a tool-written task (e.g. ticket 0001) — `priority` is always written (`none`), `closedAt` only while `state: closed`. Reference: `~/CodeBerg/issuespec/docs/en/reference/ticket-files.md` § Task.
new file mode 100644
@@ -0,0 +1,22 @@
1+# 2026-09-18 — Ticket 0005 task format
2+
3+## Done
4+
5+`.tickets/issues/0005-create-a-native-ui-to-connect-the-webapp.yaml` tasks rewritten from a hand-made `text/done` shape to IssueSpec's task schema. Verified with IssueSpec's own parser (all 15 tickets parse). Ticket stays `open`: task 8 (launch the window with the GUI toolchain and confirm the iframe embed) is still open — see `summary.md` "Not yet established".
6+
7+## How to validate a ticket file (recipe)
8+
9+```bash
10+cat > /tmp/v.mjs <<'EOF2'
11+import { parseIssueDocument } from '/Users/k33g/CodeBerg/issuespec/src/core/yaml.ts';
12+import { readFileSync } from 'node:fs';
13+const f = process.argv[2]; try { const r = parseIssueDocument(readFileSync(f,'utf8'), f); console.log('OK', r.tasks.length, 'tasks'); } catch (e) { console.log('INVALID:', e.message); process.exitCode = 1; }
14+EOF2
15+(cd ~/CodeBerg/issuespec && npx --no-install esbuild /tmp/v.mjs --bundle --platform=node --format=cjs --outfile=/tmp/v.cjs)
16+for f in .tickets/issues/*.yaml; do printf '%s: ' "$f"; node /tmp/v.cjs "$f"; done
17+```
18+`--format=esm` fails ("Dynamic require of process") because of the `yaml` package; use cjs.
19+
20+## Trap
21+
22+When closing a ticket's checklist by hand, copy the shape from a tool-written task (e.g. ticket 0001) — `priority` is always written (`none`), `closedAt` only while `state: closed`. Reference: `~/CodeBerg/issuespec/docs/en/reference/ticket-files.md` § Task.
modified .memory/history.md +15 -0
@@ -137,3 +137,18 @@
137137 - **Finding**: `origin` is `https://git.rickub.com/bots-garden/ori.git`; the server answers 401 on `git-receive-pack`, the macOS keychain has no entry for that host, and the session (launched from VSCodium's terminal) exports `GIT_ASKPASS` → VSCodium's `askpass.sh`. Git therefore hands the password prompt to VSCodium's input box, which is easy to miss, so the push waits forever. Confirmed with `ps`: `git-remote-https``askpass.sh "Password for 'https://git.rickub.com'"` blocked.
138138 - **Also verified**: network fine (DNS, 443, 22 all open); anonymous read over HTTPS works; SSH key `~/.ssh/id_ed25519` is accepted by `git@git.rickub.com` (server replies "serves git only"); `git ls-remote` over SSH succeeds and shows the remote repo is **empty** (no branches yet). Local `main` = 34e69b5.
139139 - **Recommendation left to the user**: switch `origin` to `git@git.rickub.com:bots-garden/ori.git` (no password, key already trusted), or run the push in a plain terminal with `GIT_ASKPASS` unset so osxkeychain stores the credentials. Not applied — awaiting the user's choice.
140+
141+## 2026-09-18 — AppleScript launcher for the ori sandbox + desktop app
142+
143+- **Asked**: an AppleScript that runs `sbx run -d claude . --template k33g/ori:0.0.1 --kit ./kits/ori --name ori -p 5555:8888` then launches `ori-desktop/build/bin/ori-desktop.app`.
144+- **Changes**: new `scripts/launch-ori.applescript`; one row in `quickstart.md` (everyday commands); pointer in `summary.md`.
145+- **Decisions**: (1) if `sbx ls -q` already lists `ori`, restart it with `sbx run -d --name ori` instead of re-running the create command (which would collide on the name); errors on that path only notify, the health check decides. (2) Poll `/healthz` on :5555 (2 s × 45) before opening the app, because the kit starts the server asynchronously and the desktop app auto-connects to the saved URL (`~/Library/Application Support/ori-desktop/settings.json` already holds `http://localhost:5555`). (3) `PATH` exported explicitly (Finder launches lack `/opt/homebrew/bin`). (4) Repo root derived from `path to me` so the compiled `.app` works from `scripts/` too. Rejected: `sbx rm` + recreate on every launch (destroys the sandbox's Claude session/state).
146+- **Tests**: `osacompile` OK; handlers exercised via `load script`: `sandboxExists` → false with no sandbox, `waitForServer` → false on a closed port, true against a throw-away Python `/healthz` on :5555. Not run end to end (would create a real sandbox and start Claude in it). Quality gate not re-run (no Go/TS touched).
147+
148+## 2026-09-18 — Ticket 0005 back to the IssueSpec task schema; launcher compiled as an app
149+
150+- **Asked**: "le ticket 0005 n'est plus au bon format"; then how to make the AppleScript launcher double-clickable.
151+- **Cause**: the 0005 checklist had been hand-written as `- text: … / done: true|false`, which is not IssueSpec's task shape (`id`, `title`, `state`, `priority`, `author`, `createdAt`, optional `updatedAt`/`closedAt`). IssueSpec's parser rejects the file: "tasks[0].id must be a positive integer".
152+- **Changes**: `.tickets/issues/0005-….yaml` — 8 tasks rewritten (7 `closed` with `updatedAt`/`closedAt` = 2026-09-17T22:23:39Z, 1 `open`; all `priority: none`, author k33g); issue `updatedAt` bumped. `scripts/Launch Ori.app` built with `osacompile`, ignored via `.gitignore` (`scripts/*.app/`). `summary.md` gains a `.tickets` paragraph.
153+- **Verification**: bundled IssueSpec's `parseIssueDocument` (from the local clone `~/CodeBerg/issuespec`, esbuild `--format=cjs`) and ran it over all 15 tickets: all OK; the committed 0005 fails as expected.
154+- **Follow-up**: `scripts/README.md` + `scripts/README.fr.md` written (what the launcher does, run vs. double-click, design choices, handler test recipe); quickstart row now points to it.
@@ -137,3 +137,18 @@
137 - **Finding**: `origin` is `https://git.rickub.com/bots-garden/ori.git`; the server answers 401 on `git-receive-pack`, the macOS keychain has no entry for that host, and the session (launched from VSCodium's terminal) exports `GIT_ASKPASS` → VSCodium's `askpass.sh`. Git therefore hands the password prompt to VSCodium's input box, which is easy to miss, so the push waits forever. Confirmed with `ps`: `git-remote-https``askpass.sh "Password for 'https://git.rickub.com'"` blocked.137 - **Finding**: `origin` is `https://git.rickub.com/bots-garden/ori.git`; the server answers 401 on `git-receive-pack`, the macOS keychain has no entry for that host, and the session (launched from VSCodium's terminal) exports `GIT_ASKPASS` → VSCodium's `askpass.sh`. Git therefore hands the password prompt to VSCodium's input box, which is easy to miss, so the push waits forever. Confirmed with `ps`: `git-remote-https``askpass.sh "Password for 'https://git.rickub.com'"` blocked.
138 - **Also verified**: network fine (DNS, 443, 22 all open); anonymous read over HTTPS works; SSH key `~/.ssh/id_ed25519` is accepted by `git@git.rickub.com` (server replies "serves git only"); `git ls-remote` over SSH succeeds and shows the remote repo is **empty** (no branches yet). Local `main` = 34e69b5.138 - **Also verified**: network fine (DNS, 443, 22 all open); anonymous read over HTTPS works; SSH key `~/.ssh/id_ed25519` is accepted by `git@git.rickub.com` (server replies "serves git only"); `git ls-remote` over SSH succeeds and shows the remote repo is **empty** (no branches yet). Local `main` = 34e69b5.
139 - **Recommendation left to the user**: switch `origin` to `git@git.rickub.com:bots-garden/ori.git` (no password, key already trusted), or run the push in a plain terminal with `GIT_ASKPASS` unset so osxkeychain stores the credentials. Not applied — awaiting the user's choice.139 - **Recommendation left to the user**: switch `origin` to `git@git.rickub.com:bots-garden/ori.git` (no password, key already trusted), or run the push in a plain terminal with `GIT_ASKPASS` unset so osxkeychain stores the credentials. Not applied — awaiting the user's choice.
140+
141+## 2026-09-18 — AppleScript launcher for the ori sandbox + desktop app
142+
143+- **Asked**: an AppleScript that runs `sbx run -d claude . --template k33g/ori:0.0.1 --kit ./kits/ori --name ori -p 5555:8888` then launches `ori-desktop/build/bin/ori-desktop.app`.
144+- **Changes**: new `scripts/launch-ori.applescript`; one row in `quickstart.md` (everyday commands); pointer in `summary.md`.
145+- **Decisions**: (1) if `sbx ls -q` already lists `ori`, restart it with `sbx run -d --name ori` instead of re-running the create command (which would collide on the name); errors on that path only notify, the health check decides. (2) Poll `/healthz` on :5555 (2 s × 45) before opening the app, because the kit starts the server asynchronously and the desktop app auto-connects to the saved URL (`~/Library/Application Support/ori-desktop/settings.json` already holds `http://localhost:5555`). (3) `PATH` exported explicitly (Finder launches lack `/opt/homebrew/bin`). (4) Repo root derived from `path to me` so the compiled `.app` works from `scripts/` too. Rejected: `sbx rm` + recreate on every launch (destroys the sandbox's Claude session/state).
146+- **Tests**: `osacompile` OK; handlers exercised via `load script`: `sandboxExists` → false with no sandbox, `waitForServer` → false on a closed port, true against a throw-away Python `/healthz` on :5555. Not run end to end (would create a real sandbox and start Claude in it). Quality gate not re-run (no Go/TS touched).
147+
148+## 2026-09-18 — Ticket 0005 back to the IssueSpec task schema; launcher compiled as an app
149+
150+- **Asked**: "le ticket 0005 n'est plus au bon format"; then how to make the AppleScript launcher double-clickable.
151+- **Cause**: the 0005 checklist had been hand-written as `- text: … / done: true|false`, which is not IssueSpec's task shape (`id`, `title`, `state`, `priority`, `author`, `createdAt`, optional `updatedAt`/`closedAt`). IssueSpec's parser rejects the file: "tasks[0].id must be a positive integer".
152+- **Changes**: `.tickets/issues/0005-….yaml` — 8 tasks rewritten (7 `closed` with `updatedAt`/`closedAt` = 2026-09-17T22:23:39Z, 1 `open`; all `priority: none`, author k33g); issue `updatedAt` bumped. `scripts/Launch Ori.app` built with `osacompile`, ignored via `.gitignore` (`scripts/*.app/`). `summary.md` gains a `.tickets` paragraph.
153+- **Verification**: bundled IssueSpec's `parseIssueDocument` (from the local clone `~/CodeBerg/issuespec`, esbuild `--format=cjs`) and ran it over all 15 tickets: all OK; the committed 0005 fails as expected.
154+- **Follow-up**: `scripts/README.md` + `scripts/README.fr.md` written (what the launcher does, run vs. double-click, design choices, handler test recipe); quickstart row now points to it.
modified .memory/summary.md +4 -0
@@ -39,6 +39,7 @@ browser ⇆ WebSocket /ws ⇆ Go backend ⇆ stdio (ACP) ⇆ agent subprocess
3939 - `make test``go test ./...` + `vitest run`. Also useful: `go test -race ./...`, `go test -short ./...` (skips e2e).
4040 - `make run` — with Claude Code adapter; `make run-mock` — with the demo agent (no Claude/network needed).
4141 - `make template` — builds the `k33g/ori` sandbox template image (`template/Dockerfile`, FROM `docker/sandbox-templates:claude-code`); launch with `sbx run -d claude <project> --template k33g/ori:0.0.0 --kit <ori repo>/kits/ori --name ori -p 8888:8888` (detached — see the auto-stop trap below) (see `kits/ori/README.md` and docs how-to `run-in-a-sandbox`).
42+- `scripts/launch-ori.applescript` (2026-09-18) — macOS launcher: `sbx ls -q` → restart by name or create (`k33g/ori:0.0.1`, `./kits/ori`, `-p 5555:8888`), poll `http://localhost:5555/healthz` up to 90 s, then `open ori-desktop/build/bin/ori-desktop.app`. Run with `osascript`, or `osacompile` into `scripts/Launch Ori.app`; repo root derived from the script's own location. Compile-checked and handlers unit-tested; full end-to-end run not yet done.
4243 - **sbx auto-stop trap (verified in the sbx source + daemon log, 2026-09-17)**: sandboxd stops a sandbox 30 s (hard-coded `WithAutoStopDelay(30*time.Second)`, `sandboxd/pkg/server/backend_dockernext.go`) after its last CLI "sentinel" session closes; `sbx create`/`sbx exec`/`sbx run` all hold one for their own duration, browser traffic on a published port counts for nothing. Only a sandbox created with the spec field `detached: true` (CLI: `sbx run -d …`, absent from `sbx create`) is exempt; the field is create-time only (no PATCH), so an existing sandbox must be `sbx rm`'d and recreated with `sbx run -d`. No settings/env knob for the delay.
4344 - Quality: `python3 ~/.claude/skills/quality/scripts/quality_report.py --workspace .` (gate PASS, run #16, 2026-09-17 late evening: 0 errors, 0 warnings, 0 smells, complex 514 — covers the selectors/previews/desktop work, the resizable file tree and the light/dark theme).
4445 - `docs/source-code-analysis.adoc` — AsciiDoc snapshot analysis of the codebase (2026-09-17), outside the bilingual Diátaxis set.
@@ -66,3 +67,6 @@ browser ⇆ WebSocket /ws ⇆ Go backend ⇆ stdio (ACP) ⇆ agent subprocess
6667
6768 - Behaviour against a real Claude Code session (auth flow, real tool calls) has not been exercised in this sandbox — only against the mock agent and unit doubles.
6869
70+## Tickets (`.tickets/`)
71+
72+- Managed by the **IssueSpec** VSCodium extension (`k33g.issuespec` 0.1.28, author = the user; source clone at `~/CodeBerg/issuespec`, format reference `docs/en/reference/ticket-files.md`). Hand edits are allowed but must keep the schema: a task is `id` (int ≥ 1, unique in the issue), `title`, `state: open|closed`, `priority: none|low|medium|high|urgent` (always written), `author {name,email}`, `createdAt`, optional `updatedAt`, and `closedAt` only while closed. The `text/done` checklist shape is **invalid** (fixed in ticket 0005 on 2026-09-18; validation recipe in handoff `2026-09-18-ticket-0005-format.md`).
@@ -39,6 +39,7 @@ browser ⇆ WebSocket /ws ⇆ Go backend ⇆ stdio (ACP) ⇆ agent subprocess
39 - `make test``go test ./...` + `vitest run`. Also useful: `go test -race ./...`, `go test -short ./...` (skips e2e).39 - `make test``go test ./...` + `vitest run`. Also useful: `go test -race ./...`, `go test -short ./...` (skips e2e).
40 - `make run` — with Claude Code adapter; `make run-mock` — with the demo agent (no Claude/network needed).40 - `make run` — with Claude Code adapter; `make run-mock` — with the demo agent (no Claude/network needed).
41 - `make template` — builds the `k33g/ori` sandbox template image (`template/Dockerfile`, FROM `docker/sandbox-templates:claude-code`); launch with `sbx run -d claude <project> --template k33g/ori:0.0.0 --kit <ori repo>/kits/ori --name ori -p 8888:8888` (detached — see the auto-stop trap below) (see `kits/ori/README.md` and docs how-to `run-in-a-sandbox`).41 - `make template` — builds the `k33g/ori` sandbox template image (`template/Dockerfile`, FROM `docker/sandbox-templates:claude-code`); launch with `sbx run -d claude <project> --template k33g/ori:0.0.0 --kit <ori repo>/kits/ori --name ori -p 8888:8888` (detached — see the auto-stop trap below) (see `kits/ori/README.md` and docs how-to `run-in-a-sandbox`).
42+- `scripts/launch-ori.applescript` (2026-09-18) — macOS launcher: `sbx ls -q` → restart by name or create (`k33g/ori:0.0.1`, `./kits/ori`, `-p 5555:8888`), poll `http://localhost:5555/healthz` up to 90 s, then `open ori-desktop/build/bin/ori-desktop.app`. Run with `osascript`, or `osacompile` into `scripts/Launch Ori.app`; repo root derived from the script's own location. Compile-checked and handlers unit-tested; full end-to-end run not yet done.
42 - **sbx auto-stop trap (verified in the sbx source + daemon log, 2026-09-17)**: sandboxd stops a sandbox 30 s (hard-coded `WithAutoStopDelay(30*time.Second)`, `sandboxd/pkg/server/backend_dockernext.go`) after its last CLI "sentinel" session closes; `sbx create`/`sbx exec`/`sbx run` all hold one for their own duration, browser traffic on a published port counts for nothing. Only a sandbox created with the spec field `detached: true` (CLI: `sbx run -d …`, absent from `sbx create`) is exempt; the field is create-time only (no PATCH), so an existing sandbox must be `sbx rm`'d and recreated with `sbx run -d`. No settings/env knob for the delay.43 - **sbx auto-stop trap (verified in the sbx source + daemon log, 2026-09-17)**: sandboxd stops a sandbox 30 s (hard-coded `WithAutoStopDelay(30*time.Second)`, `sandboxd/pkg/server/backend_dockernext.go`) after its last CLI "sentinel" session closes; `sbx create`/`sbx exec`/`sbx run` all hold one for their own duration, browser traffic on a published port counts for nothing. Only a sandbox created with the spec field `detached: true` (CLI: `sbx run -d …`, absent from `sbx create`) is exempt; the field is create-time only (no PATCH), so an existing sandbox must be `sbx rm`'d and recreated with `sbx run -d`. No settings/env knob for the delay.
43 - Quality: `python3 ~/.claude/skills/quality/scripts/quality_report.py --workspace .` (gate PASS, run #16, 2026-09-17 late evening: 0 errors, 0 warnings, 0 smells, complex 514 — covers the selectors/previews/desktop work, the resizable file tree and the light/dark theme).44 - Quality: `python3 ~/.claude/skills/quality/scripts/quality_report.py --workspace .` (gate PASS, run #16, 2026-09-17 late evening: 0 errors, 0 warnings, 0 smells, complex 514 — covers the selectors/previews/desktop work, the resizable file tree and the light/dark theme).
44 - `docs/source-code-analysis.adoc` — AsciiDoc snapshot analysis of the codebase (2026-09-17), outside the bilingual Diátaxis set.45 - `docs/source-code-analysis.adoc` — AsciiDoc snapshot analysis of the codebase (2026-09-17), outside the bilingual Diátaxis set.
@@ -66,3 +67,6 @@ browser ⇆ WebSocket /ws ⇆ Go backend ⇆ stdio (ACP) ⇆ agent subprocess
66 67
67 - Behaviour against a real Claude Code session (auth flow, real tool calls) has not been exercised in this sandbox — only against the mock agent and unit doubles.68 - Behaviour against a real Claude Code session (auth flow, real tool calls) has not been exercised in this sandbox — only against the mock agent and unit doubles.
68 69
70+## Tickets (`.tickets/`)
71+
72+- Managed by the **IssueSpec** VSCodium extension (`k33g.issuespec` 0.1.28, author = the user; source clone at `~/CodeBerg/issuespec`, format reference `docs/en/reference/ticket-files.md`). Hand edits are allowed but must keep the schema: a task is `id` (int ≥ 1, unique in the issue), `title`, `state: open|closed`, `priority: none|low|medium|high|urgent` (always written), `author {name,email}`, `createdAt`, optional `updatedAt`, and `closedAt` only while closed. The `text/done` checklist shape is **invalid** (fixed in ticket 0005 on 2026-09-18; validation recipe in handoff `2026-09-18-ticket-0005-format.md`).
modified .tickets/issues/0001-draft.yaml +2 -2
@@ -1,12 +1,12 @@
11 # Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
22 id: 1
33 title: draft
4-state: open
4+state: closed
55 author:
66 name: k33g
77 email: ph.charriere@gmail.com
88 createdAt: 2026-09-17T09:23:50.599Z
9-updatedAt: 2026-09-17T09:27:44.868Z
9+updatedAt: 2026-09-18T05:26:01.161Z
1010 labels: []
1111 body: |
1212 A web server using the ACP protocol to connect to an agent.
@@ -1,12 +1,12 @@
1 # Managed by IssueSpec. Hand edits are welcome; keep the schema valid.1 # Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2 id: 12 id: 1
3 title: draft3 title: draft
4-state: open4+state: closed
5 author:5 author:
6 name: k33g6 name: k33g
7 email: ph.charriere@gmail.com7 email: ph.charriere@gmail.com
8 createdAt: 2026-09-17T09:23:50.599Z8 createdAt: 2026-09-17T09:23:50.599Z
9-updatedAt: 2026-09-17T09:27:44.868Z9+updatedAt: 2026-09-18T05:26:01.161Z
10 labels: []10 labels: []
11 body: |11 body: |
12 A web server using the ACP protocol to connect to an agent.12 A web server using the ACP protocol to connect to an agent.
modified .tickets/issues/0003-how-to-run-it-outside-the-sandbox.yaml +2 -2
@@ -1,12 +1,12 @@
11 # Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
22 id: 3
33 title: How to run it outside the sandbox?
4-state: open
4+state: closed
55 author:
66 name: k33g
77 email: ph.charriere@gmail.com
88 createdAt: 2026-09-17T10:09:16.901Z
9-updatedAt: 2026-09-17T10:09:16.901Z
9+updatedAt: 2026-09-18T05:25:46.743Z
1010 labels: []
1111 body: ""
1212 tasks: []
@@ -1,12 +1,12 @@
1 # Managed by IssueSpec. Hand edits are welcome; keep the schema valid.1 # Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2 id: 32 id: 3
3 title: How to run it outside the sandbox?3 title: How to run it outside the sandbox?
4-state: open4+state: closed
5 author:5 author:
6 name: k33g6 name: k33g
7 email: ph.charriere@gmail.com7 email: ph.charriere@gmail.com
8 createdAt: 2026-09-17T10:09:16.901Z8 createdAt: 2026-09-17T10:09:16.901Z
9-updatedAt: 2026-09-17T10:09:16.901Z9+updatedAt: 2026-09-18T05:25:46.743Z
10 labels: []10 labels: []
11 body: ""11 body: ""
12 tasks: []12 tasks: []
modified .tickets/issues/0005-create-a-native-ui-to-connect-the-webapp.yaml +79 -17
@@ -6,7 +6,7 @@ author:
66 name: k33g
77 email: ph.charriere@gmail.com
88 createdAt: 2026-09-17T19:19:43.179Z
9-updatedAt: 2026-09-17T22:23:39.000Z
9+updatedAt: 2026-09-18T05:29:00.000Z
1010 labels: []
1111 body: |
1212 Desktop shell for the ori webapp, built with Wails v2 (Go + platform webview), living in
@@ -20,20 +20,82 @@ body: |
2020 Docs: `ori-desktop/README.md` (EN) and `ori-desktop/README.fr.md` (FR).
2121 Root Makefile targets: `make desktop` (wails build), `make desktop-test` (pure-Go tests).
2222 tasks:
23- - text: Own Go module with Wails v2.16 layout (main.go, app.go, wails.json, frontend/, build/)
24- done: true
25- - text: Bound Go methods GetConfig / SaveConfig / CheckHealth / Connect / OpenInBrowser / SettingsPath
26- done: true
27- - text: Settings persisted as JSON in the user config dir, with unit tests
28- done: true
29- - text: /healthz probe with unit tests against httptest
30- done: true
31- - text: Plain HTML/CSS/JS frontend embedding ori in an iframe with a thin native bar
32- done: true
33- - text: README (EN) + README.fr (FR), root Makefile targets, .gitignore entries
34- done: true
35- - text: Verified go test / go vet and a Windows cross-build (wails build -platform windows/amd64)
36- done: true
37- - text: Launch the window on a machine with the GUI toolchain (webkit2gtk / Xcode / WebView2) and confirm the iframe embed
38- done: false
23+ - id: 1
24+ title: Own Go module with Wails v2.16 layout (main.go, app.go, wails.json, frontend/, build/)
25+ state: closed
26+ priority: none
27+ author:
28+ name: k33g
29+ email: ph.charriere@gmail.com
30+ createdAt: 2026-09-17T22:23:39.000Z
31+ updatedAt: 2026-09-17T22:23:39.000Z
32+ closedAt: 2026-09-17T22:23:39.000Z
33+ - id: 2
34+ title: Bound Go methods GetConfig / SaveConfig / CheckHealth / Connect / OpenInBrowser / SettingsPath
35+ state: closed
36+ priority: none
37+ author:
38+ name: k33g
39+ email: ph.charriere@gmail.com
40+ createdAt: 2026-09-17T22:23:39.000Z
41+ updatedAt: 2026-09-17T22:23:39.000Z
42+ closedAt: 2026-09-17T22:23:39.000Z
43+ - id: 3
44+ title: Settings persisted as JSON in the user config dir, with unit tests
45+ state: closed
46+ priority: none
47+ author:
48+ name: k33g
49+ email: ph.charriere@gmail.com
50+ createdAt: 2026-09-17T22:23:39.000Z
51+ updatedAt: 2026-09-17T22:23:39.000Z
52+ closedAt: 2026-09-17T22:23:39.000Z
53+ - id: 4
54+ title: /healthz probe with unit tests against httptest
55+ state: closed
56+ priority: none
57+ author:
58+ name: k33g
59+ email: ph.charriere@gmail.com
60+ createdAt: 2026-09-17T22:23:39.000Z
61+ updatedAt: 2026-09-17T22:23:39.000Z
62+ closedAt: 2026-09-17T22:23:39.000Z
63+ - id: 5
64+ title: Plain HTML/CSS/JS frontend embedding ori in an iframe with a thin native bar
65+ state: closed
66+ priority: none
67+ author:
68+ name: k33g
69+ email: ph.charriere@gmail.com
70+ createdAt: 2026-09-17T22:23:39.000Z
71+ updatedAt: 2026-09-17T22:23:39.000Z
72+ closedAt: 2026-09-17T22:23:39.000Z
73+ - id: 6
74+ title: README (EN) + README.fr (FR), root Makefile targets, .gitignore entries
75+ state: closed
76+ priority: none
77+ author:
78+ name: k33g
79+ email: ph.charriere@gmail.com
80+ createdAt: 2026-09-17T22:23:39.000Z
81+ updatedAt: 2026-09-17T22:23:39.000Z
82+ closedAt: 2026-09-17T22:23:39.000Z
83+ - id: 7
84+ title: Verified go test / go vet and a Windows cross-build (wails build -platform windows/amd64)
85+ state: closed
86+ priority: none
87+ author:
88+ name: k33g
89+ email: ph.charriere@gmail.com
90+ createdAt: 2026-09-17T22:23:39.000Z
91+ updatedAt: 2026-09-17T22:23:39.000Z
92+ closedAt: 2026-09-17T22:23:39.000Z
93+ - id: 8
94+ title: Launch the window on a machine with the GUI toolchain (webkit2gtk / Xcode / WebView2) and confirm the iframe embed
95+ state: open
96+ priority: none
97+ author:
98+ name: k33g
99+ email: ph.charriere@gmail.com
100+ createdAt: 2026-09-17T22:23:39.000Z
39101 comments: []
@@ -6,7 +6,7 @@ author:
6 name: k33g6 name: k33g
7 email: ph.charriere@gmail.com7 email: ph.charriere@gmail.com
8 createdAt: 2026-09-17T19:19:43.179Z8 createdAt: 2026-09-17T19:19:43.179Z
9-updatedAt: 2026-09-17T22:23:39.000Z9+updatedAt: 2026-09-18T05:29:00.000Z
10 labels: []10 labels: []
11 body: |11 body: |
12 Desktop shell for the ori webapp, built with Wails v2 (Go + platform webview), living in12 Desktop shell for the ori webapp, built with Wails v2 (Go + platform webview), living in
@@ -20,20 +20,82 @@ body: |
20 Docs: `ori-desktop/README.md` (EN) and `ori-desktop/README.fr.md` (FR).20 Docs: `ori-desktop/README.md` (EN) and `ori-desktop/README.fr.md` (FR).
21 Root Makefile targets: `make desktop` (wails build), `make desktop-test` (pure-Go tests).21 Root Makefile targets: `make desktop` (wails build), `make desktop-test` (pure-Go tests).
22 tasks:22 tasks:
23- - text: Own Go module with Wails v2.16 layout (main.go, app.go, wails.json, frontend/, build/)23+ - id: 1
24- done: true24+ title: Own Go module with Wails v2.16 layout (main.go, app.go, wails.json, frontend/, build/)
25- - text: Bound Go methods GetConfig / SaveConfig / CheckHealth / Connect / OpenInBrowser / SettingsPath25+ state: closed
26- done: true26+ priority: none
27- - text: Settings persisted as JSON in the user config dir, with unit tests27+ author:
28- done: true28+ name: k33g
29- - text: /healthz probe with unit tests against httptest29+ email: ph.charriere@gmail.com
30- done: true30+ createdAt: 2026-09-17T22:23:39.000Z
31- - text: Plain HTML/CSS/JS frontend embedding ori in an iframe with a thin native bar31+ updatedAt: 2026-09-17T22:23:39.000Z
32- done: true32+ closedAt: 2026-09-17T22:23:39.000Z
33- - text: README (EN) + README.fr (FR), root Makefile targets, .gitignore entries33+ - id: 2
34- done: true34+ title: Bound Go methods GetConfig / SaveConfig / CheckHealth / Connect / OpenInBrowser / SettingsPath
35- - text: Verified go test / go vet and a Windows cross-build (wails build -platform windows/amd64)35+ state: closed
36- done: true36+ priority: none
37- - text: Launch the window on a machine with the GUI toolchain (webkit2gtk / Xcode / WebView2) and confirm the iframe embed37+ author:
38- done: false38+ name: k33g
39+ email: ph.charriere@gmail.com
40+ createdAt: 2026-09-17T22:23:39.000Z
41+ updatedAt: 2026-09-17T22:23:39.000Z
42+ closedAt: 2026-09-17T22:23:39.000Z
43+ - id: 3
44+ title: Settings persisted as JSON in the user config dir, with unit tests
45+ state: closed
46+ priority: none
47+ author:
48+ name: k33g
49+ email: ph.charriere@gmail.com
50+ createdAt: 2026-09-17T22:23:39.000Z
51+ updatedAt: 2026-09-17T22:23:39.000Z
52+ closedAt: 2026-09-17T22:23:39.000Z
53+ - id: 4
54+ title: /healthz probe with unit tests against httptest
55+ state: closed
56+ priority: none
57+ author:
58+ name: k33g
59+ email: ph.charriere@gmail.com
60+ createdAt: 2026-09-17T22:23:39.000Z
61+ updatedAt: 2026-09-17T22:23:39.000Z
62+ closedAt: 2026-09-17T22:23:39.000Z
63+ - id: 5
64+ title: Plain HTML/CSS/JS frontend embedding ori in an iframe with a thin native bar
65+ state: closed
66+ priority: none
67+ author:
68+ name: k33g
69+ email: ph.charriere@gmail.com
70+ createdAt: 2026-09-17T22:23:39.000Z
71+ updatedAt: 2026-09-17T22:23:39.000Z
72+ closedAt: 2026-09-17T22:23:39.000Z
73+ - id: 6
74+ title: README (EN) + README.fr (FR), root Makefile targets, .gitignore entries
75+ state: closed
76+ priority: none
77+ author:
78+ name: k33g
79+ email: ph.charriere@gmail.com
80+ createdAt: 2026-09-17T22:23:39.000Z
81+ updatedAt: 2026-09-17T22:23:39.000Z
82+ closedAt: 2026-09-17T22:23:39.000Z
83+ - id: 7
84+ title: Verified go test / go vet and a Windows cross-build (wails build -platform windows/amd64)
85+ state: closed
86+ priority: none
87+ author:
88+ name: k33g
89+ email: ph.charriere@gmail.com
90+ createdAt: 2026-09-17T22:23:39.000Z
91+ updatedAt: 2026-09-17T22:23:39.000Z
92+ closedAt: 2026-09-17T22:23:39.000Z
93+ - id: 8
94+ title: Launch the window on a machine with the GUI toolchain (webkit2gtk / Xcode / WebView2) and confirm the iframe embed
95+ state: open
96+ priority: none
97+ author:
98+ name: k33g
99+ email: ph.charriere@gmail.com
100+ createdAt: 2026-09-17T22:23:39.000Z
39 comments: []101 comments: []
added .tickets/issues/0016-publish-the-kit.yaml +33 -0
new file mode 100644
@@ -0,0 +1,33 @@
1+# Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2+id: 16
3+title: Publish the kit
4+state: open
5+author:
6+ name: k33g
7+ email: ph.charriere@gmail.com
8+createdAt: 2026-09-18T00:00:00.000Z
9+updatedAt: 2026-09-18T00:00:00.000Z
10+labels: []
11+body: |
12+ Publish the ori kit so it can be used via `sbx create claude --kit ori` instead of requiring
13+ a local path `--kit ./kits/ori`.
14+
15+ According to the sbx source exploration (2026-09-17, follow-up 5b in history.md), kits can be
16+ distributed using:
17+ - `sbx kit validate` — validate kit spec
18+ - `sbx kit pack` — package the kit
19+ - `sbx kit push` — push to a kit registry
20+
21+ Requirements:
22+ - Validate `kits/ori/spec.yaml` passes `sbx kit validate`
23+ - Package the kit using `sbx kit pack`
24+ - Publish to a registry accessible by `sbx create --kit ori`
25+ - Update documentation (quickstart.md, kits/ori/README.md, docs/*/how-to/run-in-a-sandbox.md)
26+ to reflect the simplified usage
27+
28+ Open questions:
29+ - What registry should be used for publication?
30+ - Does the kit need to be namespaced (e.g., `k33g/ori` or `bots-garden/ori`)?
31+ - Authentication/permissions for pushing to the registry?
32+tasks: []
33+comments: []
new file mode 100644
@@ -0,0 +1,33 @@
1+# Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2+id: 16
3+title: Publish the kit
4+state: open
5+author:
6+ name: k33g
7+ email: ph.charriere@gmail.com
8+createdAt: 2026-09-18T00:00:00.000Z
9+updatedAt: 2026-09-18T00:00:00.000Z
10+labels: []
11+body: |
12+ Publish the ori kit so it can be used via `sbx create claude --kit ori` instead of requiring
13+ a local path `--kit ./kits/ori`.
14+
15+ According to the sbx source exploration (2026-09-17, follow-up 5b in history.md), kits can be
16+ distributed using:
17+ - `sbx kit validate` — validate kit spec
18+ - `sbx kit pack` — package the kit
19+ - `sbx kit push` — push to a kit registry
20+
21+ Requirements:
22+ - Validate `kits/ori/spec.yaml` passes `sbx kit validate`
23+ - Package the kit using `sbx kit pack`
24+ - Publish to a registry accessible by `sbx create --kit ori`
25+ - Update documentation (quickstart.md, kits/ori/README.md, docs/*/how-to/run-in-a-sandbox.md)
26+ to reflect the simplified usage
27+
28+ Open questions:
29+ - What registry should be used for publication?
30+ - Does the kit need to be namespaced (e.g., `k33g/ori` or `bots-garden/ori`)?
31+ - Authentication/permissions for pushing to the registry?
32+tasks: []
33+comments: []
added .tickets/issues/0017-upload-files-with-drag-and-drop.yaml +41 -0
new file mode 100644
@@ -0,0 +1,41 @@
1+# Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2+id: 17
3+title: Upload files with drag and drop
4+state: open
5+author:
6+ name: k33g
7+ email: ph.charriere@gmail.com
8+createdAt: 2026-09-18T00:00:00.000Z
9+updatedAt: 2026-09-18T00:00:00.000Z
10+labels: []
11+body: |
12+ Add the ability to upload files to the workspace using drag and drop.
13+
14+ Requirements:
15+ - Drag and drop files from the host OS into the browser
16+ - Upload files to the workspace directory (under `--cwd`)
17+ - Visual feedback during drag (drop zone highlight)
18+ - Progress indication for uploads
19+ - Support for multiple files
20+ - Support for directories (optional)
21+
22+ Implementation considerations:
23+ - Backend: New endpoint for file uploads (e.g., `POST /api/upload` or extend `PUT /api/file`)
24+ - Frontend: Drag and drop handlers on the workspace panel or file tree
25+ - Should respect the existing 5 MiB file size limit (or adjust if needed)
26+ - Binary file handling (currently rejected with 415)
27+ - Destination path selection (drop on directory vs. root)
28+ - File tree refresh after upload
29+
30+ Related existing functionality:
31+ - `PUT /api/file` already handles file writes (text only, <5 MiB)
32+ - File tree displays the workspace contents
33+ - Binary files currently rejected (415 Unsupported Media Type)
34+
35+ Open questions:
36+ - Allow binary file uploads or keep text-only restriction?
37+ - Maximum total upload size (per request or cumulative)?
38+ - Overwrite confirmation for existing files?
39+ - Should drop target be the entire workspace panel, specific file tree area, or both?
40+tasks: []
41+comments: []
new file mode 100644
@@ -0,0 +1,41 @@
1+# Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2+id: 17
3+title: Upload files with drag and drop
4+state: open
5+author:
6+ name: k33g
7+ email: ph.charriere@gmail.com
8+createdAt: 2026-09-18T00:00:00.000Z
9+updatedAt: 2026-09-18T00:00:00.000Z
10+labels: []
11+body: |
12+ Add the ability to upload files to the workspace using drag and drop.
13+
14+ Requirements:
15+ - Drag and drop files from the host OS into the browser
16+ - Upload files to the workspace directory (under `--cwd`)
17+ - Visual feedback during drag (drop zone highlight)
18+ - Progress indication for uploads
19+ - Support for multiple files
20+ - Support for directories (optional)
21+
22+ Implementation considerations:
23+ - Backend: New endpoint for file uploads (e.g., `POST /api/upload` or extend `PUT /api/file`)
24+ - Frontend: Drag and drop handlers on the workspace panel or file tree
25+ - Should respect the existing 5 MiB file size limit (or adjust if needed)
26+ - Binary file handling (currently rejected with 415)
27+ - Destination path selection (drop on directory vs. root)
28+ - File tree refresh after upload
29+
30+ Related existing functionality:
31+ - `PUT /api/file` already handles file writes (text only, <5 MiB)
32+ - File tree displays the workspace contents
33+ - Binary files currently rejected (415 Unsupported Media Type)
34+
35+ Open questions:
36+ - Allow binary file uploads or keep text-only restriction?
37+ - Maximum total upload size (per request or cumulative)?
38+ - Overwrite confirmation for existing files?
39+ - Should drop target be the entire workspace panel, specific file tree area, or both?
40+tasks: []
41+comments: []
added .tickets/issues/0018-add-btw-command.yaml +86 -0
new file mode 100644
@@ -0,0 +1,86 @@
1+# Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2+id: 18
3+title: Add /btw command
4+state: open
5+author:
6+ name: k33g
7+ email: ph.charriere@gmail.com
8+createdAt: 2026-09-18T00:00:00.000Z
9+updatedAt: 2026-09-18T00:00:00.000Z
10+labels:
11+ - feature
12+ - enhancement
13+body: |
14+ Add a `/btw` (by the way) command to allow users to provide contextual information or side notes to the agent without triggering a full response or workflow.
15+
16+ ## Use Cases
17+
18+ - Provide background information: `/btw I prefer functional programming style`
19+ - Set preferences: `/btw use TypeScript instead of JavaScript when creating new files`
20+ - Add context: `/btw this is a legacy codebase, avoid breaking changes`
21+ - Share constraints: `/btw we're targeting Node 18, don't use newer APIs`
22+ - Note conventions: `/btw we use kebab-case for file names in this project`
23+
24+ ## Requirements
25+
26+ - Command syntax: `/btw <message>`
27+ - Should acknowledge receipt but not trigger full agent response
28+ - Store context in session memory for use in subsequent requests
29+ - Context should persist throughout the session
30+ - Minimal response (e.g., "Noted: <brief echo>")
31+ - Context should be accessible to agent when processing other requests
32+
33+ ## Implementation Considerations
34+
35+ ### Backend
36+ - New command handler in command processing logic
37+ - Session-scoped context store (in-memory per ACP session)
38+ - Context should be included in agent prompts or system messages
39+ - Consider max context size (tokens)
40+
41+ ### Frontend
42+ - Command auto-complete suggestion for `/btw`
43+ - Visual indicator that context was stored (subtle confirmation)
44+ - Optional: Display stored context in UI (sidebar, status bar, or collapsible panel)
45+ - Optional: Command to list current context `/btw list`
46+ - Optional: Command to clear context `/btw clear`
47+
48+ ## Behavior Details
49+
50+ - `/btw` without message should show usage or list current context
51+ - Multiple `/btw` commands should accumulate (not replace)
52+ - Context should be prepended to subsequent agent requests
53+ - Agent should use context passively (consider but don't always mention it)
54+
55+ ## Related Commands
56+
57+ - `/claude <message>` - sends message to agent (full response)
58+ - `/system <message>` - system-level commands
59+ - `/help` - show available commands
60+
61+ ## Open Questions
62+
63+ - Should context persist across sessions (saved to file)?
64+ - Should there be a way to remove specific context items?
65+ - Character/token limit per `/btw` message?
66+ - Should `/btw` be specific to Ori or generalized for ACP?
67+ - Format for displaying accumulated context (list, prose, structured)?
68+
69+ ## Example Interaction
70+
71+ ```
72+ User: /btw I prefer verbose variable names for clarity
73+ Ori: Noted: preference for verbose variable names
74+
75+ User: /btw This project uses ESLint with Airbnb style guide
76+ Ori: Noted: ESLint + Airbnb style guide
77+
78+ User: Add a function to calculate tax
79+ Agent: [creates function with verbose names, following Airbnb conventions]
80+ ```
81+
82+ ## Priority
83+
84+ Medium - Nice to have for improved UX and context management
85+tasks: []
86+comments: []
new file mode 100644
@@ -0,0 +1,86 @@
1+# Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2+id: 18
3+title: Add /btw command
4+state: open
5+author:
6+ name: k33g
7+ email: ph.charriere@gmail.com
8+createdAt: 2026-09-18T00:00:00.000Z
9+updatedAt: 2026-09-18T00:00:00.000Z
10+labels:
11+ - feature
12+ - enhancement
13+body: |
14+ Add a `/btw` (by the way) command to allow users to provide contextual information or side notes to the agent without triggering a full response or workflow.
15+
16+ ## Use Cases
17+
18+ - Provide background information: `/btw I prefer functional programming style`
19+ - Set preferences: `/btw use TypeScript instead of JavaScript when creating new files`
20+ - Add context: `/btw this is a legacy codebase, avoid breaking changes`
21+ - Share constraints: `/btw we're targeting Node 18, don't use newer APIs`
22+ - Note conventions: `/btw we use kebab-case for file names in this project`
23+
24+ ## Requirements
25+
26+ - Command syntax: `/btw <message>`
27+ - Should acknowledge receipt but not trigger full agent response
28+ - Store context in session memory for use in subsequent requests
29+ - Context should persist throughout the session
30+ - Minimal response (e.g., "Noted: <brief echo>")
31+ - Context should be accessible to agent when processing other requests
32+
33+ ## Implementation Considerations
34+
35+ ### Backend
36+ - New command handler in command processing logic
37+ - Session-scoped context store (in-memory per ACP session)
38+ - Context should be included in agent prompts or system messages
39+ - Consider max context size (tokens)
40+
41+ ### Frontend
42+ - Command auto-complete suggestion for `/btw`
43+ - Visual indicator that context was stored (subtle confirmation)
44+ - Optional: Display stored context in UI (sidebar, status bar, or collapsible panel)
45+ - Optional: Command to list current context `/btw list`
46+ - Optional: Command to clear context `/btw clear`
47+
48+ ## Behavior Details
49+
50+ - `/btw` without message should show usage or list current context
51+ - Multiple `/btw` commands should accumulate (not replace)
52+ - Context should be prepended to subsequent agent requests
53+ - Agent should use context passively (consider but don't always mention it)
54+
55+ ## Related Commands
56+
57+ - `/claude <message>` - sends message to agent (full response)
58+ - `/system <message>` - system-level commands
59+ - `/help` - show available commands
60+
61+ ## Open Questions
62+
63+ - Should context persist across sessions (saved to file)?
64+ - Should there be a way to remove specific context items?
65+ - Character/token limit per `/btw` message?
66+ - Should `/btw` be specific to Ori or generalized for ACP?
67+ - Format for displaying accumulated context (list, prose, structured)?
68+
69+ ## Example Interaction
70+
71+ ```
72+ User: /btw I prefer verbose variable names for clarity
73+ Ori: Noted: preference for verbose variable names
74+
75+ User: /btw This project uses ESLint with Airbnb style guide
76+ Ori: Noted: ESLint + Airbnb style guide
77+
78+ User: Add a function to calculate tax
79+ Agent: [creates function with verbose names, following Airbnb conventions]
80+ ```
81+
82+ ## Priority
83+
84+ Medium - Nice to have for improved UX and context management
85+tasks: []
86+comments: []
added .tickets/issues/0019-start-and-monitor-agents-from-ori.yaml +149 -0
new file mode 100644
@@ -0,0 +1,149 @@
1+# Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2+id: 19
3+title: Start and monitor agents from Ori
4+state: open
5+author:
6+ name: k33g
7+ email: ph.charriere@gmail.com
8+createdAt: 2026-09-18T00:00:00.000Z
9+updatedAt: 2026-09-18T00:00:00.000Z
10+labels:
11+ - feature
12+ - enhancement
13+ - agents
14+body: |
15+ Add the ability to start multiple independent agents from Ori and monitor their progress in real-time.
16+
17+ ## Use Cases
18+
19+ - Start parallel agents with different tasks: "agent bob: write a story about X" and "agent rikker: write a story about Y"
20+ - Monitor multiple long-running agents simultaneously
21+ - Track agent progress, tool calls, and outputs in separate views
22+ - Stop/pause/resume individual agents
23+ - Review agent results when complete
24+
25+ ## Requirements
26+
27+ ### Agent Lifecycle
28+ - Command syntax: `agent <name>: <task>` or `/agent <name> <task>`
29+ - Each agent gets a unique identifier/name
30+ - Agents run independently in parallel (like Task tool with run_in_background)
31+ - Agents persist across Ori sessions (survive page refresh)
32+ - Clear indication when agent starts, is running, completes, or errors
33+
34+ ### Monitoring & Visibility
35+ - Real-time display of what each agent is doing
36+ - Stream agent thoughts, tool calls, and outputs as they happen
37+ - Show agent status: queued, running, paused, completed, failed
38+ - Visual distinction between agents (colors, avatars, icons)
39+ - Ability to expand/collapse agent views
40+ - Notification when agent completes or encounters error
41+
42+ ### Control & Interaction
43+ - Pause/resume individual agents
44+ - Stop/terminate agents
45+ - Respond to agent questions/prompts individually
46+ - View full agent conversation history
47+ - Export/save agent results
48+ - Restart failed agents
49+
50+ ## Implementation Considerations
51+
52+ ### Backend
53+ - Extend ACP protocol or use existing Task tool capabilities
54+ - Each agent needs its own ACP session or isolated execution context
55+ - Agent state persistence (in-memory or file-based)
56+ - Agent output streaming (SSE, WebSocket, or polling)
57+ - Resource limits per agent (memory, CPU, timeout)
58+ - Queue management if too many agents requested
59+
60+ ### Frontend UI Options
61+
62+ **Option 1: Tabbed Agent Panel**
63+ - Each agent gets its own tab
64+ - Active tab shows streaming output
65+ - Tab indicators show agent status (spinner, checkmark, error icon)
66+ - Similar to browser tabs or VS Code terminal tabs
67+
68+ **Option 2: Split View**
69+ - Vertical or horizontal splits
70+ - Each pane shows one agent
71+ - Resize panes to focus on specific agents
72+ - Similar to tmux or terminal multiplexers
73+
74+ **Option 3: Agent Dashboard**
75+ - Grid or list view of all active agents
76+ - Cards show agent name, status, last output
77+ - Click card to expand to full view
78+ - Similar to task/process managers
79+
80+ **Option 4: Unified Stream with Filtering**
81+ - All agent outputs in single stream
82+ - Color-coded or labeled by agent name
83+ - Filter controls to show/hide specific agents
84+ - Similar to multi-tail log viewers
85+
86+ ### ACP Integration
87+ - Leverage existing ACP streaming capabilities
88+ - Use Task tool with run_in_background: true
89+ - Poll TaskOutput for agent progress
90+ - Or implement new ACP commands: `start_agent`, `list_agents`, `stop_agent`
91+
92+ ## User Experience Flow
93+
94+ ```
95+ User: agent bob: write a story about Jean-Luc Picard
96+ User: agent rikker: write a story about Seven of Nine
97+
98+ UI: Shows two agent cards/tabs:
99+ [Bob] ⏳ Writing story... (thought: searching for Picard references)
100+ [Rikker] ⏳ Writing story... (thought: analyzing Seven's character arc)
101+
102+ User: *clicks Bob's card to expand*
103+ UI: Shows full streaming output of Bob's work
104+
105+ User: *Bob completes*
106+ UI: [Bob] ✓ Complete - picard-story.md created
107+
108+ User: /agents list
109+ UI:
110+ - bob: completed (2 min ago) - picard-story.md
111+ - rikker: running (3/5 tasks complete)
112+ ```
113+
114+ ## Related Features
115+
116+ - Could integrate with `/btw` command for agent-specific context
117+ - Agent results could appear in file tree automatically
118+ - Terminal panel could show agent bash commands
119+ - Could support agent-to-agent communication (advanced)
120+
121+ ## Open Questions
122+
123+ - Maximum number of concurrent agents?
124+ - Should agents share workspace context or be isolated?
125+ - How to handle agent conflicts (both editing same file)?
126+ - Should agents see each other's outputs?
127+ - Pricing/cost implications of multiple parallel agents?
128+ - Should agent names be user-defined or auto-generated?
129+ - Persist agent history across Ori restarts?
130+ - Should there be agent templates/presets?
131+
132+ ## Technical Challenges
133+
134+ - Resource management with multiple Claude API calls
135+ - State synchronization between backend and frontend
136+ - File system conflicts when multiple agents write
137+ - Error handling and recovery for individual agents
138+ - Performance impact of streaming multiple outputs
139+
140+ ## Priority
141+
142+ High - This would be a differentiating feature for Ori as a multi-agent orchestration tool
143+
144+ ## Related Work
145+
146+ - Claude Code's Task tool with run_in_background
147+ - Aider's architect mode
148+ - AutoGPT/BabyAGI multi-agent systems
149+ - LangChain agent executors
new file mode 100644
@@ -0,0 +1,149 @@
1+# Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2+id: 19
3+title: Start and monitor agents from Ori
4+state: open
5+author:
6+ name: k33g
7+ email: ph.charriere@gmail.com
8+createdAt: 2026-09-18T00:00:00.000Z
9+updatedAt: 2026-09-18T00:00:00.000Z
10+labels:
11+ - feature
12+ - enhancement
13+ - agents
14+body: |
15+ Add the ability to start multiple independent agents from Ori and monitor their progress in real-time.
16+
17+ ## Use Cases
18+
19+ - Start parallel agents with different tasks: "agent bob: write a story about X" and "agent rikker: write a story about Y"
20+ - Monitor multiple long-running agents simultaneously
21+ - Track agent progress, tool calls, and outputs in separate views
22+ - Stop/pause/resume individual agents
23+ - Review agent results when complete
24+
25+ ## Requirements
26+
27+ ### Agent Lifecycle
28+ - Command syntax: `agent <name>: <task>` or `/agent <name> <task>`
29+ - Each agent gets a unique identifier/name
30+ - Agents run independently in parallel (like Task tool with run_in_background)
31+ - Agents persist across Ori sessions (survive page refresh)
32+ - Clear indication when agent starts, is running, completes, or errors
33+
34+ ### Monitoring & Visibility
35+ - Real-time display of what each agent is doing
36+ - Stream agent thoughts, tool calls, and outputs as they happen
37+ - Show agent status: queued, running, paused, completed, failed
38+ - Visual distinction between agents (colors, avatars, icons)
39+ - Ability to expand/collapse agent views
40+ - Notification when agent completes or encounters error
41+
42+ ### Control & Interaction
43+ - Pause/resume individual agents
44+ - Stop/terminate agents
45+ - Respond to agent questions/prompts individually
46+ - View full agent conversation history
47+ - Export/save agent results
48+ - Restart failed agents
49+
50+ ## Implementation Considerations
51+
52+ ### Backend
53+ - Extend ACP protocol or use existing Task tool capabilities
54+ - Each agent needs its own ACP session or isolated execution context
55+ - Agent state persistence (in-memory or file-based)
56+ - Agent output streaming (SSE, WebSocket, or polling)
57+ - Resource limits per agent (memory, CPU, timeout)
58+ - Queue management if too many agents requested
59+
60+ ### Frontend UI Options
61+
62+ **Option 1: Tabbed Agent Panel**
63+ - Each agent gets its own tab
64+ - Active tab shows streaming output
65+ - Tab indicators show agent status (spinner, checkmark, error icon)
66+ - Similar to browser tabs or VS Code terminal tabs
67+
68+ **Option 2: Split View**
69+ - Vertical or horizontal splits
70+ - Each pane shows one agent
71+ - Resize panes to focus on specific agents
72+ - Similar to tmux or terminal multiplexers
73+
74+ **Option 3: Agent Dashboard**
75+ - Grid or list view of all active agents
76+ - Cards show agent name, status, last output
77+ - Click card to expand to full view
78+ - Similar to task/process managers
79+
80+ **Option 4: Unified Stream with Filtering**
81+ - All agent outputs in single stream
82+ - Color-coded or labeled by agent name
83+ - Filter controls to show/hide specific agents
84+ - Similar to multi-tail log viewers
85+
86+ ### ACP Integration
87+ - Leverage existing ACP streaming capabilities
88+ - Use Task tool with run_in_background: true
89+ - Poll TaskOutput for agent progress
90+ - Or implement new ACP commands: `start_agent`, `list_agents`, `stop_agent`
91+
92+ ## User Experience Flow
93+
94+ ```
95+ User: agent bob: write a story about Jean-Luc Picard
96+ User: agent rikker: write a story about Seven of Nine
97+
98+ UI: Shows two agent cards/tabs:
99+ [Bob] ⏳ Writing story... (thought: searching for Picard references)
100+ [Rikker] ⏳ Writing story... (thought: analyzing Seven's character arc)
101+
102+ User: *clicks Bob's card to expand*
103+ UI: Shows full streaming output of Bob's work
104+
105+ User: *Bob completes*
106+ UI: [Bob] ✓ Complete - picard-story.md created
107+
108+ User: /agents list
109+ UI:
110+ - bob: completed (2 min ago) - picard-story.md
111+ - rikker: running (3/5 tasks complete)
112+ ```
113+
114+ ## Related Features
115+
116+ - Could integrate with `/btw` command for agent-specific context
117+ - Agent results could appear in file tree automatically
118+ - Terminal panel could show agent bash commands
119+ - Could support agent-to-agent communication (advanced)
120+
121+ ## Open Questions
122+
123+ - Maximum number of concurrent agents?
124+ - Should agents share workspace context or be isolated?
125+ - How to handle agent conflicts (both editing same file)?
126+ - Should agents see each other's outputs?
127+ - Pricing/cost implications of multiple parallel agents?
128+ - Should agent names be user-defined or auto-generated?
129+ - Persist agent history across Ori restarts?
130+ - Should there be agent templates/presets?
131+
132+ ## Technical Challenges
133+
134+ - Resource management with multiple Claude API calls
135+ - State synchronization between backend and frontend
136+ - File system conflicts when multiple agents write
137+ - Error handling and recovery for individual agents
138+ - Performance impact of streaming multiple outputs
139+
140+ ## Priority
141+
142+ High - This would be a differentiating feature for Ori as a multi-agent orchestration tool
143+
144+ ## Related Work
145+
146+ - Claude Code's Task tool with run_in_background
147+ - Aider's architect mode
148+ - AutoGPT/BabyAGI multi-agent systems
149+ - LangChain agent executors
added .tickets/issues/0020-add-more-ui-themes.yaml +217 -0
new file mode 100644
@@ -0,0 +1,217 @@
1+# Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2+id: 20
3+title: Add more UI themes
4+state: open
5+author:
6+ name: k33g
7+ email: ph.charriere@gmail.com
8+createdAt: 2026-09-18T00:00:00.000Z
9+updatedAt: 2026-09-18T00:00:00.000Z
10+labels:
11+ - feature
12+ - enhancement
13+ - ui
14+ - theming
15+body: |
16+ Expand the current light/dark theme system to support multiple color themes and color schemes.
17+
18+ ## Current State
19+
20+ Based on ticket #0013, Ori currently has:
21+ - Light theme
22+ - Dark theme
23+ - Theme toggle functionality
24+
25+ ## Proposed Themes
26+
27+ ### Popular Editor Themes
28+ - **Dracula** - Dark purple-based theme (very popular)
29+ - **Solarized Light** - Warm beige-based light theme
30+ - **Solarized Dark** - Dark teal-based theme
31+ - **Monokai** - Dark theme with vibrant colors
32+ - **Nord** - Cool blue/gray theme
33+ - **One Dark** - Atom's dark theme
34+ - **One Light** - Atom's light theme
35+ - **GitHub Light** - GitHub's light theme
36+ - **GitHub Dark** - GitHub's dark theme
37+ - **Gruvbox** - Warm retro groove colors
38+ - **Material Theme** - Google Material Design inspired
39+ - **Night Owl** - Dark theme optimized for night coding
40+
41+ ### VS Code Compatible
42+ - Import popular VS Code themes
43+ - Support VS Code theme JSON format
44+ - Allow users to load custom .vsix themes
45+
46+ ### High Contrast Options
47+ - High Contrast Light (accessibility)
48+ - High Contrast Dark (accessibility)
49+ - WCAG AAA compliant color combinations
50+
51+ ### Colorblind-Friendly
52+ - Deuteranopia (red-green colorblind) friendly
53+ - Protanopia friendly
54+ - Tritanopia (blue-yellow colorblind) friendly
55+
56+ ## Requirements
57+
58+ ### Theme Management
59+ - Theme selector in settings/preferences
60+ - Preview themes before applying
61+ - Persist selected theme across sessions
62+ - Quick theme switcher (dropdown or command palette)
63+ - Theme applies to entire UI (panels, editor, terminal)
64+
65+ ### Theme Components
66+ Each theme should define:
67+ - Background colors (primary, secondary, tertiary)
68+ - Foreground/text colors
69+ - Syntax highlighting colors (keywords, strings, comments, etc.)
70+ - UI element colors (borders, dividers, shadows)
71+ - Status colors (info, success, warning, error)
72+ - Selection/highlight colors
73+ - Terminal colors (16-color palette)
74+
75+ ### Monaco Editor Integration
76+ - Themes must work with Monaco editor
77+ - Support for semantic highlighting
78+ - Consistent colors between UI and code editor
79+ - Import Monaco/VS Code theme definitions
80+
81+ ## Implementation Considerations
82+
83+ ### Frontend Architecture
84+ - CSS custom properties (variables) for easy theme switching
85+ - Theme configuration in JSON/JavaScript
86+ - Dynamic CSS injection or class-based switching
87+ - Tailwind CSS theme extension (if using Tailwind)
88+
89+ ### Theme File Structure
90+ ```
91+ themes/
92+ ├── dracula.json
93+ ├── solarized-light.json
94+ ├── nord.json
95+ └── custom/
96+ └── user-theme.json
97+ ```
98+
99+ ### Theme Definition Format
100+ ```json
101+ {
102+ "name": "Dracula",
103+ "type": "dark",
104+ "colors": {
105+ "background": "#282a36",
106+ "foreground": "#f8f8f2",
107+ "primary": "#bd93f9",
108+ "secondary": "#ff79c6",
109+ "accent": "#50fa7b",
110+ "border": "#44475a",
111+ "selection": "#44475a",
112+ "error": "#ff5555",
113+ "warning": "#ffb86c",
114+ "success": "#50fa7b",
115+ "info": "#8be9fd"
116+ },
117+ "syntax": {
118+ "keyword": "#ff79c6",
119+ "string": "#f1fa8c",
120+ "comment": "#6272a4",
121+ "function": "#50fa7b",
122+ "variable": "#f8f8f2",
123+ "number": "#bd93f9",
124+ "operator": "#ff79c6"
125+ },
126+ "terminal": {
127+ "black": "#21222c",
128+ "red": "#ff5555",
129+ "green": "#50fa7b",
130+ ...
131+ }
132+ }
133+ ```
134+
135+ ### Custom Theme Support
136+ - Allow users to upload custom themes
137+ - Theme editor/creator UI (advanced)
138+ - Export current theme as JSON
139+ - Share themes via URL or file
140+
141+ ## User Experience
142+
143+ ### Theme Switcher UI Options
144+ 1. **Dropdown in toolbar** - Quick access, always visible
145+ 2. **Settings panel** - More detailed, with preview
146+ 3. **Command palette** - `/theme <name>` command
147+ 4. **Keyboard shortcut** - Cycle through themes (Cmd+K T)
148+
149+ ### Preview Before Apply
150+ - Show theme preview in modal/sidebar
151+ - Split view: current vs. new theme
152+ - Live preview without committing
153+ - Preview on hover (theme gallery)
154+
155+ ### Theme Categories
156+ - Group themes: Light, Dark, High Contrast, Colorblind-Friendly
157+ - Filter/search themes by name or characteristics
158+ - Mark favorite themes
159+ - Recently used themes
160+
161+ ## Accessibility Considerations
162+
163+ - WCAG 2.1 AA minimum contrast ratios
164+ - AAA compliance for high contrast themes
165+ - Colorblind simulation/testing tools
166+ - Screen reader announcements for theme changes
167+ - Respect system preferences (prefers-color-scheme, prefers-contrast)
168+
169+ ## Related Features
170+
171+ - Could integrate with `/btw theme dracula` command
172+ - Auto-switch based on time of day (optional)
173+ - Sync theme with OS system theme
174+ - Per-workspace theme preferences
175+ - Theme marketplace/gallery (future)
176+
177+ ## Migration Path
178+
179+ - Existing light/dark themes become "Default Light" and "Default Dark"
180+ - Current theme setting preserved
181+ - Gradual rollout of new themes
182+ - Theme compatibility version checking
183+
184+ ## Open Questions
185+
186+ - Should terminal colors be part of theme or separate?
187+ - Support for theme-specific fonts?
188+ - Allow per-file-type theme overrides?
189+ - Should themes affect Monaco editor minimap colors?
190+ - Support for animated theme transitions?
191+ - Should there be a "theme of the day" feature?
192+ - Community theme submissions/repository?
193+
194+ ## Technical Challenges
195+
196+ - Ensuring consistent colors across all UI components
197+ - Performance impact of theme switching (CSS recalculation)
198+ - Monaco editor theme format conversion
199+ - Terminal emulator color scheme integration
200+ - Testing all themes for accessibility compliance
201+ - Managing theme asset size (bundle size optimization)
202+
203+ ## Priority
204+
205+ Medium - Nice to have for personalization and accessibility
206+
207+ ## Related Issues
208+
209+ - #0013 - Themes: light and dark (completed)
210+
211+ ## Inspiration
212+
213+ - VS Code theme marketplace
214+ - JetBrains IDE themes
215+ - Zed editor themes
216+ - iTerm2 color schemes
217+ - Hyper terminal themes
new file mode 100644
@@ -0,0 +1,217 @@
1+# Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2+id: 20
3+title: Add more UI themes
4+state: open
5+author:
6+ name: k33g
7+ email: ph.charriere@gmail.com
8+createdAt: 2026-09-18T00:00:00.000Z
9+updatedAt: 2026-09-18T00:00:00.000Z
10+labels:
11+ - feature
12+ - enhancement
13+ - ui
14+ - theming
15+body: |
16+ Expand the current light/dark theme system to support multiple color themes and color schemes.
17+
18+ ## Current State
19+
20+ Based on ticket #0013, Ori currently has:
21+ - Light theme
22+ - Dark theme
23+ - Theme toggle functionality
24+
25+ ## Proposed Themes
26+
27+ ### Popular Editor Themes
28+ - **Dracula** - Dark purple-based theme (very popular)
29+ - **Solarized Light** - Warm beige-based light theme
30+ - **Solarized Dark** - Dark teal-based theme
31+ - **Monokai** - Dark theme with vibrant colors
32+ - **Nord** - Cool blue/gray theme
33+ - **One Dark** - Atom's dark theme
34+ - **One Light** - Atom's light theme
35+ - **GitHub Light** - GitHub's light theme
36+ - **GitHub Dark** - GitHub's dark theme
37+ - **Gruvbox** - Warm retro groove colors
38+ - **Material Theme** - Google Material Design inspired
39+ - **Night Owl** - Dark theme optimized for night coding
40+
41+ ### VS Code Compatible
42+ - Import popular VS Code themes
43+ - Support VS Code theme JSON format
44+ - Allow users to load custom .vsix themes
45+
46+ ### High Contrast Options
47+ - High Contrast Light (accessibility)
48+ - High Contrast Dark (accessibility)
49+ - WCAG AAA compliant color combinations
50+
51+ ### Colorblind-Friendly
52+ - Deuteranopia (red-green colorblind) friendly
53+ - Protanopia friendly
54+ - Tritanopia (blue-yellow colorblind) friendly
55+
56+ ## Requirements
57+
58+ ### Theme Management
59+ - Theme selector in settings/preferences
60+ - Preview themes before applying
61+ - Persist selected theme across sessions
62+ - Quick theme switcher (dropdown or command palette)
63+ - Theme applies to entire UI (panels, editor, terminal)
64+
65+ ### Theme Components
66+ Each theme should define:
67+ - Background colors (primary, secondary, tertiary)
68+ - Foreground/text colors
69+ - Syntax highlighting colors (keywords, strings, comments, etc.)
70+ - UI element colors (borders, dividers, shadows)
71+ - Status colors (info, success, warning, error)
72+ - Selection/highlight colors
73+ - Terminal colors (16-color palette)
74+
75+ ### Monaco Editor Integration
76+ - Themes must work with Monaco editor
77+ - Support for semantic highlighting
78+ - Consistent colors between UI and code editor
79+ - Import Monaco/VS Code theme definitions
80+
81+ ## Implementation Considerations
82+
83+ ### Frontend Architecture
84+ - CSS custom properties (variables) for easy theme switching
85+ - Theme configuration in JSON/JavaScript
86+ - Dynamic CSS injection or class-based switching
87+ - Tailwind CSS theme extension (if using Tailwind)
88+
89+ ### Theme File Structure
90+ ```
91+ themes/
92+ ├── dracula.json
93+ ├── solarized-light.json
94+ ├── nord.json
95+ └── custom/
96+ └── user-theme.json
97+ ```
98+
99+ ### Theme Definition Format
100+ ```json
101+ {
102+ "name": "Dracula",
103+ "type": "dark",
104+ "colors": {
105+ "background": "#282a36",
106+ "foreground": "#f8f8f2",
107+ "primary": "#bd93f9",
108+ "secondary": "#ff79c6",
109+ "accent": "#50fa7b",
110+ "border": "#44475a",
111+ "selection": "#44475a",
112+ "error": "#ff5555",
113+ "warning": "#ffb86c",
114+ "success": "#50fa7b",
115+ "info": "#8be9fd"
116+ },
117+ "syntax": {
118+ "keyword": "#ff79c6",
119+ "string": "#f1fa8c",
120+ "comment": "#6272a4",
121+ "function": "#50fa7b",
122+ "variable": "#f8f8f2",
123+ "number": "#bd93f9",
124+ "operator": "#ff79c6"
125+ },
126+ "terminal": {
127+ "black": "#21222c",
128+ "red": "#ff5555",
129+ "green": "#50fa7b",
130+ ...
131+ }
132+ }
133+ ```
134+
135+ ### Custom Theme Support
136+ - Allow users to upload custom themes
137+ - Theme editor/creator UI (advanced)
138+ - Export current theme as JSON
139+ - Share themes via URL or file
140+
141+ ## User Experience
142+
143+ ### Theme Switcher UI Options
144+ 1. **Dropdown in toolbar** - Quick access, always visible
145+ 2. **Settings panel** - More detailed, with preview
146+ 3. **Command palette** - `/theme <name>` command
147+ 4. **Keyboard shortcut** - Cycle through themes (Cmd+K T)
148+
149+ ### Preview Before Apply
150+ - Show theme preview in modal/sidebar
151+ - Split view: current vs. new theme
152+ - Live preview without committing
153+ - Preview on hover (theme gallery)
154+
155+ ### Theme Categories
156+ - Group themes: Light, Dark, High Contrast, Colorblind-Friendly
157+ - Filter/search themes by name or characteristics
158+ - Mark favorite themes
159+ - Recently used themes
160+
161+ ## Accessibility Considerations
162+
163+ - WCAG 2.1 AA minimum contrast ratios
164+ - AAA compliance for high contrast themes
165+ - Colorblind simulation/testing tools
166+ - Screen reader announcements for theme changes
167+ - Respect system preferences (prefers-color-scheme, prefers-contrast)
168+
169+ ## Related Features
170+
171+ - Could integrate with `/btw theme dracula` command
172+ - Auto-switch based on time of day (optional)
173+ - Sync theme with OS system theme
174+ - Per-workspace theme preferences
175+ - Theme marketplace/gallery (future)
176+
177+ ## Migration Path
178+
179+ - Existing light/dark themes become "Default Light" and "Default Dark"
180+ - Current theme setting preserved
181+ - Gradual rollout of new themes
182+ - Theme compatibility version checking
183+
184+ ## Open Questions
185+
186+ - Should terminal colors be part of theme or separate?
187+ - Support for theme-specific fonts?
188+ - Allow per-file-type theme overrides?
189+ - Should themes affect Monaco editor minimap colors?
190+ - Support for animated theme transitions?
191+ - Should there be a "theme of the day" feature?
192+ - Community theme submissions/repository?
193+
194+ ## Technical Challenges
195+
196+ - Ensuring consistent colors across all UI components
197+ - Performance impact of theme switching (CSS recalculation)
198+ - Monaco editor theme format conversion
199+ - Terminal emulator color scheme integration
200+ - Testing all themes for accessibility compliance
201+ - Managing theme asset size (bundle size optimization)
202+
203+ ## Priority
204+
205+ Medium - Nice to have for personalization and accessibility
206+
207+ ## Related Issues
208+
209+ - #0013 - Themes: light and dark (completed)
210+
211+ ## Inspiration
212+
213+ - VS Code theme marketplace
214+ - JetBrains IDE themes
215+ - Zed editor themes
216+ - iTerm2 color schemes
217+ - Hyper terminal themes
modified README.md +9 -5
@@ -5,14 +5,18 @@ Ori is a web client for [ACP (Agent Client Protocol)](https://agentclientprotoco
55
66 ## Quick start
77
8+From the directory where the kit lives, pointing at the project you want the agent to work on:
9+
810 ```bash
9-make deps # install frontend dependencies
10-make run-mock # build everything and start on :8888 with the bundled demo agent (no Claude needed)
11-make run # same, but connected to Claude Code via npx @zed-industries/claude-code-acp
12-make test # run the Go and frontend test suites
11+sbx run -d claude ~/path/to/your/project \
12+ --template k33g/ori:0.0.0 \
13+ --kit ./kits/ori \
14+ --name ori \
15+ -p 8888:8888
1316 ```
1417
15-Then open [http://localhost:8888](http://localhost:8888).
18+Then open **http://localhost:8888** — the panel connects to a Claude Code session already running in the sandbox, no login needed.
19+
1620
1721 ## Documentation
1822
@@ -5,14 +5,18 @@ Ori is a web client for [ACP (Agent Client Protocol)](https://agentclientprotoco
5 5
6 ## Quick start6 ## Quick start
7 7
8+From the directory where the kit lives, pointing at the project you want the agent to work on:
9+
8 ```bash10 ```bash
9-make deps # install frontend dependencies11+sbx run -d claude ~/path/to/your/project \
10-make run-mock # build everything and start on :8888 with the bundled demo agent (no Claude needed)12+ --template k33g/ori:0.0.0 \
11-make run # same, but connected to Claude Code via npx @zed-industries/claude-code-acp13+ --kit ./kits/ori \
12-make test # run the Go and frontend test suites14+ --name ori \
15+ -p 8888:8888
13 ```16 ```
14 17
15-Then open [http://localhost:8888](http://localhost:8888).18+Then open **http://localhost:8888** — the panel connects to a Claude Code session already running in the sandbox, no login needed.
19+
16 20
17 ## Documentation21 ## Documentation
18 22
added picard-story.md +33 -0
new file mode 100644
@@ -0,0 +1,33 @@
1+# The Archaeologist's Gambit
2+
3+**Agent: Bob**
4+
5+Captain Jean-Luc Picard stood before the ancient artifact, his fingers hovering millimeters above its surface. The crystalline structure pulsed with a faint amber glow, responding to his proximity like a living thing.
6+
7+"Captain, I must advise caution," Data said from behind him, his golden eyes scanning the tricorder readings. "The energy signature is unlike anything in our database."
8+
9+Picard's lips curved into a slight smile. "Mr. Data, in my experience, the most profound discoveries often lie beyond the boundaries of our databases."
10+
11+They were deep within the ruins of Kataan—not the Kataan of his inner light experience, but its sister colony, hidden for millennia beneath the ice sheets of Delta Sigma IV. The Federation archaeological survey had discovered it three weeks ago, and Picard had been unable to resist the opportunity to lead the away team himself.
12+
13+"This script," Picard murmured, tracing the air above the inscriptions that spiraled around the artifact's base, "is Kataan, but it's... older. More refined than what I learned."
14+
15+He closed his eyes, and for a moment, he was Kamin again—the memories of that life as vivid as his actual past. The flute music, the sun on his face, Eline's laugh. A life lived in forty minutes that had shaped him forever.
16+
17+"It's a beacon," Picard said suddenly, his eyes opening. "Not a warning, but an invitation. The Kataan people knew their sun was dying. They sent out their culture, their memories, in multiple forms. We found one—the probe that found me. But this... this is something more."
18+
19+"More?" Commander Riker's voice crackled through the comm badge. "Captain, you're already talking about a civilization that downloaded an entire lifetime into your brain. What could be 'more' than that?"
20+
21+Picard's hand finally made contact with the artifact. The amber light exploded into a cascade of images—not memories this time, but pure information. Mathematics. Philosophy. Art. The complete accumulated knowledge of a civilization.
22+
23+"Number One," Picard said, his voice thick with emotion, "prepare to download approximately four hundred exabytes of data. The Kataan didn't just want to be remembered—they wanted to teach. This is their university, their library, their gift to whoever would listen."
24+
25+As Data began the careful transfer, Picard stood back, one hand unconsciously moving to his uniform jacket pocket where he kept Kamin's flute. He had been given a life once by the Kataan people. Now, they were giving him—giving humanity—the tools to understand that life and countless others.
26+
27+"Make it so," he whispered to himself, a small smile playing at the corners of his mouth.
28+
29+The Enterprise would be here for weeks, perhaps months, cataloging this discovery. And for once, Jean-Luc Picard, who had always believed that to boldly go meant to leave and explore further, was content to stay still and listen to the voices of the past.
30+
31+---
32+
33+*Captain's Log, Supplemental: The Kataan archive is beyond anything I imagined. In seeking to preserve themselves, they may have given us the key to understanding dozens of lost civilizations. I find myself wondering: how many other ancient peoples left such gifts among the stars, waiting for someone to stop and listen? Perhaps the greatest exploration is not in discovering new worlds, but in understanding those that came before us.*
new file mode 100644
@@ -0,0 +1,33 @@
1+# The Archaeologist's Gambit
2+
3+**Agent: Bob**
4+
5+Captain Jean-Luc Picard stood before the ancient artifact, his fingers hovering millimeters above its surface. The crystalline structure pulsed with a faint amber glow, responding to his proximity like a living thing.
6+
7+"Captain, I must advise caution," Data said from behind him, his golden eyes scanning the tricorder readings. "The energy signature is unlike anything in our database."
8+
9+Picard's lips curved into a slight smile. "Mr. Data, in my experience, the most profound discoveries often lie beyond the boundaries of our databases."
10+
11+They were deep within the ruins of Kataan—not the Kataan of his inner light experience, but its sister colony, hidden for millennia beneath the ice sheets of Delta Sigma IV. The Federation archaeological survey had discovered it three weeks ago, and Picard had been unable to resist the opportunity to lead the away team himself.
12+
13+"This script," Picard murmured, tracing the air above the inscriptions that spiraled around the artifact's base, "is Kataan, but it's... older. More refined than what I learned."
14+
15+He closed his eyes, and for a moment, he was Kamin again—the memories of that life as vivid as his actual past. The flute music, the sun on his face, Eline's laugh. A life lived in forty minutes that had shaped him forever.
16+
17+"It's a beacon," Picard said suddenly, his eyes opening. "Not a warning, but an invitation. The Kataan people knew their sun was dying. They sent out their culture, their memories, in multiple forms. We found one—the probe that found me. But this... this is something more."
18+
19+"More?" Commander Riker's voice crackled through the comm badge. "Captain, you're already talking about a civilization that downloaded an entire lifetime into your brain. What could be 'more' than that?"
20+
21+Picard's hand finally made contact with the artifact. The amber light exploded into a cascade of images—not memories this time, but pure information. Mathematics. Philosophy. Art. The complete accumulated knowledge of a civilization.
22+
23+"Number One," Picard said, his voice thick with emotion, "prepare to download approximately four hundred exabytes of data. The Kataan didn't just want to be remembered—they wanted to teach. This is their university, their library, their gift to whoever would listen."
24+
25+As Data began the careful transfer, Picard stood back, one hand unconsciously moving to his uniform jacket pocket where he kept Kamin's flute. He had been given a life once by the Kataan people. Now, they were giving him—giving humanity—the tools to understand that life and countless others.
26+
27+"Make it so," he whispered to himself, a small smile playing at the corners of his mouth.
28+
29+The Enterprise would be here for weeks, perhaps months, cataloging this discovery. And for once, Jean-Luc Picard, who had always believed that to boldly go meant to leave and explore further, was content to stay still and listen to the voices of the past.
30+
31+---
32+
33+*Captain's Log, Supplemental: The Kataan archive is beyond anything I imagined. In seeking to preserve themselves, they may have given us the key to understanding dozens of lost civilizations. I find myself wondering: how many other ancient peoples left such gifts among the stars, waiting for someone to stop and listen? Perhaps the greatest exploration is not in discovering new worlds, but in understanding those that came before us.*
modified quickstart.md +2 -1
@@ -42,6 +42,7 @@ Without `-p`, the kit still publishes an ephemeral port; the command output prin
4242 | Attach the terminal Claude session (starts a stopped sandbox) | `sbx attach ori` |
4343 | Restart a stopped sandbox without attaching | `sbx run -d --name ori` |
4444 | Stop / remove | `sbx stop ori` · `sbx rm ori` |
45+| Start (or restart) the sandbox and open ori-desktop in one go | `osascript scripts/launch-ori.applescript` — or a double-clickable app, see [scripts/README.md](scripts/README.md) |
4546 | Demo without Claude usage | `sbx exec ori sh -c 'pkill -x ori; nohup ori --addr :8888 --agent-cmd ori-mock-agent --cwd /home/agent/workspace >> /home/agent/.ori.log 2>&1 &'` |
4647
4748 ## Building the image yourself
@@ -68,7 +69,7 @@ sbx run -d claude . \
6869 sbx run -d claude . \
6970 --template k33g/ori:0.0.1 \
7071 --kit ./kits/ori \
71- --name ori2 \
72+ --name ori \
7273 -p 5555:8888
7374 ```
7475
@@ -42,6 +42,7 @@ Without `-p`, the kit still publishes an ephemeral port; the command output prin
42 | Attach the terminal Claude session (starts a stopped sandbox) | `sbx attach ori` |42 | Attach the terminal Claude session (starts a stopped sandbox) | `sbx attach ori` |
43 | Restart a stopped sandbox without attaching | `sbx run -d --name ori` |43 | Restart a stopped sandbox without attaching | `sbx run -d --name ori` |
44 | Stop / remove | `sbx stop ori` · `sbx rm ori` |44 | Stop / remove | `sbx stop ori` · `sbx rm ori` |
45+| Start (or restart) the sandbox and open ori-desktop in one go | `osascript scripts/launch-ori.applescript` — or a double-clickable app, see [scripts/README.md](scripts/README.md) |
45 | Demo without Claude usage | `sbx exec ori sh -c 'pkill -x ori; nohup ori --addr :8888 --agent-cmd ori-mock-agent --cwd /home/agent/workspace >> /home/agent/.ori.log 2>&1 &'` |46 | Demo without Claude usage | `sbx exec ori sh -c 'pkill -x ori; nohup ori --addr :8888 --agent-cmd ori-mock-agent --cwd /home/agent/workspace >> /home/agent/.ori.log 2>&1 &'` |
46 47
47 ## Building the image yourself48 ## Building the image yourself
@@ -68,7 +69,7 @@ sbx run -d claude . \
68 sbx run -d claude . \69 sbx run -d claude . \
69 --template k33g/ori:0.0.1 \70 --template k33g/ori:0.0.1 \
70 --kit ./kits/ori \71 --kit ./kits/ori \
71- --name ori2 \72+ --name ori \
72 -p 5555:888873 -p 5555:8888
73 ```74 ```
74 75
added sbx-docker-summary.adoc +294 -0
new file mode 100644
@@ -0,0 +1,294 @@
1+= SBX: Docker Sandbox Environment
2+:toc: left
3+:toclevels: 3
4+:sectnums:
5+:icons: font
6+
7+== Overview
8+
9+SBX is Docker's sandboxed environment system that provides isolated, persistent development containers with controlled network access, environment persistence, and Git integration. It enables secure development workflows with fine-grained policy control.
10+
11+== Core Features
12+
13+=== Environment Persistence
14+
15+SBX provides a persistent environment file at `/etc/sandbox-persistent.sh` that is automatically sourced across all shell contexts:
16+
17+* **Non-interactive shells**: via `BASH_ENV=/etc/sandbox-persistent.sh`
18+* **Login shells**: via `/etc/profile.d/sandbox-persistent.sh`
19+* **Interactive shells**: via `/etc/bash.bashrc` and `~/.bashrc`
20+
21+.Adding Persistent Variables
22+[source,bash]
23+----
24+echo "export VAR_NAME=value" >> /etc/sandbox-persistent.sh
25+----
26+
27+[IMPORTANT]
28+====
29+**Never add shell completion scripts to `/etc/sandbox-persistent.sh`**. Completion scripts break the bash tool because the persistent file is sourced before every command execution, not just during initialization. Only add core initialization scripts (like `nvm.sh` or `sdkman-init.sh`), never completion scripts (like `bash_completion`).
30+====
31+
32+=== Network Access and Security
33+
34+SBX includes a firewall that restricts outbound network access with policy-based controls.
35+
36+==== Blocked Request Handling
37+
38+Blocked HTTP/HTTPS requests return **HTTP 403** with structured explanations:
39+
40+[horizontal]
41+Blocked by local rule:: A developer-added deny rule (global or per-sandbox) is blocking the host
42+Blocked by org policy:: Centralized organization policy enforcement
43+No matching allow rule:: Domain not on any allow list (default deny)
44+
45+.Inspecting Connection Policy
46+[source,bash]
47+----
48+sbx policy log # Shows host, rule, reason, last-seen time
49+sbx policy ls # Shows active rules and suppressed rules
50+----
51+
52+.Allowing Network Access
53+[source,bash]
54+----
55+sbx policy allow network <domain>[,<domain>] # Allow specific domains
56+sbx policy allow network "**" # Allow all (not on denylist)
57+----
58+
59+.Removing Deny Rules
60+[source,bash]
61+----
62+sbx policy rm network --resource <host> # Remove global deny
63+sbx policy rm network --sandbox <sandbox> --resource <host> # Remove sandbox-scoped deny
64+----
65+
66+==== Port Publishing
67+
68+Services in the sandbox are not directly accessible from the host. To expose ports:
69+
70+[source,bash]
71+----
72+sbx ports <sandbox-name> --publish [[HOST_IP:]HOST_PORT:]SANDBOX_PORT[/PROTOCOL]
73+----
74+
75+.Example: Publishing Web Server
76+[source,bash]
77+----
78+sbx ports <sandbox-name> --publish 8080:8080/tcp
79+sbx ports <sandbox-name> # List published ports
80+sbx ports <sandbox-name> --unpublish 8080:8080/tcp # Unpublish
81+----
82+
83+[NOTE]
84+====
85+Services must listen on the `eth0` interface (not just `127.0.0.1`). Bind to `0.0.0.0` (IPv4) or `::` (IPv6) to be reachable via port publishing.
86+====
87+
88+==== Accessing Host Services
89+
90+The sandbox has its own `localhost`. To reach services on the host machine:
91+
92+[source,bash]
93+----
94+curl http://host.docker.internal:3000
95+----
96+
97+==== IP Stack Configuration
98+
99+If connectivity fails, the proxy may be using the wrong IP protocol version. Configure with:
100+
101+[source,bash]
102+----
103+DOCKER_SANDBOXES_IP_STACK=ipv4only # Only IPv4
104+DOCKER_SANDBOXES_IP_STACK=ipv6only # Only IPv6
105+DOCKER_SANDBOXES_IP_STACK=dual-stack # Try both (may be slow if one fails)
106+----
107+
108+==== .NET Aspire IPv6 Workaround
109+
110+.NET Aspire's DCP uses bracketed IPv6 loopback `http://[::1]:<port>`. Add to `NO_PROXY`:
111+
112+[source,bash]
113+----
114+cat >> /etc/sandbox-persistent.sh <<'EOF'
115+if [ -z "${SBX_ASPIRE_NOPROXY_DONE:-}" ]; then
116+ export NO_PROXY="${NO_PROXY:+$NO_PROXY,}[::1]"
117+ export no_proxy="$NO_PROXY"
118+ export SBX_ASPIRE_NOPROXY_DONE=1
119+fi
120+EOF
121+----
122+
123+=== Git Integration
124+
125+==== Authentication
126+
127+The sandbox proxy handles GitHub authentication automatically by injecting credentials for HTTPS Git operations. No need to run `gh auth login` inside the sandbox.
128+
129+[IMPORTANT]
130+====
131+`gh auth status` will show "not logged in" inside the sandbox. This is expected and does not affect Git operations.
132+====
133+
134+.Configuring GitHub Token
135+[source,bash]
136+----
137+# For existing sandbox (immediate effect)
138+sbx secret set github --sandbox <sandbox-name> -t "$(gh auth token)"
139+
140+# Globally for all future sandboxes (requires recreate)
141+sbx secret set github -t "$(gh auth token)"
142+----
143+
144+[TIP]
145+====
146+Find the sandbox name using `$SANDBOX_NAME`, `hostname`, or the deprecated `$SANDBOX_VM_ID` inside the sandbox.
147+====
148+
149+==== Git Workspace Modes
150+
151+SBX supports two workspace modes. Check your mode:
152+
153+[source,bash]
154+----
155+if [ -d /run/sandbox/source ]; then echo "clone mode"; else echo "direct mode"; fi
156+----
157+
158+===== Direct Mode (Default)
159+
160+The host working tree is mounted directly. Edits, commits, and branches appear on the host **immediately**. No separate copy to sync.
161+
162+===== Clone Mode (`--clone`)
163+
164+A standalone Git clone made at sandbox creation time:
165+
166+* **HEAD** matches the host repo's state at creation
167+* **Commits stay in sandbox** until fetched by the host
168+* **Host fetches with**: `git fetch sandbox-<name>`
169+* **Read-only host mount** at `/run/sandbox/source`
170+
171+.Syncing from Host in Clone Mode
172+[source,bash]
173+----
174+git fetch /run/sandbox/source # Fetch host commits
175+git log HEAD..FETCH_HEAD --oneline # See what's new on host
176+git pull /run/sandbox/source <branch> # Merge host branch
177+----
178+
179+.Host Retrieving Sandbox Commits
180+[source,bash]
181+----
182+git fetch sandbox-<name> # On host machine
183+----
184+
185+[WARNING]
186+====
187+Commits not pushed to a remote (like GitHub) are lost if the sandbox is removed, as the git-daemon only runs while the sandbox is active.
188+====
189+
190+==== Pushing and Pull Requests
191+
192+Push and open PRs **directly from inside the sandbox**:
193+
194+[source,bash]
195+----
196+git remote -v # Check available remotes
197+git checkout -b <branch> # Create working branch
198+git add -A && git commit -m ""
199+git push -u origin <branch> # Push to mirrored remote
200+gh pr create --fill # Create PR
201+----
202+
203+.Pushing to Fork
204+[source,bash]
205+----
206+git push -u <fork-remote> <branch>
207+gh pr create --repo <org>/<repo> --head <fork-user>:<branch> --fill
208+----
209+
210+== Claude Code Integration
211+
212+=== Environment File
213+
214+The `CLAUDE_ENV_FILE` variable is set to `/etc/sandbox-persistent.sh`, which is sourced before each Bash command execution, ensuring environment persistence across tool invocations.
215+
216+[CAUTION]
217+====
218+Apply the same shell completion restriction: never add completion scripts to this file, as it's sourced before every command, not just shell initialization.
219+====
220+
221+=== Using the Bash Tool
222+
223+When tools are not found in PATH after installation:
224+
225+[source,bash]
226+----
227+bash -l -c "your-command" # Use login shell
228+bash -l -c "java -version" # Example: SDKMAN-installed Java
229+bash -l -c "node --version" # Example: NVM-installed Node
230+----
231+
232+[TIP]
233+====
234+Login shells always source the persistent environment file fresh, ensuring the latest configuration is honored even if shell snapshots contain cached state.
235+====
236+
237+== Kits System
238+
239+SBX supports installable "kits" that provide specialized functionality. Kit documentation is available under `/Users/k33g/kDrive/Rickub/bots-garden/kits-agent-context/` and should be read only when relevant to the task.
240+
241+.Example: Ori Kit
242+The `ori` kit provides an ACP web client for Claude Code, serving a browser-based interface with:
243+
244+* React SPA with Zed-style agent panel
245+* Workspace panel with file tree and Monaco editor
246+* Interactive terminal
247+* Markdown and AsciiDoc rendering
248+
249+== Common Operations
250+
251+=== Troubleshooting Connectivity
252+
253+.Check Host IP Addresses
254+[source,bash]
255+----
256+# macOS
257+ifconfig | grep 'inet ' # IPv4
258+ifconfig | grep 'inet6 ' # IPv6 (ignore fe80::)
259+
260+# Linux
261+ip -4 addr show scope global
262+ip -6 addr show scope global
263+----
264+
265+=== Managing Secrets
266+
267+[source,bash]
268+----
269+sbx secret set <name> --sandbox <sandbox-name> -t "value" # Per-sandbox
270+sbx secret set <name> -t "value" # Global
271+----
272+
273+=== Docker Network Access
274+
275+Direct access to container ports requires adding the container's network to the `no_proxy` configuration, as Docker daemon access is provided but port routing needs explicit configuration.
276+
277+== Best Practices
278+
279+[arabic]
280+. **Never add shell completions to persistent environment files** - only core initialization
281+. **Use login shells (`bash -l -c`)** when tools aren't found after installation
282+. **Bind services to `0.0.0.0` or `::`** not just `127.0.0.1` for port publishing
283+. **Use `host.docker.internal`** to access host services, not `localhost`
284+. **Push and create PRs from inside the sandbox** - it's the authorized workflow
285+. **Set IP stack explicitly** if dual-stack causes slow connections
286+. **Configure GitHub tokens as sandbox secrets** for Git push operations
287+
288+== References
289+
290+* Sandbox policy management: `sbx policy`
291+* Port publishing: `sbx ports`
292+* Secret management: `sbx secret`
293+* Git authentication: Automatic via proxy credential injection
294+* Environment persistence: `/etc/sandbox-persistent.sh`
new file mode 100644
@@ -0,0 +1,294 @@
1+= SBX: Docker Sandbox Environment
2+:toc: left
3+:toclevels: 3
4+:sectnums:
5+:icons: font
6+
7+== Overview
8+
9+SBX is Docker's sandboxed environment system that provides isolated, persistent development containers with controlled network access, environment persistence, and Git integration. It enables secure development workflows with fine-grained policy control.
10+
11+== Core Features
12+
13+=== Environment Persistence
14+
15+SBX provides a persistent environment file at `/etc/sandbox-persistent.sh` that is automatically sourced across all shell contexts:
16+
17+* **Non-interactive shells**: via `BASH_ENV=/etc/sandbox-persistent.sh`
18+* **Login shells**: via `/etc/profile.d/sandbox-persistent.sh`
19+* **Interactive shells**: via `/etc/bash.bashrc` and `~/.bashrc`
20+
21+.Adding Persistent Variables
22+[source,bash]
23+----
24+echo "export VAR_NAME=value" >> /etc/sandbox-persistent.sh
25+----
26+
27+[IMPORTANT]
28+====
29+**Never add shell completion scripts to `/etc/sandbox-persistent.sh`**. Completion scripts break the bash tool because the persistent file is sourced before every command execution, not just during initialization. Only add core initialization scripts (like `nvm.sh` or `sdkman-init.sh`), never completion scripts (like `bash_completion`).
30+====
31+
32+=== Network Access and Security
33+
34+SBX includes a firewall that restricts outbound network access with policy-based controls.
35+
36+==== Blocked Request Handling
37+
38+Blocked HTTP/HTTPS requests return **HTTP 403** with structured explanations:
39+
40+[horizontal]
41+Blocked by local rule:: A developer-added deny rule (global or per-sandbox) is blocking the host
42+Blocked by org policy:: Centralized organization policy enforcement
43+No matching allow rule:: Domain not on any allow list (default deny)
44+
45+.Inspecting Connection Policy
46+[source,bash]
47+----
48+sbx policy log # Shows host, rule, reason, last-seen time
49+sbx policy ls # Shows active rules and suppressed rules
50+----
51+
52+.Allowing Network Access
53+[source,bash]
54+----
55+sbx policy allow network <domain>[,<domain>] # Allow specific domains
56+sbx policy allow network "**" # Allow all (not on denylist)
57+----
58+
59+.Removing Deny Rules
60+[source,bash]
61+----
62+sbx policy rm network --resource <host> # Remove global deny
63+sbx policy rm network --sandbox <sandbox> --resource <host> # Remove sandbox-scoped deny
64+----
65+
66+==== Port Publishing
67+
68+Services in the sandbox are not directly accessible from the host. To expose ports:
69+
70+[source,bash]
71+----
72+sbx ports <sandbox-name> --publish [[HOST_IP:]HOST_PORT:]SANDBOX_PORT[/PROTOCOL]
73+----
74+
75+.Example: Publishing Web Server
76+[source,bash]
77+----
78+sbx ports <sandbox-name> --publish 8080:8080/tcp
79+sbx ports <sandbox-name> # List published ports
80+sbx ports <sandbox-name> --unpublish 8080:8080/tcp # Unpublish
81+----
82+
83+[NOTE]
84+====
85+Services must listen on the `eth0` interface (not just `127.0.0.1`). Bind to `0.0.0.0` (IPv4) or `::` (IPv6) to be reachable via port publishing.
86+====
87+
88+==== Accessing Host Services
89+
90+The sandbox has its own `localhost`. To reach services on the host machine:
91+
92+[source,bash]
93+----
94+curl http://host.docker.internal:3000
95+----
96+
97+==== IP Stack Configuration
98+
99+If connectivity fails, the proxy may be using the wrong IP protocol version. Configure with:
100+
101+[source,bash]
102+----
103+DOCKER_SANDBOXES_IP_STACK=ipv4only # Only IPv4
104+DOCKER_SANDBOXES_IP_STACK=ipv6only # Only IPv6
105+DOCKER_SANDBOXES_IP_STACK=dual-stack # Try both (may be slow if one fails)
106+----
107+
108+==== .NET Aspire IPv6 Workaround
109+
110+.NET Aspire's DCP uses bracketed IPv6 loopback `http://[::1]:<port>`. Add to `NO_PROXY`:
111+
112+[source,bash]
113+----
114+cat >> /etc/sandbox-persistent.sh <<'EOF'
115+if [ -z "${SBX_ASPIRE_NOPROXY_DONE:-}" ]; then
116+ export NO_PROXY="${NO_PROXY:+$NO_PROXY,}[::1]"
117+ export no_proxy="$NO_PROXY"
118+ export SBX_ASPIRE_NOPROXY_DONE=1
119+fi
120+EOF
121+----
122+
123+=== Git Integration
124+
125+==== Authentication
126+
127+The sandbox proxy handles GitHub authentication automatically by injecting credentials for HTTPS Git operations. No need to run `gh auth login` inside the sandbox.
128+
129+[IMPORTANT]
130+====
131+`gh auth status` will show "not logged in" inside the sandbox. This is expected and does not affect Git operations.
132+====
133+
134+.Configuring GitHub Token
135+[source,bash]
136+----
137+# For existing sandbox (immediate effect)
138+sbx secret set github --sandbox <sandbox-name> -t "$(gh auth token)"
139+
140+# Globally for all future sandboxes (requires recreate)
141+sbx secret set github -t "$(gh auth token)"
142+----
143+
144+[TIP]
145+====
146+Find the sandbox name using `$SANDBOX_NAME`, `hostname`, or the deprecated `$SANDBOX_VM_ID` inside the sandbox.
147+====
148+
149+==== Git Workspace Modes
150+
151+SBX supports two workspace modes. Check your mode:
152+
153+[source,bash]
154+----
155+if [ -d /run/sandbox/source ]; then echo "clone mode"; else echo "direct mode"; fi
156+----
157+
158+===== Direct Mode (Default)
159+
160+The host working tree is mounted directly. Edits, commits, and branches appear on the host **immediately**. No separate copy to sync.
161+
162+===== Clone Mode (`--clone`)
163+
164+A standalone Git clone made at sandbox creation time:
165+
166+* **HEAD** matches the host repo's state at creation
167+* **Commits stay in sandbox** until fetched by the host
168+* **Host fetches with**: `git fetch sandbox-<name>`
169+* **Read-only host mount** at `/run/sandbox/source`
170+
171+.Syncing from Host in Clone Mode
172+[source,bash]
173+----
174+git fetch /run/sandbox/source # Fetch host commits
175+git log HEAD..FETCH_HEAD --oneline # See what's new on host
176+git pull /run/sandbox/source <branch> # Merge host branch
177+----
178+
179+.Host Retrieving Sandbox Commits
180+[source,bash]
181+----
182+git fetch sandbox-<name> # On host machine
183+----
184+
185+[WARNING]
186+====
187+Commits not pushed to a remote (like GitHub) are lost if the sandbox is removed, as the git-daemon only runs while the sandbox is active.
188+====
189+
190+==== Pushing and Pull Requests
191+
192+Push and open PRs **directly from inside the sandbox**:
193+
194+[source,bash]
195+----
196+git remote -v # Check available remotes
197+git checkout -b <branch> # Create working branch
198+git add -A && git commit -m ""
199+git push -u origin <branch> # Push to mirrored remote
200+gh pr create --fill # Create PR
201+----
202+
203+.Pushing to Fork
204+[source,bash]
205+----
206+git push -u <fork-remote> <branch>
207+gh pr create --repo <org>/<repo> --head <fork-user>:<branch> --fill
208+----
209+
210+== Claude Code Integration
211+
212+=== Environment File
213+
214+The `CLAUDE_ENV_FILE` variable is set to `/etc/sandbox-persistent.sh`, which is sourced before each Bash command execution, ensuring environment persistence across tool invocations.
215+
216+[CAUTION]
217+====
218+Apply the same shell completion restriction: never add completion scripts to this file, as it's sourced before every command, not just shell initialization.
219+====
220+
221+=== Using the Bash Tool
222+
223+When tools are not found in PATH after installation:
224+
225+[source,bash]
226+----
227+bash -l -c "your-command" # Use login shell
228+bash -l -c "java -version" # Example: SDKMAN-installed Java
229+bash -l -c "node --version" # Example: NVM-installed Node
230+----
231+
232+[TIP]
233+====
234+Login shells always source the persistent environment file fresh, ensuring the latest configuration is honored even if shell snapshots contain cached state.
235+====
236+
237+== Kits System
238+
239+SBX supports installable "kits" that provide specialized functionality. Kit documentation is available under `/Users/k33g/kDrive/Rickub/bots-garden/kits-agent-context/` and should be read only when relevant to the task.
240+
241+.Example: Ori Kit
242+The `ori` kit provides an ACP web client for Claude Code, serving a browser-based interface with:
243+
244+* React SPA with Zed-style agent panel
245+* Workspace panel with file tree and Monaco editor
246+* Interactive terminal
247+* Markdown and AsciiDoc rendering
248+
249+== Common Operations
250+
251+=== Troubleshooting Connectivity
252+
253+.Check Host IP Addresses
254+[source,bash]
255+----
256+# macOS
257+ifconfig | grep 'inet ' # IPv4
258+ifconfig | grep 'inet6 ' # IPv6 (ignore fe80::)
259+
260+# Linux
261+ip -4 addr show scope global
262+ip -6 addr show scope global
263+----
264+
265+=== Managing Secrets
266+
267+[source,bash]
268+----
269+sbx secret set <name> --sandbox <sandbox-name> -t "value" # Per-sandbox
270+sbx secret set <name> -t "value" # Global
271+----
272+
273+=== Docker Network Access
274+
275+Direct access to container ports requires adding the container's network to the `no_proxy` configuration, as Docker daemon access is provided but port routing needs explicit configuration.
276+
277+== Best Practices
278+
279+[arabic]
280+. **Never add shell completions to persistent environment files** - only core initialization
281+. **Use login shells (`bash -l -c`)** when tools aren't found after installation
282+. **Bind services to `0.0.0.0` or `::`** not just `127.0.0.1` for port publishing
283+. **Use `host.docker.internal`** to access host services, not `localhost`
284+. **Push and create PRs from inside the sandbox** - it's the authorized workflow
285+. **Set IP stack explicitly** if dual-stack causes slow connections
286+. **Configure GitHub tokens as sandbox secrets** for Git push operations
287+
288+== References
289+
290+* Sandbox policy management: `sbx policy`
291+* Port publishing: `sbx ports`
292+* Secret management: `sbx secret`
293+* Git authentication: Automatic via proxy credential injection
294+* Environment persistence: `/etc/sandbox-persistent.sh`
added scripts/README.fr.md +54 -0
new file mode 100644
@@ -0,0 +1,54 @@
1+# Scripts
2+
3+*[English version](README.md)*
4+
5+## `launch-ori.applescript` — démarrer le sandbox et ouvrir ori-desktop
6+
7+Un seul geste au lieu de deux commandes : le script démarre (ou redémarre) le sandbox `ori`, attend que le serveur ori réponde, puis ouvre l'application desktop.
8+
9+Ce qu'il fait, dans l'ordre :
10+
11+1. Retrouve la racine du dépôt à partir de son propre emplacement (`<dépôt>/scripts/…`). Renseigne la propriété `repoDirOverride` en tête de fichier si tu le déplaces ailleurs.
12+2. Vérifie que `ori-desktop/build/bin/ori-desktop.app` existe ; sinon il affiche comment la construire (`cd ori-desktop && wails build && xattr -cr build/bin/ori-desktop.app`).
13+3. Si `sbx ls -q` liste déjà un sandbox nommé `ori`, le redémarre avec `sbx run -d --name ori`. Sinon il le crée :
14+ ```bash
15+ sbx run -d claude . --template k33g/ori:0.0.1 --kit ./kits/ori --name ori -p 5555:8888
16+ ```
17+4. Interroge `http://localhost:5555/healthz` toutes les 2 s, jusqu'à 90 s (`healthTimeoutSeconds`). Si le serveur ne répond jamais, il ouvre quand même l'app et indique où regarder : `sbx exec ori cat /var/log/sbx-kit-startup.log`.
18+5. Ouvre `ori-desktop.app`, qui se connecte automatiquement à l'URL mémorisée la dernière fois (`~/Library/Application Support/ori-desktop/settings.json`, clé `serverUrl`). Saisis `http://localhost:5555` sur l'écran de connexion la première fois.
19+
20+Template, kit, ports, nom du sandbox et délai sont des lignes `property` en tête du script.
21+
22+### Lancer depuis un terminal
23+
24+```bash
25+osascript scripts/launch-ori.applescript
26+```
27+
28+### Le rendre double-cliquable
29+
30+Compile le script en bundle d'application :
31+
32+```bash
33+osacompile -o "scripts/Launch Ori.app" scripts/launch-ori.applescript
34+```
35+
36+- Double-clique sur `scripts/Launch Ori.app` dans le Finder, glisse-le dans le Dock, ou lance-le depuis Spotlight (« Launch Ori »).
37+- Le `.app` est un artefact de build, ignoré par git (`scripts/*.app/`). Recompile-le après chaque modification du `.applescript`.
38+- Construit localement, il ne porte pas d'attribut de quarantaine : Gatekeeper ne le bloque pas. macOS demandera peut-être une fois l'autorisation d'afficher des notifications.
39+- La progression est signalée par des notifications ; un échec bloquant (app non construite, `sbx run` en erreur, le plus souvent parce que Docker Desktop ne tourne pas) ouvre une boîte de dialogue.
40+
41+### Pourquoi ces choix
42+
43+- **Un lancement depuis le Finder reçoit un `PATH` minimal** sans `/opt/homebrew/bin` : le script l'exporte avant chaque commande shell.
44+- **`sbx run -d`** (détaché) rend la main dès que le sandbox existe et l'exempte de l'arrêt automatique de sbx après 30 s. Le kit démarre ensuite le serveur ori de façon asynchrone, d'où l'attente sur `/healthz` avant d'ouvrir l'app.
45+- **Redémarrer plutôt que recréer** quand le sandbox existe : relancer la commande de création échouerait sur le nom, et `sbx rm` + création perdrait la session Claude du sandbox.
46+
47+### Tester les handlers sans créer de sandbox
48+
49+```bash
50+osacompile -o /tmp/launch-ori.scpt scripts/launch-ori.applescript
51+osascript -e 'set s to load script POSIX file "/tmp/launch-ori.scpt"
52+set s'"'"'s healthTimeoutSeconds to 4
53+return s'"'"'s waitForServer("http://localhost:5555")' # false sauf si quelque chose répond sur :5555
54+```
new file mode 100644
@@ -0,0 +1,54 @@
1+# Scripts
2+
3+*[English version](README.md)*
4+
5+## `launch-ori.applescript` — démarrer le sandbox et ouvrir ori-desktop
6+
7+Un seul geste au lieu de deux commandes : le script démarre (ou redémarre) le sandbox `ori`, attend que le serveur ori réponde, puis ouvre l'application desktop.
8+
9+Ce qu'il fait, dans l'ordre :
10+
11+1. Retrouve la racine du dépôt à partir de son propre emplacement (`<dépôt>/scripts/…`). Renseigne la propriété `repoDirOverride` en tête de fichier si tu le déplaces ailleurs.
12+2. Vérifie que `ori-desktop/build/bin/ori-desktop.app` existe ; sinon il affiche comment la construire (`cd ori-desktop && wails build && xattr -cr build/bin/ori-desktop.app`).
13+3. Si `sbx ls -q` liste déjà un sandbox nommé `ori`, le redémarre avec `sbx run -d --name ori`. Sinon il le crée :
14+ ```bash
15+ sbx run -d claude . --template k33g/ori:0.0.1 --kit ./kits/ori --name ori -p 5555:8888
16+ ```
17+4. Interroge `http://localhost:5555/healthz` toutes les 2 s, jusqu'à 90 s (`healthTimeoutSeconds`). Si le serveur ne répond jamais, il ouvre quand même l'app et indique où regarder : `sbx exec ori cat /var/log/sbx-kit-startup.log`.
18+5. Ouvre `ori-desktop.app`, qui se connecte automatiquement à l'URL mémorisée la dernière fois (`~/Library/Application Support/ori-desktop/settings.json`, clé `serverUrl`). Saisis `http://localhost:5555` sur l'écran de connexion la première fois.
19+
20+Template, kit, ports, nom du sandbox et délai sont des lignes `property` en tête du script.
21+
22+### Lancer depuis un terminal
23+
24+```bash
25+osascript scripts/launch-ori.applescript
26+```
27+
28+### Le rendre double-cliquable
29+
30+Compile le script en bundle d'application :
31+
32+```bash
33+osacompile -o "scripts/Launch Ori.app" scripts/launch-ori.applescript
34+```
35+
36+- Double-clique sur `scripts/Launch Ori.app` dans le Finder, glisse-le dans le Dock, ou lance-le depuis Spotlight (« Launch Ori »).
37+- Le `.app` est un artefact de build, ignoré par git (`scripts/*.app/`). Recompile-le après chaque modification du `.applescript`.
38+- Construit localement, il ne porte pas d'attribut de quarantaine : Gatekeeper ne le bloque pas. macOS demandera peut-être une fois l'autorisation d'afficher des notifications.
39+- La progression est signalée par des notifications ; un échec bloquant (app non construite, `sbx run` en erreur, le plus souvent parce que Docker Desktop ne tourne pas) ouvre une boîte de dialogue.
40+
41+### Pourquoi ces choix
42+
43+- **Un lancement depuis le Finder reçoit un `PATH` minimal** sans `/opt/homebrew/bin` : le script l'exporte avant chaque commande shell.
44+- **`sbx run -d`** (détaché) rend la main dès que le sandbox existe et l'exempte de l'arrêt automatique de sbx après 30 s. Le kit démarre ensuite le serveur ori de façon asynchrone, d'où l'attente sur `/healthz` avant d'ouvrir l'app.
45+- **Redémarrer plutôt que recréer** quand le sandbox existe : relancer la commande de création échouerait sur le nom, et `sbx rm` + création perdrait la session Claude du sandbox.
46+
47+### Tester les handlers sans créer de sandbox
48+
49+```bash
50+osacompile -o /tmp/launch-ori.scpt scripts/launch-ori.applescript
51+osascript -e 'set s to load script POSIX file "/tmp/launch-ori.scpt"
52+set s'"'"'s healthTimeoutSeconds to 4
53+return s'"'"'s waitForServer("http://localhost:5555")' # false sauf si quelque chose répond sur :5555
54+```
added scripts/README.md +54 -0
new file mode 100644
@@ -0,0 +1,54 @@
1+# Scripts
2+
3+*[Version française](README.fr.md)*
4+
5+## `launch-ori.applescript` — start the sandbox and open ori-desktop
6+
7+One gesture instead of two commands: the script starts (or restarts) the `ori` sandbox, waits until the ori server answers, then opens the desktop app.
8+
9+What it does, in order:
10+
11+1. Finds the repository root from its own location (`<repo>/scripts/…`). Set the `repoDirOverride` property at the top of the file if you move it elsewhere.
12+2. Checks that `ori-desktop/build/bin/ori-desktop.app` exists; otherwise shows how to build it (`cd ori-desktop && wails build && xattr -cr build/bin/ori-desktop.app`).
13+3. If `sbx ls -q` already lists a sandbox named `ori`, restarts it with `sbx run -d --name ori`. Otherwise creates it:
14+ ```bash
15+ sbx run -d claude . --template k33g/ori:0.0.1 --kit ./kits/ori --name ori -p 5555:8888
16+ ```
17+4. Polls `http://localhost:5555/healthz` every 2 s, up to 90 s (`healthTimeoutSeconds`). If the server never answers it still opens the app and tells you where to look: `sbx exec ori cat /var/log/sbx-kit-startup.log`.
18+5. Opens `ori-desktop.app`, which auto-connects to the server URL it remembered last time (`~/Library/Application Support/ori-desktop/settings.json`, key `serverUrl`). Set it to `http://localhost:5555` on the first connection screen.
19+
20+Template, kit, ports, sandbox name and timeout are `property` lines at the top of the script.
21+
22+### Run it from a terminal
23+
24+```bash
25+osascript scripts/launch-ori.applescript
26+```
27+
28+### Make it double-clickable
29+
30+Compile the script into an application bundle:
31+
32+```bash
33+osacompile -o "scripts/Launch Ori.app" scripts/launch-ori.applescript
34+```
35+
36+- Double-click `scripts/Launch Ori.app` in the Finder, drag it to the Dock, or launch it from Spotlight ("Launch Ori").
37+- The `.app` is a build artefact and is gitignored (`scripts/*.app/`). Rebuild it after every edit of the `.applescript`.
38+- Built locally, it carries no quarantine attribute, so Gatekeeper does not block it. macOS may ask once for permission to show notifications.
39+- Progress is reported with notifications; a hard failure (app not built, `sbx run` failing, usually because Docker Desktop is not running) opens an alert dialog.
40+
41+### Why these choices
42+
43+- **Finder launches get a minimal `PATH`** without `/opt/homebrew/bin`, so the script exports it before every shell command.
44+- **`sbx run -d`** (detached) returns as soon as the sandbox exists, and exempts it from sbx's 30 s auto-stop. The kit then starts the ori server asynchronously, hence the health poll before opening the app.
45+- **Restart instead of recreate** when the sandbox exists: re-running the create command would collide on the name, and `sbx rm` + create would lose the sandbox's Claude session.
46+
47+### Test the handlers without creating a sandbox
48+
49+```bash
50+osacompile -o /tmp/launch-ori.scpt scripts/launch-ori.applescript
51+osascript -e 'set s to load script POSIX file "/tmp/launch-ori.scpt"
52+set s'"'"'s healthTimeoutSeconds to 4
53+return s'"'"'s waitForServer("http://localhost:5555")' # false unless something answers on :5555
54+```
new file mode 100644
@@ -0,0 +1,54 @@
1+# Scripts
2+
3+*[Version française](README.fr.md)*
4+
5+## `launch-ori.applescript` — start the sandbox and open ori-desktop
6+
7+One gesture instead of two commands: the script starts (or restarts) the `ori` sandbox, waits until the ori server answers, then opens the desktop app.
8+
9+What it does, in order:
10+
11+1. Finds the repository root from its own location (`<repo>/scripts/…`). Set the `repoDirOverride` property at the top of the file if you move it elsewhere.
12+2. Checks that `ori-desktop/build/bin/ori-desktop.app` exists; otherwise shows how to build it (`cd ori-desktop && wails build && xattr -cr build/bin/ori-desktop.app`).
13+3. If `sbx ls -q` already lists a sandbox named `ori`, restarts it with `sbx run -d --name ori`. Otherwise creates it:
14+ ```bash
15+ sbx run -d claude . --template k33g/ori:0.0.1 --kit ./kits/ori --name ori -p 5555:8888
16+ ```
17+4. Polls `http://localhost:5555/healthz` every 2 s, up to 90 s (`healthTimeoutSeconds`). If the server never answers it still opens the app and tells you where to look: `sbx exec ori cat /var/log/sbx-kit-startup.log`.
18+5. Opens `ori-desktop.app`, which auto-connects to the server URL it remembered last time (`~/Library/Application Support/ori-desktop/settings.json`, key `serverUrl`). Set it to `http://localhost:5555` on the first connection screen.
19+
20+Template, kit, ports, sandbox name and timeout are `property` lines at the top of the script.
21+
22+### Run it from a terminal
23+
24+```bash
25+osascript scripts/launch-ori.applescript
26+```
27+
28+### Make it double-clickable
29+
30+Compile the script into an application bundle:
31+
32+```bash
33+osacompile -o "scripts/Launch Ori.app" scripts/launch-ori.applescript
34+```
35+
36+- Double-click `scripts/Launch Ori.app` in the Finder, drag it to the Dock, or launch it from Spotlight ("Launch Ori").
37+- The `.app` is a build artefact and is gitignored (`scripts/*.app/`). Rebuild it after every edit of the `.applescript`.
38+- Built locally, it carries no quarantine attribute, so Gatekeeper does not block it. macOS may ask once for permission to show notifications.
39+- Progress is reported with notifications; a hard failure (app not built, `sbx run` failing, usually because Docker Desktop is not running) opens an alert dialog.
40+
41+### Why these choices
42+
43+- **Finder launches get a minimal `PATH`** without `/opt/homebrew/bin`, so the script exports it before every shell command.
44+- **`sbx run -d`** (detached) returns as soon as the sandbox exists, and exempts it from sbx's 30 s auto-stop. The kit then starts the ori server asynchronously, hence the health poll before opening the app.
45+- **Restart instead of recreate** when the sandbox exists: re-running the create command would collide on the name, and `sbx rm` + create would lose the sandbox's Claude session.
46+
47+### Test the handlers without creating a sandbox
48+
49+```bash
50+osacompile -o /tmp/launch-ori.scpt scripts/launch-ori.applescript
51+osascript -e 'set s to load script POSIX file "/tmp/launch-ori.scpt"
52+set s'"'"'s healthTimeoutSeconds to 4
53+return s'"'"'s waitForServer("http://localhost:5555")' # false unless something answers on :5555
54+```
added scripts/launch-ori.applescript +0 -0
new file mode 100644
Binary files /dev/null and b/scripts/launch-ori.applescript differ
new file mode 100644
Binary files /dev/null and b/scripts/launch-ori.applescript differBinary files /dev/null and b/scripts/launch-ori.applescript differ
added seven-story.md +55 -0
new file mode 100644
@@ -0,0 +1,55 @@
1+# Frequency of Self
2+
3+**Agent: Riker**
4+
5+Seven of Nine stood in the Voyager's astrometrics lab, surrounded by the comforting precision of stellar cartography. The darkness of the room was punctuated by thousands of glowing data points—stars, nebulae, spatial anomalies—each one catalogued, measured, understood.
6+
7+"You've been here for fourteen hours straight," Kathryn Janeway's voice came from the doorway, gentle but firm.
8+
9+"Efficiency," Seven replied without turning. "I can complete the Astrometrics survey in—"
10+
11+"Seven." Janeway stepped into the star field, her face illuminated by the blue-white glow of a nearby pulsar. "That's not what I asked."
12+
13+Seven's hands stilled on the console. The question Janeway hadn't asked hung in the air between them, as visible as the holographic stars.
14+
15+"I am... struggling with a paradox," Seven finally admitted.
16+
17+Janeway moved to stand beside her, studying the star chart. "Tell me."
18+
19+"The Borg's concept of perfection is mathematical. Absolute. Add complexity, eliminate redundancy, optimize all functions." Seven's voice held that peculiar flatness it took on when she discussed her former Collective. "But humanity's concept of perfection is... contradictory."
20+
21+She pulled up a new display—not stars this time, but a complex probability matrix. "I have analyzed 4,327 human literary works, 12,482 personal logs, and 847 philosophical texts. In 94.3% of cases, humans describe 'perfect' moments that are inefficient, redundant, or even counterproductive."
22+
23+Seven zoomed in on a specific data point. "The Doctor recently described his time singing opera with Ensign Kim as 'perfect,' despite the fact that they made seventeen errors in tempo and pitch. Lieutenant Paris called watching a sunset on an M-class planet 'perfect,' though it served no tactical or scientific purpose. You yourself—"
24+
25+"Called our coffee yesterday morning perfect, even though we were late for the staff meeting," Janeway finished with a smile.
26+
27+"Yes." Seven's hands gripped the edge of the console. "I do not understand how something flawed can be perfect. It is... illogical. And yet..."
28+
29+"And yet?" Janeway prompted gently.
30+
31+Seven's voice dropped to barely above a whisper. "Last night, I helped Naomi Wildman construct a model of a subspace manifold for her science project. We made numerous errors. The scale was incorrect. The materials were inadequate. By any objective measure, it was deeply flawed."
32+
33+She paused, and when she continued, there was something almost vulnerable in her tone. "Naomi said it was 'perfect.' And I... agreed with her."
34+
35+Janeway said nothing, letting the silence stretch.
36+
37+"The Borg were wrong," Seven said finally, the words coming out like a confession. "Perfection is not the elimination of imperfection. It is..." She struggled, her assimilation-trained mind wrestling with concepts that couldn't be reduced to data. "It is finding value in the inefficiency. Meaning in the redundancy. Beauty in the flaw."
38+
39+"You're learning to be human," Janeway said softly.
40+
41+"I am learning that being human is not something one completes," Seven corrected. "It is not a state to be achieved, like optimal efficiency. It is a process. An ongoing... adaptation."
42+
43+She turned to face Janeway fully. "I will never be perfectly human, Captain. I will always be partially Borg. But perhaps that is acceptable. Perhaps perfection is not about eliminating what I was, but about integrating who I am becoming."
44+
45+Janeway reached out and squeezed Seven's shoulder. "That sounds pretty perfect to me."
46+
47+Seven allowed herself a small smile—still rare, still uncertain, but genuine. "Inefficient sentiment. But... appreciated."
48+
49+After Janeway left, Seven returned to her star charts. But before she resumed her work, she did something new. She pulled up an image from the ship's database: the flawed subspace manifold she and Naomi had built, photographed before they'd taken it to the science fair.
50+
51+She added it to her personal files, archived under a new category she created specifically for this purpose:
52+
53+*Imperfect Perfection.*
54+
55+Then Seven of Nine, former Borg drone, current human-in-progress, went back to mapping the stars, secure in the knowledge that sometimes the most important journeys weren't through space at all.
new file mode 100644
@@ -0,0 +1,55 @@
1+# Frequency of Self
2+
3+**Agent: Riker**
4+
5+Seven of Nine stood in the Voyager's astrometrics lab, surrounded by the comforting precision of stellar cartography. The darkness of the room was punctuated by thousands of glowing data points—stars, nebulae, spatial anomalies—each one catalogued, measured, understood.
6+
7+"You've been here for fourteen hours straight," Kathryn Janeway's voice came from the doorway, gentle but firm.
8+
9+"Efficiency," Seven replied without turning. "I can complete the Astrometrics survey in—"
10+
11+"Seven." Janeway stepped into the star field, her face illuminated by the blue-white glow of a nearby pulsar. "That's not what I asked."
12+
13+Seven's hands stilled on the console. The question Janeway hadn't asked hung in the air between them, as visible as the holographic stars.
14+
15+"I am... struggling with a paradox," Seven finally admitted.
16+
17+Janeway moved to stand beside her, studying the star chart. "Tell me."
18+
19+"The Borg's concept of perfection is mathematical. Absolute. Add complexity, eliminate redundancy, optimize all functions." Seven's voice held that peculiar flatness it took on when she discussed her former Collective. "But humanity's concept of perfection is... contradictory."
20+
21+She pulled up a new display—not stars this time, but a complex probability matrix. "I have analyzed 4,327 human literary works, 12,482 personal logs, and 847 philosophical texts. In 94.3% of cases, humans describe 'perfect' moments that are inefficient, redundant, or even counterproductive."
22+
23+Seven zoomed in on a specific data point. "The Doctor recently described his time singing opera with Ensign Kim as 'perfect,' despite the fact that they made seventeen errors in tempo and pitch. Lieutenant Paris called watching a sunset on an M-class planet 'perfect,' though it served no tactical or scientific purpose. You yourself—"
24+
25+"Called our coffee yesterday morning perfect, even though we were late for the staff meeting," Janeway finished with a smile.
26+
27+"Yes." Seven's hands gripped the edge of the console. "I do not understand how something flawed can be perfect. It is... illogical. And yet..."
28+
29+"And yet?" Janeway prompted gently.
30+
31+Seven's voice dropped to barely above a whisper. "Last night, I helped Naomi Wildman construct a model of a subspace manifold for her science project. We made numerous errors. The scale was incorrect. The materials were inadequate. By any objective measure, it was deeply flawed."
32+
33+She paused, and when she continued, there was something almost vulnerable in her tone. "Naomi said it was 'perfect.' And I... agreed with her."
34+
35+Janeway said nothing, letting the silence stretch.
36+
37+"The Borg were wrong," Seven said finally, the words coming out like a confession. "Perfection is not the elimination of imperfection. It is..." She struggled, her assimilation-trained mind wrestling with concepts that couldn't be reduced to data. "It is finding value in the inefficiency. Meaning in the redundancy. Beauty in the flaw."
38+
39+"You're learning to be human," Janeway said softly.
40+
41+"I am learning that being human is not something one completes," Seven corrected. "It is not a state to be achieved, like optimal efficiency. It is a process. An ongoing... adaptation."
42+
43+She turned to face Janeway fully. "I will never be perfectly human, Captain. I will always be partially Borg. But perhaps that is acceptable. Perhaps perfection is not about eliminating what I was, but about integrating who I am becoming."
44+
45+Janeway reached out and squeezed Seven's shoulder. "That sounds pretty perfect to me."
46+
47+Seven allowed herself a small smile—still rare, still uncertain, but genuine. "Inefficient sentiment. But... appreciated."
48+
49+After Janeway left, Seven returned to her star charts. But before she resumed her work, she did something new. She pulled up an image from the ship's database: the flawed subspace manifold she and Naomi had built, photographed before they'd taken it to the science fair.
50+
51+She added it to her personal files, archived under a new category she created specifically for this purpose:
52+
53+*Imperfect Perfection.*
54+
55+Then Seven of Nine, former Borg drone, current human-in-progress, went back to mapping the stars, secure in the knowledge that sometimes the most important journeys weren't through space at all.