Imported from ParthKapoor-dev/devex (
AGENTS.md). Install upstream withnpx skills add ParthKapoor-dev/devex. Copyright stays with the author.
Devex Agent Guide
Summary Devex is a cloud development IDE with sandboxed “repl” sessions. The system is split into services. The core service handles auth and session orchestration, while the runner provides the interactive sandbox (WebSocket + PTY). Session data is persisted to S3-compatible storage when a repl is deactivated.
Architecture (High Level)
- Core service (
apps/core) is deployed to a VPS via Docker Swarm and is the control plane. - Runner service (
apps/runner) is the data plane sandbox image. Each repl is a Kubernetes Deployment with a single pod. - Pod layout:
initContainerpulls workspace files from S3.runnerContaineris the interactive sandbox (WebSocket + PTY).
- Deactivation flow:
- Core injects an ephemeral container into the pod to upload workspace data to S3.
- Core then deletes Deployment/Service/Ingress/Middleware.
- Routing:
- Base host:
repl.parthkapoor.me - Route pattern:
repl.parthkapoor.me/<repl-id>/<route> - Uses
hostNetwork: trueto avoid a load balancer and save cost.
- Base host:
Key Entry Points
- Core API:
apps/core/cmd/main.go - Runner API:
apps/runner/cmd/main.go - MCP service:
apps/mcp/cmd/main.go
Repo Layout
apps/core/: Control-plane service (auth + session orchestration + k8s + s3 + redis).apps/runner/: Sandbox service (WebSocket, PTY, file operations, shutdown manager).apps/mcp/: MCP server.apps/web/: Frontend web app.apps/agent/: Agent-related app (check README inside).packages/: Shared Go packages and generated protobufs.packages/logging: Shared logger wrapper.packages/proto+packages/pb: Proto sources and generated code.
infra/: Deployment and infrastructure.infra/core/: Swarm dockerfile + stack config.infra/runner/: Runner dockerfiles (base + language variants).infra/mcp/: MCP dockerfile.infra/k8s/: K8s manifests, cert-manager, ingress, traefik.
templates/: Repl templates synced to object storage.
Data Stores
- Redis: repl/session state.
- S3-compatible storage: workspace persistence on session end.
Build and Test (Local)
- Core build:
cd apps/corego build -o /tmp/core ./cmd/main.go
- Runner build:
cd apps/runnergo build -o /tmp/runner ./cmd/main.go
- Docker images:
docker build -f infra/core/dockerfile -t devex/core:local .docker build -f infra/runner/dockerfile -t devex/runner:local .
CI/CD
- Workflows live in
.github/workflows/. - Core pipeline builds/pushes and deploys via Docker Swarm.
- Runner pipeline builds runner + env images.
- Templates pipeline syncs
templates/to DigitalOcean Spaces.
Where to Look First
- Auth/session logic:
apps/core/services/auth/ - Repl lifecycle:
apps/core/services/repl/andapps/core/internal/k8s/ - Runner WS/PTY:
apps/runner/pkg/ws/,apps/runner/pkg/pty/ - Shared logging:
packages/logging/
Notes for Agents
- The system relies on
hostNetwork: truefor simplicity and cost. - The core service is the orchestrator; runner instances are ephemeral and created per repl session.
- If you change protobufs in
packages/proto/, regenerate viamake generate-proto.
Frontend
Working on apps/web? Read apps/web/AGENTS.md first.
It covers the design-token system (raw Tailwind palette shades are banned in
component code), the animation/performance rules, MDX documentation authoring,
and SEO. The frontend's distinctive animated look is a product asset — the brief
is to keep it striking while keeping it cheap, not to simplify it away.
The visual direction is Graphite + Signal: true-neutral surfaces at zero chroma with a single amber accent, rationed to roughly 1-2% of the pixels on screen. The accent means one thing — this is the thing you are on. Colour that is not the accent belongs in the backdrop, not the chrome.
Things that bite immediately:
apps/webbuilds on webpack, not Turbopack (npm run devomits the flag). MDX plugins cannot cross Turbopack's loader boundary on Next 15.- Do not run
npm run buildwhilenpm run devis running. They share.next; the build overwrites artifacts the dev server has open and it fails with aMODULE_NOT_FOUNDin_document.jsthat looks like a missing dependency but is not. - Docs are authored MDX in
apps/web/content/docs/, not scraped READMEs. The old GitHub-scraping pipeline is deleted; do not reintroduce it. - Canvas, WebGL, Satori and the manifest cannot resolve
var()oroklch(). Import hex fromapps/web/lib/tokens.ts. - The editor (Monaco) and the docs (Shiki) share one syntax palette. Change
components/sandbox/Editor/theme.tsandlib/docs/shiki-theme.tstogether. - Do not change the
glassutility. The maintainer asked to keep that treatment as-is. (The footer itself was redesigned on 2026-09-13, at the maintainer's request, along with everything after the FAQ.) - The landing page runs one WebGL context at a time. Two exist — the
hero's CRT and the footer's blaze — and they are a full page apart, so
neither is ever live while the other is: each pauses the moment it leaves
the viewport, and the blaze's shader chunk is not even fetched until the
footer is within a screen and a half. That is the whole budget. A third
shader, or a second one that can share the viewport with either of these,
needs a different answer — CSS, a scroll-linked transform, or a 2D canvas on
useCanvasScene. components/brand/block-wordmark.tsxis unused on purpose. The maintainer asked to keep it for later; do not delete it as dead code.- Run
npm run audit:agentsbefore calling a frontend change done. It scores how readable the site is to an AI agent (npx ax audit devx.parthkapoor.me). Production was 30/100 when first measured. The audit reads the deployed origin, not your working tree, so the number only moves after a deploy. Every agent-facing document — robots.txt, llms.txt, the markdown twins, the OpenAPI spec, the/.well-knowncatalogues — is generated fromapps/web/lib/agents.ts; change a fact there, not in the documents.apps/web/AGENTS.mdhas the full table and the list of checks that need backend work instead.
Transactional email (apps/core/internal/email)
The magic-link email is a table-based HTML template in
internal/email/templates/, rendered by render.go.
- It is parsed with
text/template, NOThtml/template.html/templatestrips every HTML comment, which silently deletes the MSO conditional comments carrying the bulletproof VML button and the Outlook ghost tables. There is no error — the button just breaks in Outlook.render_test.goguards this; if it starts failing, someone switched the package. - Escaping is therefore ours. Every field on
magicLinkDatais escaped at construction innewMagicLinkData. Anything added must be too. - The template is authored dark, and declares
<meta name="color-scheme" content="dark">— notlight dark— so Apple Mail and iOS leave it alone instead of inverting it. Clients that force an invert anyway (Outlook mobile, OWA) are handled by re-asserting every colour under[data-ogsc]and[data-ogsb].render_test.goasserts the palette is the current one, so a stale brand colour fails the build rather than shipping. - Banned in email HTML:
backdrop-filter,linear-gradient,display:flex,position:absolute, web fonts. Tests assert their absence. Use nested tables and solidbgcolorcells — the accent bar is four adjacent coloured cells, not a gradient. - Always send the
text/plainalternative; HTML-only mail is a spam signal. - Preview it:
EMAIL_PREVIEW_DIR=/tmp go test ./internal/email/ -run TestWriteEmailPreview
