feat(studio): add :latest-studio variant (PR-3)
Bundle pi-studio (omaclaren/pi-studio) as a new -studio image variant: browser prompt editor, KaTeX/Mermaid preview, tmux-backed literate REPLs, /studio command + studio_* agent tools. - Dockerfile.variant: INSTALL_STUDIO + PI_STUDIO_REPO/REF args; vendor pi-studio to /opt/pi-studio (no build step — prebuilt client in git; npm install --omit=dev for 3 prod deps). STUDIO_PORT=8765 advisory. - entrypoint-user.sh: register /opt/pi-studio via the existing pi install local-path loop (auto-skips in non-studio variant). - smoke-test.sh: auto-detected studio assertions (clone + prebuilt client + pi install registration). - CI: resolve PI_STUDIO_REF to a SHA; independent smoke-studio + build-variant-studio jobs that gate ONLY the -studio tags, so a studio failure never blocks the core :latest release. - README: 'Using pi-studio' section documenting the container access reality — pi-studio hard-binds 127.0.0.1 (index.ts .listen(port, '127.0.0.1'), no --host flag), so -p publish alone can't reach it. Documents host-networking and loopback-bridge paths, the remote ssh -L forward, and the mosh caveat (no port forwarding; run parallel ssh -L). - CHANGELOG/AGENTS/DOCKER_HUB updated. Will tag as v1.1.0 (minor). No tag created — stopping for review.
This commit is contained in:
@@ -131,16 +131,91 @@ Currently published:
|
||||
|---|---|---|
|
||||
| `joakimp/pi-devbox:latest` | base + pi + tooling | ~3.2 GB |
|
||||
| `joakimp/pi-devbox:vX.Y.Z` | pinned-version equivalent | ~3.2 GB |
|
||||
| `joakimp/pi-devbox:latest-studio` | `latest` + [pi-studio](https://github.com/omaclaren/pi-studio) (browser prompt editor, KaTeX/Mermaid preview, tmux-backed literate REPLs) | ~3.25 GB |
|
||||
| `joakimp/pi-devbox:vX.Y.Z-studio` | pinned-version studio equivalent | ~3.25 GB |
|
||||
|
||||
Planned for upcoming minor releases:
|
||||
Planned for an upcoming minor release:
|
||||
|
||||
- `joakimp/pi-devbox:latest-studio` — adds [pi-studio](https://github.com/omaclaren/pi-studio)
|
||||
for browser-based prompt editing, KaTeX/Mermaid preview, and
|
||||
literate REPLs (Shell / Python / IPython / Julia / R / GHCi /
|
||||
Clojure). Adds ~50 MB.
|
||||
- `joakimp/pi-devbox:latest-studio-tex` — also adds `texlive-xetex`
|
||||
- `joakimp/pi-devbox:latest-studio-tex` — `-studio` plus `texlive-xetex`
|
||||
for PDF export from Studio. Adds ~600 MB on top of `-studio`.
|
||||
|
||||
## Using pi-studio (`-studio` variant)
|
||||
|
||||
The `-studio` images bundle [pi-studio](https://github.com/omaclaren/pi-studio):
|
||||
a two-pane browser workspace with a prompt/response editor, live
|
||||
KaTeX/Mermaid preview, and tmux-backed literate REPLs (Shell / Python /
|
||||
IPython / Julia / R / GHCi / Clojure). It is registered automatically on
|
||||
container start (no `pi install` needed) and exposes the `/studio` slash
|
||||
command plus the `studio_repl_send` / `studio_export_*` agent tools.
|
||||
|
||||
Inside a pi session in the container:
|
||||
|
||||
```
|
||||
/studio --no-browser --port 8765 # pin a fixed port; STUDIO_PORT=8765 is the baked default
|
||||
/studio --status # reprint the tokenized URL
|
||||
```
|
||||
|
||||
### Reaching the UI from your browser (the container caveat)
|
||||
|
||||
pi-studio **hard-binds its server to `127.0.0.1` inside the container**
|
||||
(`index.ts`: `.listen(port, "127.0.0.1")`) and serves a tokenized URL.
|
||||
There is no `--host`/bind flag. This matters for a container: a plain
|
||||
`docker run -p 8765:8765` publish forwards to the container's *external*
|
||||
interface, **not** its loopback, so it will not reach Studio. Two paths
|
||||
work:
|
||||
|
||||
**A. Host networking (simplest — recommended on OrbStack / single-host).**
|
||||
Run the container with host networking so the container's loopback is the
|
||||
host's loopback:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
devbox:
|
||||
network_mode: host # container 127.0.0.1 == host 127.0.0.1
|
||||
```
|
||||
|
||||
Then `http://127.0.0.1:8765/?token=…` works in a browser on the Docker
|
||||
host. (Note: host networking changes `host.docker.internal` semantics, so
|
||||
weigh it against the LAN-jump SSH feature if you use that.)
|
||||
|
||||
**B. Loopback bridge (portable — bridge networking).** Publish a port and
|
||||
bridge the container's loopback to its external interface with a one-liner
|
||||
(uses the bundled `node`; binds the eth0 IP only, so it never clashes with
|
||||
Studio's own `127.0.0.1:8765` listener):
|
||||
|
||||
```yaml
|
||||
services:
|
||||
devbox:
|
||||
ports:
|
||||
- "127.0.0.1:8765:8765" # host-localhost only
|
||||
```
|
||||
|
||||
```bash
|
||||
# inside the container, after /studio --port 8765:
|
||||
EXT=$(hostname -i)
|
||||
node -e 'const net=require("net"),p=process.env.STUDIO_PORT||8765,h=process.argv[1];\
|
||||
net.createServer(c=>{const u=net.connect(p,"127.0.0.1");c.pipe(u);u.pipe(c);u.on("error",()=>c.destroy());c.on("error",()=>u.destroy());}).listen(p,h,()=>console.log("bridge "+h+":"+p+" -> 127.0.0.1:"+p));' "$EXT"
|
||||
```
|
||||
|
||||
### Remote host (SSH / mosh)
|
||||
|
||||
When the Docker host is remote, keep Studio on localhost and forward the
|
||||
port from your laptop:
|
||||
|
||||
```bash
|
||||
ssh -L 8765:127.0.0.1:8765 user@docker-host # then open the token URL locally
|
||||
```
|
||||
|
||||
**mosh cannot forward ports** (no `-L`/`-R` equivalent). To use Studio
|
||||
over a mosh session, run a *separate* `ssh -L 8765:127.0.0.1:8765 host`
|
||||
tunnel alongside mosh (mosh for the shell, ssh for the port), or reach the
|
||||
host's published port directly over a trusted network (LAN / Tailscale /
|
||||
WireGuard).
|
||||
|
||||
> PDF export (`/studio-pdf`, `studio_export_pdf`) needs a LaTeX engine,
|
||||
> which is **not** in `-studio` (only the planned `-studio-tex`). HTML
|
||||
> export, KaTeX, Mermaid, and all REPL features work without it.
|
||||
|
||||
## docker-compose.yml — basic shape
|
||||
|
||||
```yaml
|
||||
|
||||
Reference in New Issue
Block a user