Manor is a Docker-first personal agent harness.
It keeps Codex on a warm worker, puts Butler in charge of supervision, and gives each job private previews, disposable services, and stack-scoped runtime state without exposing raw app ports on the host.
- Public Preview
- Screenshots
- Opinionated by Design
- Quick Start
- Image Distribution
- Core Model
- Execution Rule
- Runtime Surfaces
- Auth
- Trust and Security Model
- Development
- License
Manor is usable, but early. Expect rough edges around setup, upgrades, and advanced runtime workflows.
The current goal is a dependable single-operator appliance: clear Docker setup, honest trust boundaries, durable worker state, and practical runtime isolation for agent-led development work.
The example project Butler was given to build in the screenshots below is peter-olom/vaultfolio-drive.
Manor's patterns are heavily shaped by my operating opinions.
The project optimizes for a specific way of working:
- Docker-first development and verification
- one trusted operator, not a hosted multi-tenant product
- warm long-running agents instead of throwaway prompt sessions
- explicit supervision through Butler
- isolated previews for installs, builds, and app runtime
- evidence over status-only reporting
- private ingress and narrow host exposure
- simple primitives before broad orchestration layers
That bias is intentional. Manor is not trying to be neutral infrastructure for every team shape, but with it you can build and run most things.
Prerequisites:
- Docker with Compose support
- OpenAI API-key auth or ChatGPT device-code login
- GitHub auth in the Codex box if repo cloning or fresh project setup is needed
Run the guided installer:
./install.shThe installer checks Docker and Compose, writes local Compose settings, generates a local runtime broker token, and can start Manor.
By default, the installer pulls published Manor images from GHCR. To build images locally instead:
./install.sh --build-from-sourceTo pin a published image tag:
./install.sh --image-tag sha-<commit>For the default non-interactive setup:
./install.sh -yThen open:
http://127.0.0.1:8180
Daily control:
./manor.sh start
./manor.sh stop
./manor.sh status
./manor.sh logsInteractive defaults:
- host port:
8180 - image registry:
ghcr.io/peter-olom - image tag:
latest - build from source: off
- Codex auto-update on reboot: off
- Codex auto-update target:
latest - require Codex auto-update before startup: off
- start Manor after install: yes
Manor runs as one Docker Compose project with these services:
butler: the always-on supervisor and web appbutler-gateway: the host-facing reverse proxy for the Butler UIcodex-box: the trusted worker container that owns repos, tools, and long-running workruntime-broker: the Docker control plane for previews, stack leases, and disposable servicesegress: the restricted outbound proxy for Butler and Codexpreview-egress: the separate outbound path for preview runtimesplaywright: the browser automation sidecardesktop-proof: optional headed desktop proof sidecar for Electron/native app smoke checks
Pushes to main and version tags publish these images to GHCR:
ghcr.io/peter-olom/manor-butlerghcr.io/peter-olom/manor-codex-boxghcr.io/peter-olom/manor-egressghcr.io/peter-olom/manor-preview-egressghcr.io/peter-olom/manor-runtime-brokerghcr.io/peter-olom/manor-playwrightghcr.io/peter-olom/manor-desktop-proof
Published tags include latest for the default branch, release tags, branch tags, and commit SHA tags.
The default Compose file uses published images. Local source builds use the source-build overlay:
./manor.sh start --buildThe working model is:
- one operator
- one Butler supervisor
- one warm Codex worker
- one Docker host
- many jobs
The default job shape is:
- one job maps to one Codex thread
- one repo task should use one dedicated worktree
- one job may own one isolated stack lease
- previews and disposable services attach to that stack when needed
Manor keeps repository work and runtime work separate on purpose.
- do repository, git, and edit work in the warm Codex worker
- do package installs, app startup, builds, and browser checks in previews
- use shared previews when runtime changes should persist in the mounted worktree
- use snapshot previews for disposable smoke runs that should not mutate the source worktree
- use the optional desktop proof sidecar only when native headed app verification is needed
- treat worker-side package installation as an exception, not the default path
Butler is the operator-facing control plane.
Today it provides:
- a web UI on
http://127.0.0.1:8180 - a unified Butler chat
- a jobs sidebar and per-job windows
- a dedicated Codex terminal surface
- runtime visibility for stacks, previews, and services
- image-reference tracking for visual tasks
- tool-driven delegation into Codex workstreams
Butler is built on the Pi agent framework and supervises Codex through the Codex app server.
The Codex box is the trusted worker.
Today it provides:
- the official Codex CLI
- Codex app-server mode
- a direct shell through
ttyd - repo and worktree access through a dedicated Docker volume mounted at
/repos - shared runtime state through dedicated Docker volumes
- local helper access through
manor-harness
Codex owns repository work. Butler and the broker own runtime lifecycle and policy.
Preview runtimes are disposable containers started by the runtime broker.
Current preview behavior:
- every preview gets a lease
- Butler exposes a stable private route for each lease
- raw host port publishing is not the default path
- previews are heartbeat-gated during startup
- preview egress defaults to normal outbound internet access
- previews are the default place for installs, builds, app startup, and runtime verification
none, named profiles, and custom domain policies remain available when a preview needs stricter outbound control
Stacks are the unit of multi-container runtime isolation.
Each stack gives a job:
- one private Docker network
- grouped lifecycle for previews and disposable services
- stack-level cleanup
- optional retained volumes for stateful work
This is the path Manor uses for Docker-heavy projects that need multiple cooperating app and infra containers.
Stateful stacks are the default answer for mutable service state.
manor-harness stack start --stateful creates a job-scoped retained storage namespace and applies an opinionated policy:
- a project base storage key is derived automatically
- a writable per-job storage key is derived automatically
- the job stack forks from the project base by default
- built-in stateful services copy data lazily on first use
manor-harness stack promote <stackId>publishes back to the project base by default
--storage-mode base is reserved for intentional seed or snapshot refresh work.
The intended rule is simple:
- never let concurrent jobs share one writable database volume
- fork for job work
- promote only after validation
Built-in dependency templates:
- Postgres
- Redis
- MySQL
- MSSQL
- RabbitMQ
- MinIO
- Mailpit
- SQLite
Container-backed templates run as disposable private-network services. SQLite is provisioned directly in the selected worktree as an embedded file.
If a dependency is missing, Butler or Codex can register a new template on first use and persist it for later jobs.
Electron and native desktop checks use a separate opt-in sidecar instead of the browser automation sidecar.
Start it only when needed:
./manor.sh desktop start --buildDaily desktop proof control:
./manor.sh desktop start
./manor.sh desktop stop
./manor.sh desktop statusThe sidecar runs a virtual display, window manager, x11vnc, noVNC, screenshot capture, simple desktop input tooling, and a persistent desktop home under the sidecar state volume. Browser proof remains on the lighter Playwright sidecar.
Workers interact with attached runtimes through manor-harness.
That surface currently supports:
- job context and runtime inventory
- stack start, inspect, promote, and stop
- preview start, inspect, logs, processes, exec, verify, and stop
- desktop status, list, start, current-screen, action, and stop
- service template listing and registration
- service start, inspect, logs, processes, exec, and stop
- supervisor reporting back to Butler
The important constraint is unchanged:
- workers use
manor-harness - Butler and the broker own runtime policy
Both Butler and Codex support:
- ChatGPT device-code login
- API key login
Useful commands:
docker compose exec butler butler-auth status
docker compose exec butler butler-auth device
docker compose exec butler butler-auth api-key
docker compose exec codex-box codex-auth status
docker compose exec codex-box codex-auth device
docker compose exec codex-box codex-auth api-key
docker compose exec codex-box gh auth status
docker compose exec -it codex-box gh-auth-headlessManor is a trusted personal worker appliance, not a multi-tenant sandbox.
Current trust boundaries:
- Butler and Codex are separated into different services
- Codex does not get direct internet access
- Butler and Codex go out through the restricted
egressproxy - preview runtimes keep private runtime networking and get direct outbound internet by default
- optional preview egress profiles remain available for stricter outbound control
- the runtime broker is the only service that talks to the Docker socket
- preview and service traffic stays on private Docker networks
- Butler routes previews instead of publishing arbitrary app ports on the host
This is an architecture-first containment model, not a claim of full internal sandboxing.
For vulnerability reporting and remote-use hardening, see the security policy.
- Codex worker model instructions are mounted from
config/codex-model-instructions.md compose.ymlpasses that markdown file into the Codex CLI throughCODEX_MODEL_INSTRUCTIONS_FILECODEX_PERSONALITYremains available for Codex's built-in preset personalities (none,friendly,pragmatic)- edit the markdown if you want to change default worker tone or reporting behavior without teaching Butler a new prompt rule
Current local development assumptions:
- the default stack is deployment-safe and persists core state in named Docker volumes
- the default stack pulls published images
- Butler source hot reload is opt-in through the development overlay
- local hot-reload with source images runs use
docker compose -f compose.yml -f compose.build.yml -f compose.dev.yml up -d --build - older host-side
state,artifacts, andreposdirectories are not mounted by default anymore - runtime broker operations affect live Docker resources on the host
For contribution workflow and validation expectations, see the contributing guide.
compose.yml: deployment-safe Manor stack with named Docker volumescompose.build.yml: optional local source-build overlaycompose.dev.yml: optional local Butler hot-reload overlaybutler/: Butler backend and web appconfig/: optional preview egress profiles and Codex model instructionsdocker/butler/: Butler image and auth helpersdocker/butler-gateway/: Butler reverse proxydocker/codex-box/: Codex worker image and harness CLIdocker/egress/: restricted outbound proxydocker/preview-egress/: optional restrictive preview egress control planedocker/runtime-broker/: preview, service, and stack runtime brokerdocker/playwright/: browser automation imagedocker/desktop-proof/: optional headed desktop proof image
The current stack has been verified recently for:
- Butler production build success
- live stack lease lifecycle
- live disposable service provisioning
- retained volume restart persistence
- retained volume fork and promote flow for Postgres
- cleanup back to zero active stacks and services after smoke runs
Manor is licensed under the MIT License.




