The workflow showed a session from the user’s side. This page opens the machinery: which images exist and why, what the sandbox profile enforces, what the manifest, the file the container writes about itself, tells the agent, and how host skills and host services are let into the container.
The image family
A single container carrying every tool anyone might need would be enormous and
mostly wasted. Instead secdev builds a tree of images that inherit from one
another. Each carries the same set of coding agents; each adds the toolchain
for one kind of work. The tree of images:
What each image adds, nested as in the tree, so that an indented image inherits everything from the image above it:
baseis ordinary development: C/C++, Rust, Go, Python and Node toolchains,uvfor Python environments, and the usual search and text tools. Every agent lives here.browseradds Playwright driving Chromium and Firefox without a screen (headless browsers), for automation, not for logging in.webadds Apache serving the working directory, PHP and Hugo. This site is built in thewebimage.opencmsadds the skill for the university’s content management system; see OpenCMS .
texadds TeX Live,latexmk,biber,pandoc, linters and two skills (editorial pass, sketch-to-TikZ).newtonadds the scientific Python stack, Maxima, Octave, gnuplot, Fortran, the Lean proof system, and the fixed project layout for research (the research scaffold) documented under Research .einsteinadds SSH access to a host with graphics processors (GPUs), a computer-algebra host and the compute cluster with its SLURM job scheduler, the program that queues jobs and starts them when nodes are free, and a shared remote home. Hosts come from the config, never from the image.
officeadds LibreOffice without its window, text recognition for scans (OCR) and PDF-form tooling with document skills.
localroutes OpenCode to a model on institute hardware.
./build.sh <variant> builds one image and its parents.
The sandbox profile
A sandbox profile is the set of limits a container runs under. --security N
selects one at launch, and the config sets the default. In the table, sudo
means running a command as the machine’s administrator; withholding it stops
the agent changing the container itself. The two profiles in daily use:
| Level | sudo | Caps and privileges | /tmp | Typical use |
|---|---|---|---|---|
| 0 | yes | none | container filesystem, no size cap | Trusted work that must install system packages |
| 1 | no | RAM, CPU and process-count caps from the config; no new privileges; almost all Linux capabilities (individual administrator powers) dropped | an in-memory filesystem, one per container | The everyday default |
The “Caps and privileges” column has one exception: when einstein mounts a
remote home, the launcher keeps the few privileges that sshfs, a remote
directory reached over SSH, needs.
Higher levels exist that also restrict the container’s network to an allow list of destinations, with the container running behind a firewall of its own. They are experimental and not fully operational, so the table leaves them out.
When a resource cap (memory, processor or process count) cannot be applied
because the container runs without root privileges, the launcher drops it with
a warning, and host_info inside the container shows which caps applied.
The manifest: telling the agent where it is
An agent dropped into an unfamiliar environment discovers its constraints by
running into them: it tries sudo, fails, tries something else; it assumes a
tool exists and burns a minute finding out it does not. So at every container
start, secdev writes SECDEV.md into the working directory: the tools,
services, isolation, active security settings, reachable endpoints, and the
things the agent must not attempt. The manifest is assembled from one
fragment per image layer and filled in with the current settings at start, so
the file describes the container that is running, at the level it is running
at. AGENTS.md, the
file most agents read first, receives a short managed block that points at
the manifest; content outside that block is never touched.
Skills: bundled and mounted
A skill is a directory holding a SKILL.md procedure plus any scripts or
reference material it needs; an agent loads it when a task matches. secdev
links two sources into every agent’s skill directory at container start:
bundled skills, baked into the image layer whose tooling they need, and
host skills from a directory named in the config or given with
--skills DIR for one run, mounted read-only. A bundled skill wins over a
host skill of the same name. Editing a host skill takes effect at once;
adding or removing one needs a container restart.
The configuration file
The installer writes a first ~/.config/secdev/config.toml, readable by you
alone because it can hold keys. The sections a user edits:
[container]
memory = "8g" # caps at level 1
cpus = "4"
pids_limit = "512"
tmpfs_size = "1g"
[security]
default_level = 1
[runtime.skills]
# your own skills, mounted into every container
dir = ""
# einstein: user@host per helper, empty disables it
[hosts]
gpu = ""
mathematica = ""
slurm = ""
remote_home = ""
Changes take effect on the next launch, except [hosts], which needs a rerun
of ./install.sh to regenerate the SSH configuration. Further sections
configure three things: the local variant’s route to its model (optionally
through an SSH tunnel to a model elsewhere on the institute network), the
logins to keep across containers, and the agent identities described next.
Agent identities (optional)
A container is anonymous by default: it holds none of your credentials, and
the manifest forbids it to push. An identity lifts that ban for one named
agent, so several agents can work on one project through a shared Git remote.
secdev identity add generates an SSH keypair, records the Git server’s host
key so that a server presenting a different key is refused, and prints the
public key for you to register with the Git-server account you have set up
for that agent; secrets never enter the config file. A container started
with --identity commits and pushes as that account, keeps its own agent
logins, and gains a manifest section that states the narrow conditions under
which the ban is lifted: push to origin only, no new remotes, no
force-push, no tags. The identity commands:
# once per agent, on the host; asks for account and email
secdev identity add pi
secdev identity list
secdev identity show pi # settings and public key
secdev --identity pi newton # run as that agent
secdev attach --identity pi
secdev identity remove pi # credentials and saved logins
Give each agent its own clone: two containers in one directory fight over the working tree. The project layout for several agents that goes with identities is described under Research’s Technical Details .
MCP services (optional)
MCP (Model Context Protocol) is the standard by which an agent calls tools
that live in another process. A container needs none, but secdev lets
OpenCode use MCP servers declared in the configuration file, one section
each. A remote server is a URL. A server on the
host can instead expose a Unix socket, a file on the host’s disk: the launcher
mounts the socket’s directory read-only and relays it to an address inside
the container that only the container itself can reach (a loopback
address). No endpoint or token is baked into an image; both are read from
the config at launch. Wingman
uses this route to give an
agent hands on the institute’s servers without giving it the key, and
Wingman’s Technical Details
shows the
configuration and the relay.
OpenCode in a browser (optional)
OpenCode
ships a web front end; secdev can start it
instead of a shell:
# host loopback, HTTP basic auth
secdev --opencode-web
secdev local --opencode-web --port N # a different host port
The front end requires a password in the config. It listens only on the
host’s own loopback address, which other machines cannot reach, unless an
explicit --publish says otherwise. It speaks plain HTTP, so any exposure
beyond the machine belongs behind a TLS proxy. A system prompt file named in
the config sets the instructions of the default agent without a rebuild.