Also removes unneeded configurability of the tmux session name
Parallel ws1+ instances were configured by generating a gitignored docker/devenv/instances/wsN.env overlay on every start and layering it over defaults.env with a second --env-file. The file looked editable but was overwritten each run and could go stale; every value in it is a pure function of the instance number.
Replace it with instance-env-overrides, which echoes the per-instance KEY=VALUE pairs that instance-compose injects into its env -i docker compose call. Compose gives shell-env precedence over --env-file, so they override the defaults.env baseline; nothing is written to disk and the values are recomputed every call, so they cannot drift. Re-key the is-it-set-up guard to the workspace clone's existence, drop the unused instances/ dir and its .gitignore entry, and trim the per-instance-config docs and memory to current behaviour.
docker compose config renders byte-identical to the old overlay mechanism for ws0 and ws1.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Support --ws in all relevant commands, fix some bugs in the CLI and add more
precondition validation.
The guide was adjusted to give a better overview of the multi-workspace setup
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
run-devenv-agentic now seeds the container's global git config from the
host on every bring-up so commits made inside the devenv (typically by
coding agents reached through start-coding-agent) carry a real
author/committer instead of the bare `penpot@<container>` fallback that
makes review unworkable.
New optional flags on run-devenv-agentic:
--git-user-name NAME author/committer name
--git-user-email EMAIL matching email
When a flag is omitted the value is resolved from the host's effective
`git config user.{name,email}` (plain `git config`, no --global) so a
per-repo override in <repo>/.git/config wins over ~/.gitconfig -- matching
what `git commit` on the host would actually record. If neither flag nor
host config provides a value the script prints a warning and continues;
in-container commits will fail until the user fixes it.
start-instance applies the values via two `docker exec ... git config
--global user.{name,email}` calls right after the container reaches
Running, before start-tmux.sh is launched. Keeps the write logic next to
the rest of the per-instance bring-up and out of the tmux script -- no
env-var contract between manage.sh and the tmux entry point is needed.
Docs updated in docs/technical-guide/developer/devenv.md (new "Git
identity inside the container" section) and the agentic-devenv guide.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Improve parallel-workspaces developer CLI,
and add an opt-in layer that lets four AI
coding agents (Claude Code, opencode, VS Code Copilot, OpenAI Codex CLI)
drive a specific workspace through a single launcher command.
Parallel-workspace semantics
----------------------------
each run-devenv-agentic call brings up one wsN;
--ws N (integer; default 0) targets a specific workspace and auto-starts
ws0 first when N>=1 so the worker invariant holds. --sync is forbidden on
ws0 and re-seeds the workspace from the live repo for ws1+. Stop semantics
mirror the start invariant -- ws0 is the last to stop, shared infra stops
with it, --all walks every instance highest-first. The worker policy
section explains why workers run only on ws0 (Postgres FOR UPDATE
SKIP LOCKED is safe across many workers but the cron dedup primitive is
best-effort, and :telemetry / :audit-log-archive are not idempotent).
Per-instance Valkey Pub/Sub isolation, msgbus topology, and the
"async task notifications miss ws1+ tabs" caveat are stated explicitly.
The mem:prod-infra/core memory captures the same external-services and
task-queue / Pub-Sub topology in agent-readable form, and
mem:backend/core and mem:critical-info now cross-link it so backend work
surfaces the horizontal-scaling constraints from the start.
AI coding agent integration
---------------------------
New top-level .devenv/ directory holds committed templates
(templates/{claude-code,opencode,vscode}.json and templates/codex.toml,
each with \${PENPOT_MCP_PORT} and \${SERENA_MCP_PORT} placeholders) plus
committed shared entries (matching shared/* files for Playwright, the
only workspace-independent server we ship today).
./manage.sh start-coding-agent <claude|opencode|vscode|codex> [--ws N]
launches the chosen client against one workspace. It cd's into the
target's directory (the live repo for ws0; workspace-path "wsN" for ws1+)
and refuses to launch unless (a) the binary is on PATH, (b) the
workspace directory exists for ws1+, and (c) the instance is up
(devenv-main-running) -- the MCP servers only exist while the devenv is
running. The agentic-devenv guide is restructured around this Quick
start path, with a per-client table and a Manual configuration fallback
for clients we don't cover.
Co-Authored-By: Codex <codex@openai.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add support for running N parallel devenv instances under separate compose
projects sharing Postgres, MinIO, mailer, and LDAP. Each instance has its
own main container, Valkey, source checkout, tmux session, and host port
range offset by 10000 (3449 -> 13449 -> 23449, etc.).
./manage.sh run-devenv-agentic --n-instances N reconciles the running set
to exactly {ws0..ws(N-1)}: missing instances are created (workspace sync
from the live repo via git ls-files + per-instance env-file generation
under docker/devenv/instances/ + detached tmux startup), surplus instances
are stopped highest-first via compose down (never -v), already-running
instances are left untouched. ws0 binds the live repo at PWD; ws1+ are
scratch clones under ~/.penpot/penpot_workspaces/.
Backend workers (enable-backend-worker) are gated on PENPOT_BACKEND_WORKER
in backend/scripts/_env; ws1+ overlays disable them so async-task
notifications stay bound to a single Valkey Pub/Sub instance.
Compose helpers wrap docker compose with env -i so per-instance overlay
--env-file actually overrides defaults.env -- without the strip, the shell
env from sourcing defaults.env at startup would shadow the overlay (Compose
gives shell precedence over --env-file).
Other:
- Drop network aliases (- main, - redis); use container_name for
cross-container DNS so multiple instances on the shared network don't
fight over the same DNS name.
- Pin volume names via name: (PENPOT_*_VOLUME) so volumes survive project
renames; ws0 keeps the pre-existing physical names (penpotdev_*).
- Remove cross-project depends_on from main.yml (postgres/minio-setup now
live in penpotdev-infra); manage.sh ensure-infra-up docker-waits on the
minio-setup one-shot.
- Strict arg parsing in run-devenv / run-devenv-agentic; --n-instances 0
rejected.
- Remove unused Host-matched server block from the Caddyfile.
Memory mem:devenv/core and developer docs updated.
Co-authored-by: Codex <codex@openai.com>
Move shared services into an infra compose file and keep the main devenv container plus Valkey in a separate compose file driven by defaults.env. Parameterize host-side ports, container names, source path, and runtime env while keeping container-internal ports fixed for same-origin proxying.
Make tmux startup idempotent, add attach-devenv for the live instance, move shared MinIO user setup to infra startup, and let exporter scripts load backend _env.local overrides.
Co-authored-by: Codex <codex@openai.com>
* Revert "🐛 Detect duplicated token names in the whole library (#9034)"
This reverts commit 61cd7573553b1c5e9fc2d7300cf9b2c36b4dcbb6.
* 🔧 Preserve some enhancements and fixes that are still valid
* 🔧 Fix broken integration tests