forked from bots-garden/ori
🛟 Updated.
f5c963a parent: ca7e020 modified
.gitignore +3 -0 | @@ -25,3 +25,6 @@ ori-desktop/build/windows/installer/tmp/ | ||
| 25 | 25 | ori-desktop/frontend/wailsjs/ |
| 26 | 26 | ori-desktop/frontend/node_modules/ |
| 27 | 27 | 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 @@ | ||
| 137 | 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 | 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 | 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. | |
| @@ -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 | ||
| 39 | 39 | - `make test` — `go test ./...` + `vitest run`. Also useful: `go test -race ./...`, `go test -short ./...` (skips e2e). |
| 40 | 40 | - `make run` — with Claude Code adapter; `make run-mock` — with the demo agent (no Claude/network needed). |
| 41 | 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 | 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 | 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 | 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 | 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`). | |
| @@ -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 @@ | ||
| 1 | 1 | # Managed by IssueSpec. Hand edits are welcome; keep the schema valid. |
| 2 | 2 | id: 1 |
| 3 | 3 | title: draft |
| 4 | -state: open | |
| 4 | +state: closed | |
| 5 | 5 | author: |
| 6 | 6 | name: k33g |
| 7 | 7 | email: ph.charriere@gmail.com |
| 8 | 8 | createdAt: 2026-09-17T09:23:50.599Z |
| 9 | -updatedAt: 2026-09-17T09:27:44.868Z | |
| 9 | +updatedAt: 2026-09-18T05:26:01.161Z | |
| 10 | 10 | labels: [] |
| 11 | 11 | body: | |
| 12 | 12 | 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: 1 | 2 | id: 1 |
| 3 | title: draft | 3 | title: draft |
| 4 | -state: open | 4 | +state: closed |
| 5 | author: | 5 | author: |
| 6 | name: k33g | 6 | name: k33g |
| 7 | email: ph.charriere@gmail.com | 7 | email: ph.charriere@gmail.com |
| 8 | createdAt: 2026-09-17T09:23:50.599Z | 8 | createdAt: 2026-09-17T09:23:50.599Z |
| 9 | -updatedAt: 2026-09-17T09:27:44.868Z | 9 | +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 @@ | ||
| 1 | 1 | # Managed by IssueSpec. Hand edits are welcome; keep the schema valid. |
| 2 | 2 | id: 3 |
| 3 | 3 | title: How to run it outside the sandbox? |
| 4 | -state: open | |
| 4 | +state: closed | |
| 5 | 5 | author: |
| 6 | 6 | name: k33g |
| 7 | 7 | email: ph.charriere@gmail.com |
| 8 | 8 | createdAt: 2026-09-17T10:09:16.901Z |
| 9 | -updatedAt: 2026-09-17T10:09:16.901Z | |
| 9 | +updatedAt: 2026-09-18T05:25:46.743Z | |
| 10 | 10 | labels: [] |
| 11 | 11 | body: "" |
| 12 | 12 | 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: 3 | 2 | id: 3 |
| 3 | title: How to run it outside the sandbox? | 3 | title: How to run it outside the sandbox? |
| 4 | -state: open | 4 | +state: closed |
| 5 | author: | 5 | author: |
| 6 | name: k33g | 6 | name: k33g |
| 7 | email: ph.charriere@gmail.com | 7 | email: ph.charriere@gmail.com |
| 8 | createdAt: 2026-09-17T10:09:16.901Z | 8 | createdAt: 2026-09-17T10:09:16.901Z |
| 9 | -updatedAt: 2026-09-17T10:09:16.901Z | 9 | +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: | ||
| 6 | 6 | name: k33g |
| 7 | 7 | email: ph.charriere@gmail.com |
| 8 | 8 | createdAt: 2026-09-17T19:19:43.179Z |
| 9 | -updatedAt: 2026-09-17T22:23:39.000Z | |
| 9 | +updatedAt: 2026-09-18T05:29:00.000Z | |
| 10 | 10 | labels: [] |
| 11 | 11 | body: | |
| 12 | 12 | Desktop shell for the ori webapp, built with Wails v2 (Go + platform webview), living in |
| @@ -20,20 +20,82 @@ body: | | ||
| 20 | 20 | Docs: `ori-desktop/README.md` (EN) and `ori-desktop/README.fr.md` (FR). |
| 21 | 21 | Root Makefile targets: `make desktop` (wails build), `make desktop-test` (pure-Go tests). |
| 22 | 22 | 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 | |
| 39 | 101 | comments: [] |
| @@ -6,7 +6,7 @@ author: | |||
| 6 | name: k33g | 6 | name: k33g |
| 7 | email: ph.charriere@gmail.com | 7 | email: ph.charriere@gmail.com |
| 8 | createdAt: 2026-09-17T19:19:43.179Z | 8 | createdAt: 2026-09-17T19:19:43.179Z |
| 9 | -updatedAt: 2026-09-17T22:23:39.000Z | 9 | +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 in | 12 | 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: true | 24 | + 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 / SettingsPath | 25 | + state: closed |
| 26 | - done: true | 26 | + priority: none |
| 27 | - - text: Settings persisted as JSON in the user config dir, with unit tests | 27 | + author: |
| 28 | - done: true | 28 | + name: k33g |
| 29 | - - text: /healthz probe with unit tests against httptest | 29 | + email: ph.charriere@gmail.com |
| 30 | - done: true | 30 | + createdAt: 2026-09-17T22:23:39.000Z |
| 31 | - - text: Plain HTML/CSS/JS frontend embedding ori in an iframe with a thin native bar | 31 | + updatedAt: 2026-09-17T22:23:39.000Z |
| 32 | - done: true | 32 | + closedAt: 2026-09-17T22:23:39.000Z |
| 33 | - - text: README (EN) + README.fr (FR), root Makefile targets, .gitignore entries | 33 | + - id: 2 |
| 34 | - done: true | 34 | + 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: true | 36 | + priority: none |
| 37 | - - text: Launch the window on a machine with the GUI toolchain (webkit2gtk / Xcode / WebView2) and confirm the iframe embed | 37 | + author: |
| 38 | - done: false | 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 | ||
| 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 | ||
| 5 | 5 | |
| 6 | 6 | ## 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 | 10 | ```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 | |
| 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 | 21 | ## Documentation |
| 18 | 22 | |
| @@ -5,14 +5,18 @@ Ori is a web client for [ACP (Agent Client Protocol)](https://agentclientprotoco | |||
| 5 | 5 | ||
| 6 | ## Quick start | 6 | ## 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 | ```bash | 10 | ```bash |
| 9 | -make deps # install frontend dependencies | 11 | +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-acp | 13 | + --kit ./kits/ori \ |
| 12 | -make test # run the Go and frontend test suites | 14 | + --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 | ## Documentation | 21 | ## 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 | ||
| 42 | 42 | | Attach the terminal Claude session (starts a stopped sandbox) | `sbx attach ori` | |
| 43 | 43 | | Restart a stopped sandbox without attaching | `sbx run -d --name ori` | |
| 44 | 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 | 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 | 48 | ## Building the image yourself |
| @@ -68,7 +69,7 @@ sbx run -d claude . \ | ||
| 68 | 69 | sbx run -d claude . \ |
| 69 | 70 | --template k33g/ori:0.0.1 \ |
| 70 | 71 | --kit ./kits/ori \ |
| 71 | - --name ori2 \ | |
| 72 | + --name ori \ | |
| 72 | 73 | -p 5555:8888 |
| 73 | 74 | ``` |
| 74 | 75 | |
| @@ -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 yourself | 48 | ## 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:8888 | 73 | -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 differ | Binary 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. | ||