Add components to a workbench
You don’t design the whole workbench up front. You start with what you need
today and add the rest when you actually need it. This guide follows one
workbench, called acme, as it grows from a plain Node project into one with a
database and GitHub access. Every step is the same loop: change the config,
then apply.
Start small
Section titled “Start small”On day one you know two things: it’s a Node app, and you want Claude Code in the workbench to help you build it. So that’s what you start with.
monoceros init acme --with-languages=node --with-features=claudeinit doesn’t build anything yet. It writes two files and stops, both under
~/.monoceros/container-configs/: acme.yml describes the workbench, and
acme.env holds the secrets the yml points at. You can open and edit them by
hand any time, though most of the time you let the add- commands do it.
Here is what you get (the real files also carry comments that explain each
field, dropped here for brevity):
schemaVersion: 1name: acmeruntimeVersion: 1.8.0languages: - node:22features: - ref: ghcr.io/getmonoceros/monoceros-features/claude-code:1 options: permissionMode: auto apiKey: ${CLAUDE_CODE_API_KEY}CLAUDE_CODE_API_KEY=The yml is the source of truth. Node is pinned to a major version, and Claude
Code comes in as a feature. Notice its apiKey: it points at
${CLAUDE_CODE_API_KEY} in the env file, and that key is empty. That is fine.
Leave it blank and Claude Code asks you to log in through your browser on first
run. If you would rather use an API key, paste it there.
When the config looks right, build it:
monoceros apply acmeapply reads the yml, builds the workbench, and prints the command to get
inside.
Work inside it
Section titled “Work inside it”The workbench is up. There are a few ways to get to work, and you will mix them.
Open a shell and do whatever you would do on your own machine:
monoceros shell acmeYou land in a bash session inside the workbench. Your tools are all there,
Claude Code included: type claude and it starts right in the workspace.
Run a single command without leaving a session behind. This is how you hand the agent a task, run a build, or start a dev server:
monoceros run acme --in projects/web -- claude "Add a health-check endpoint at /healthz"Everything after -- runs inside the workbench, and run exits when it does.
--in sets the working directory, so point it at your project under
projects/.
Or connect your editor. open attaches VS Code (or VS Codium) to the workbench
over SSH, so you edit the code inside it with your normal IDE while your host
stays clean:
monoceros open acme codePrefer Claude Code as a desktop app? It attaches the same way. Point its
Connect to SSH host feature at the host monoceros apply set up, and Claude
Code runs inside the workbench while the app stays on your host. See Claude
Code for the walkthrough.
Pick whichever fits the moment. However you work, it all runs inside the workbench, against its tools and services, never on your host. For editor setup and other tools, see Use an IDE.
Here it is on screen: apply builds the workbench, then open attaches the
editor straight to it.
Add a database
Section titled “Add a database”The app needs to store things, so you add Postgres. You don’t edit the yml by hand. You let Monoceros do it:
monoceros add-service acme postgresTwo things change. The yml gets a services section, and acme.env gets three
new values with working defaults:
services: - name: postgres image: postgres:18 port: 5432 env: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB} volumes: - data:/var/lib/postgresql healthcheck: test: ['CMD', 'pg_isready', '-U', '${POSTGRES_USER}', '-d', '${POSTGRES_DB}'] interval: 10s timeout: 5s retries: 5 connectionEnv: URL: 'postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${host}:${port}/${POSTGRES_DB}' HOST: '${host}' PORT: '${port}' USER: '${POSTGRES_USER}' PASSWORD: '${POSTGRES_PASSWORD}' DB: '${POSTGRES_DB}'POSTGRES_USER=monocerosPOSTGRES_PASSWORD=monocerosPOSTGRES_DB=monocerosThe useful part is connectionEnv. Monoceros writes ready-made connection
values for the service, including a full URL, so you never build a connection
string by hand or guess the hostname. Inside the workbench Postgres answers at
postgres:5432, and your app reads these values from the environment. The
credentials sit in acme.env if you want to change them.
Nothing is running yet. add-service only changed the files. Bring Postgres up
with another apply:
monoceros apply acmeHere is the whole loop start to finish, the edit and then the build:
Push to GitHub
Section titled “Push to GitHub”Time to get the code off your machine. You want the gh CLI in the workbench
so you can push and open pull requests from the shell. Same move:
monoceros add-feature acme githubThe yml gets a second feature, and acme.env gets an empty token to fill in:
features: # ... the claude-code feature from before, still here ... - ref: ghcr.io/getmonoceros/monoceros-features/github-cli:1 options: apiToken: ${GITHUB_API_TOKEN}GITHUB_API_TOKEN=The github feature reads GITHUB_API_TOKEN. Paste a personal access token
there and gh is signed in as soon as the workbench starts. Leave it empty and
run gh auth login yourself on first run. Either way the login survives
rebuilds, so you do it once.
Need to create the token first? Git and
repositories walks
through it and lists the scopes gh needs: repo, read:org, gist, and
read:user.
And again, it takes effect on the next apply:
monoceros apply acmeOn GitLab it is the same move: monoceros add-feature acme gitlab brings in the
glab CLI, with its token set in acme.env just like the GitHub one. See
GitLab CLI for its token and scopes.
Edit, then apply
Section titled “Edit, then apply”Every step was the same two commands: an add- command to change the config,
then apply to make it real. There is one for each kind of component:
add-language, add-service, add-feature, add-repo, add-port, and a few
more, each with a remove- counterpart. The
yml holds all of it, so anyone who checks it out and runs apply gets the same
workbench you have.
See also
Section titled “See also”- Lifecycle commands -
init,apply,run,shell, and the rest of a workbench’s life. - Config commands - every
add-andremove-editing command, with its options. - Utility commands - listing the catalog, URLs, tunnels, sharing, logs, and upgrades.
- Git and repositories - the full workflow
behind
add-repo: create an access token, store it, clone, and juggle multiple accounts.