📚 Update and improve devenv documentation

* Fix stale references to `run-devenv-agentic` and `start-devenv`
* Improve clarity in description of workspaces
* Improve section on agentic devenv

Co-authored-by: Michael Panchenko <michael.panchenko@oraios-ai.de>
This commit is contained in:
Dominik Jain 2026-06-24 16:52:54 +02:00 committed by Alonso Torres
parent 93b5baa9fc
commit b9e0421f79
4 changed files with 53 additions and 55 deletions

View File

@ -52,7 +52,7 @@ built fresh from `shared/codex.toml` + `templates/codex.toml` at launch.
`manage.sh`.
* **`mcp/`** (Claude Code, opencode) is the result of merging `shared/` with
the port-substituted `templates/`. `manage.sh` writes these on every
`run-devenv-agentic` pass. Gitignored, dedicated paths with no developer
`run-devenv --agentic` pass. Gitignored, dedicated paths with no developer
content — never edit by hand, your edits will be overwritten on the next
reconcile.
* **`.vscode/mcp.json`** is the same merge, but written to the path VS Code

View File

@ -25,7 +25,7 @@ Compose-based dev environment under `docker/devenv/`, driven by `manage.sh`. Par
## Worker policy
Backend workers run only on ws0. `_env` gates `enable-backend-worker` on `PENPOT_BACKEND_WORKER`; ws1+ inject it as false. ws0 must be running whenever any ws1+ is running, and is the last instance to stop — `run-devenv-agentic --ws N` (N≥1) auto-starts ws0 first; `stop-devenv` refuses to stop ws0 while any ws1+ is up. Workers are pure fire-and-forget: `wrk/submit!` inserts a row into the shared Postgres `task` table and returns; RPC handlers never wait on completion and workers never publish to msgbus. The reason for "ws0 only" is avoiding multi-instance worker races (cron dedup is best-effort across instances, `wrk/submit!` `dedupe` is racy across submitters); details in `mem:prod-infra/core`.
Backend workers run only on ws0. `_env` gates `enable-backend-worker` on `PENPOT_BACKEND_WORKER`; ws1+ inject it as false. ws0 must be running whenever any ws1+ is running, and is the last instance to stop — `run-devenv --agentic --ws N` (N≥1) auto-starts ws0 first; `stop-devenv` refuses to stop ws0 while any ws1+ is up. Workers are pure fire-and-forget: `wrk/submit!` inserts a row into the shared Postgres `task` table and returns; RPC handlers never wait on completion and workers never publish to msgbus. The reason for "ws0 only" is avoiding multi-instance worker races (cron dedup is best-effort across instances, `wrk/submit!` `dedupe` is racy across submitters); details in `mem:prod-infra/core`.
## Port layout
@ -44,13 +44,13 @@ Everything else (frontend dev, backend API, exporter, storybook, REPLs, plugin d
## Tmux + MCP routing
`docker/devenv/files/start-tmux.sh` is session-level idempotent. Reads `PENPOT_TMUX_ATTACH`. If the session exists it attaches or exits; otherwise creates 4 base windows (frontend watch / storybook / exporter / backend) plus `mcp` (when `enable-mcp` in `PENPOT_FLAGS`) and `serena` (when `SERENA_ENABLED=true`). `run-devenv-agentic` always sets both env vars. The legacy `run-devenv` alias doesn't, hence its 4-window-only session. To switch from a legacy session to agentic, `stop-devenv` then `run-devenv-agentic` — the conditional windows are only added at session create time.
`docker/devenv/files/start-tmux.sh` is session-level idempotent. Reads `PENPOT_TMUX_ATTACH`. If the session exists it attaches or exits; otherwise creates 4 base windows (frontend watch / storybook / exporter / backend) plus `mcp` (when `enable-mcp` in `PENPOT_FLAGS`) and `serena` (when `SERENA_ENABLED=true`). `run-devenv --agentic` always sets both env vars. The legacy `run-devenv` alias doesn't, hence its 4-window-only session. To switch from a legacy session to agentic, `stop-devenv` then `run-devenv --agentic` — the conditional windows are only added at session create time.
MCP plugin routing is same-origin: frontend uses `<public-uri>/mcp/ws`, per-instance nginx proxies to MCP port 4401 in-container. For the plugin↔MCP server wiring (how the browser plugin discovers the URL, the in-memory connection registry, why DB-mediated routing isn't needed), see `mem:mcp/core`.
## Workspace orchestration (ws1+)
Workspace directories are user-maintained at `${PENPOT_WORKSPACES_DIR}/wsN`. `run-devenv-agentic --ws i` syncs only when `--sync` is passed, with one exception: if the workspace directory is missing on first use, sync runs implicitly to seed it.
Workspace directories are user-maintained at `${PENPOT_WORKSPACES_DIR}/wsN`. `run-devenv --agentic --ws i` syncs only when `--sync` is passed, with one exception: if the workspace directory is missing on first use, sync runs implicitly to seed it.
`sync-workspace wsN`:
1. `assert-clean-git-state` — refuses on `.git/{rebase-apply,rebase-merge,MERGE_HEAD,CHERRY_PICK_HEAD,index.lock}`. No `--sync-force` escape.
@ -63,7 +63,7 @@ No `--delete` on the working-tree pass: gitignored caches in the workspace survi
## CLI surface
- `run-devenv-agentic [--ws main|0|wsN|N] [--sync] [--serena-context CTX]`: bring one instance up. Agentic only — MCP and Serena windows are always created. Default target main. Errors out if the target is already running. `--sync` is rejected on main; on ws1+ it's optional (forced only when the workspace dir does not exist yet). Auto-starts ws0 first when the target is ws1+ and ws0 is not yet up.
- `run-devenv --agentic [--ws main|0|wsN|N] [--sync] [--serena-context CTX]`: bring one instance up. Agentic only — MCP and Serena windows are always created. Default target main. Errors out if the target is already running. `--sync` is rejected on main; on ws1+ it's optional (forced only when the workspace dir does not exist yet). Auto-starts ws0 first when the target is ws1+ and ws0 is not yet up.
- `stop-devenv [--ws main|0|wsN|N] [--all]`: stop instances. Flags mutually exclusive. `--ws N` (N≥1) stops just that workspace. `--ws 0` or no flag stops ws0 + shared infra, refused while any ws1+ is running. `--all` stops every ws highest-first then ws0, then infra.
- `run-devenv`: legacy alias, ws0 non-agentic attached.
- `attach-devenv [--ws main|0|wsN|N]`: pure attach. Fails fast if instance/session missing.

View File

@ -1,30 +1,22 @@
---
title: 3.11. Agentic Development Environment
title: 3.11. Agentic Dev Environment
desc: Dive into agentic Penpot development.
---
# Agentic Development Environment
# Agentic Dev Environment
The agentic DevEnv is an extension of the standard DevEnv (the
[general DevEnv instructions](/technical-guide/developer/devenv/) apply),
optimised for AI agent-based development. It adds MCP servers (Penpot,
Serena, Playwright) and supports a launcher that wires them into your AI client.
Two things to know up front:
- **Parallel workspaces are first-class.** Run several devenv instances side
by side - one per AI agent if you like - each with its own source-tree
clone, ports, and tmux session. Pass `--ws N` to target one.
- **Your existing AI-client config is preserved.** The launcher loads a
per-workspace MCP config on top of your global one.
## Quick Start
1. **Bring up one or more workspaces**[^cfg]:
```bash
./manage.sh run-devenv-agentic # ws0 (the live repo)
./manage.sh run-devenv-agentic --ws 1 # ws1 (sibling clone)
./manage.sh run-devenv --agentic --attach # ws0 (the live repo)
./manage.sh run-devenv --agentic --ws 1 # ws1 (sibling clone)
```
Add `--ws 2`, `--ws 3`, … for more parallel workspaces.
@ -47,20 +39,20 @@ Two things to know up front:
"MCP Server" on. The agentic DevEnv runs the MCP server in single-user
mode - the key and proxied URL shown in the UI are not needed.
4. **Launch your AI client** against the workspace you want it to drive:
4. **Launch your AI client**. Either use your manually configured client
(as described below) or conveniently launch an explicitly supported client
against the workspace you want it to drive:
```bash
./manage.sh start-coding-agent claude # ws0
./manage.sh start-coding-agent claude # ws0 (main)
./manage.sh start-coding-agent claude --ws 1 # ws1
```
Supported clients: `claude` | `opencode` | `vscode` | `codex`.
5. **Attach to the tmux session** for the workspace (optional):
Note: The launcher loads a per-workspace MCP config on top of your global one (if any).
```bash
./manage.sh attach-devenv # ws0
./manage.sh attach-devenv --ws 1 # ws1
```
5. **Work within your client**, which is now equipped with extended capabilities
for Penpot development (see below for details).
6. **Shut down workspaces** with `./manage.sh stop-devenv`, either one by one or all at once.
You cannot shut down `ws0` if any other workspace is still running, since it's the worker-bearer.
@ -113,10 +105,10 @@ var penpotFlags = "enable-mcp";
```
The file is gitignored and lives in the live repo only. On every
`run-devenv-agentic` call it is read directly for ws0; for wsN (N ≥ 1) it is
`run-devenv --agentic` call it is read directly for ws0; for wsN (N ≥ 1) it is
copied into the workspace clone on the **initial** sync only - subsequent
`--sync` passes leave the workspace's copy alone so per-workspace
customisations survive. `run-devenv-agentic` refuses to start if the file is
customisations survive. `run-devenv --agentic` refuses to start if the file is
missing.
**Browser remote debugging.** The Playwright MCP server drives a real
@ -148,13 +140,13 @@ devenv image itself (add a tool, change a base layer):
./manage.sh build-devenv --local
```
The default `run-devenv-agentic` flow pulls the published image
The default `run-devenv --agentic` flow pulls the published image
automatically, so regular users never run this.
### Bringing up workspaces
```bash
./manage.sh run-devenv-agentic \
./manage.sh run-devenv --agentic \
[--ws N] [--sync] [--serena-context CTX] \
[--git-user-name NAME] [--git-user-email EMAIL]
```
@ -171,7 +163,7 @@ every bring-up so you don't compute offsets by hand. See the
semantics, and stop ordering.
**Git identity for agent commits.** Coding agents typically need to commit
inside the devenv, so `run-devenv-agentic` wires a Git identity into the
inside the devenv, so `run-devenv --agentic` wires a Git identity into the
container's global config on every bring-up. By default it propagates the
host's effective `git config user.{name,email}` (local repo override wins
over `~/.gitconfig`, matching what `git commit` on the host would record).
@ -189,7 +181,7 @@ the full mechanics.
>
> ```bash
> ./manage.sh stop-devenv
> ./manage.sh run-devenv-agentic
> ./manage.sh run-devenv --agentic
> ```
### Launching an AI client
@ -198,7 +190,7 @@ The agentic environment supports any AI client, one just needs to set the right
see [manual configuration](#manual-ai-client-configuration) below. For some popular clients, the `manage.sh`
CLI offers direct support through the following mechanism:
Every `run-devenv-agentic` regenerates three MCP-client config files with
Every `run-devenv --agentic` regenerates three MCP-client config files with
the workspace's ports baked in; Codex is wired up at launch instead (see
below):

View File

@ -45,31 +45,38 @@ This is an incomplete list of devenv related subcommands found on
manage.sh script:
```bash
./manage.sh build-devenv --local # builds the local devenv docker image
./manage.sh start-devenv # brings up the shared infra + ws0 in background
./manage.sh run-devenv # ws0 with non-agentic tmux, attached (legacy alias)
./manage.sh run-devenv-agentic # one agentic instance; --ws to target ws1+; see below
./manage.sh attach-devenv # re-attaches to the tmux session of a running instance
./manage.sh stop-devenv # stops one instance (or --all); infra stops with the last
./manage.sh drop-devenv # removes containers (data volumes preserved)
./manage.sh build-devenv --local # builds the local devenv docker image
./manage.sh start-devenv # brings up the shared infra + ws0 in background
./manage.sh run-devenv --attach # bring up main devenv instance and attach to its tmux session
./manage.sh run-devenv --agentic --attach # bring up main devenv instance in agentic mode and attach tmux
./manage.sh attach-devenv # re-attaches to the tmux session of a running instance
./manage.sh stop-devenv # stops one instance (or --all); infra stops with the last
./manage.sh drop-devenv # removes containers (data volumes preserved)
```
### Agentic Mode
The `--agentic` flag enables additional features for AI-assisted development.
See the dedicated section [Agentic Dev Environment](../agentic-devenv/) for details.
### Parallel workspaces
The devenv runs as separate compose projects: shared infra (`penpotdev-infra`:
Postgres, MinIO, mailer, LDAP) plus one `penpotdev-wsN` project per runtime
instance. `ws0` (a.k.a. `main`) binds the live repo; `ws1+` bind clones the
developer maintains explicitly under `${PENPOT_WORKSPACES_DIR}/wsN/`
(default `~/.penpot/penpot_workspaces/`).
The devenv runs as separate compose projects:
* shared infra (`penpotdev-infra`: Postgres, MinIO, mailer, LDAP)
* `penpotdev-wsN` project per runtime instance.
- `ws0` (a.k.a. `main`) is the current state of your repo;
- `ws1` and up are clones that you maintain explicitly under `${PENPOT_WORKSPACES_DIR}/wsN/`
(default `~/.penpot/penpot_workspaces/`). You can explicitly sync them
with the `--sync` flag (automatic on first start).
Each call to `run-devenv-agentic` brings up one instance, and ws0 is always
Each call to `run-devenv` brings up one instance, and ws0 is always
running whenever any ws1+ is — `--ws N` (N≥1) auto-starts ws0 first if it
isn't already up:
```bash
./manage.sh run-devenv-agentic # main (ws0)
./manage.sh run-devenv-agentic --ws 1 # ws0 if needed, then ws1
./manage.sh run-devenv-agentic --ws 2 --sync # ws2, re-seeding from the live repo
./manage.sh run-devenv # main (ws0)
./manage.sh run-devenv --ws 1 # ws0 if needed, then ws1
./manage.sh run-devenv --ws 2 --sync # ws2, re-seeding from the live repo
```
Starting an instance that is already running is an error. `--sync` is only
@ -102,12 +109,12 @@ Host ports are offset by `10000 × N`:
| Serena MCP | `http://localhost:14181` | `http://localhost:24181` | `http://localhost:34181` |
Container-internal ports stay fixed. Target a specific instance with
`--ws N` on `attach-devenv`, `run-devenv-agentic`, `stop-devenv`,
`--ws N` on `attach-devenv`, `run-devenv`, `stop-devenv`,
`start-coding-agent`, `run-devenv-shell`, and `isolated-shell`. `--ws`
accepts a **non-negative integer only**`--ws main` or `--ws ws1` is
rejected, keeping the flag shape uniform across commands. `run-devenv` is
ws0-only and takes no workspace flag. `run-devenv-agentic` also accepts
`--serena-context CTX` and `--git-user-name NAME` / `--git-user-email
ws0-only and takes no workspace flag. `run-devenv` also accepts
`--serena-context CTX` (used together with `--agentic`) and `--git-user-name NAME` / `--git-user-email
EMAIL` (see below).
Configuration lives in one tracked file, `docker/devenv/defaults.env` (the
@ -116,7 +123,7 @@ derived and injected automatically, so there is no per-instance file to edit.
### Git identity inside the container
`run-devenv-agentic` wires a Git author identity into the container's
`run-devenv` wires a Git author identity into the container's
**global** git config (`git config --global user.{name,email}`) so commits
made from inside the devenv carry a real author/committer. Without this,
the container would commit as the unconfigured `penpot@<container>`
@ -130,7 +137,7 @@ returns at the working directory `manage.sh` is invoked from — local
`git commit` on the host would record. If neither is available the script
prints a warning and continues — commits will fail inside the container
until you set an identity. The values are applied every time
`run-devenv-agentic` brings an instance up (idempotent), so re-running
`run-devenv` brings an instance up (idempotent), so re-running
with different flags is the way to change the in-container identity.
### Shared state and workers
@ -185,11 +192,10 @@ docker rm penpotdev-postgres-1 penpotdev-minio-1 penpotdev-minio-setup-1 \
docker network rm penpotdev_default 2>/dev/null
# Bring up infra + ws0 under the new project layout.
./manage.sh run-devenv-agentic
./manage.sh run-devenv
```
After the cleanup, normal `./manage.sh start-devenv` / `run-devenv` /
`run-devenv-agentic` commands work against the new layout. The legacy
After the cleanup, normal `./manage.sh start-devenv` / `run-devenv` work against the new layout. The legacy
`penpotdev` compose project is no longer used.
Having the container running and tmux opened inside the container,