Compass is Jenkins for autonomous DevOps

Jenkins won CI not because it was the most elegant server, but because it was yours: self-hosted, open source, and extensible by anyone who could write a plugin. Autonomous DevOps needs the same thing. That is what Compass is built to be.

Ilia Dubovskii · October 2026 · 8 min read

Why Jenkins won

Before Jenkins, continuous integration was a practice teams described and rarely ran. Jenkins made it a thing you could install on a spare machine on a Friday afternoon. It ran inside your network, with your credentials, against your repositories. It did almost nothing on its own; plugins did everything. When it needed to do something new, someone wrote a plugin, and then everyone had it.

Twenty years later the shape still holds up: a small core that schedules and records work, a plugin ecosystem that does the work, a UI that lists both, and an update centre that keeps them current. It is the shape an autonomous DevOps platform needs too, because autonomous agents raise exactly the questions Jenkins answered for builds: where does this run, who controls it, and how do I add the thing my team needs?

The same architecture, a different kind of job

Compass maps an AWS account to the Terraform and repositories that own it, then acts on the map: it imports unmanaged resources into Terraform, plants decoy credentials that trip when used, and keeps the pull requests it opens alive. Underneath, it is organised the way Jenkins is.

Jenkins and Compass side by side Both have a web UI, a core with a queue and an executor, a set of plugins or captains, and an update channel. Jenkins produces builds and artifacts; Compass produces pull requests. Jenkins Compass UI queue extensions updates output Jenkins web UI · Manage Jenkins Dashboard · Settings → Captains build queue → executors jobs table → daemon (every 2 s) plugins (.hpi) captains (compass.captains) Update Center catalog.json · releases feed · updater builds · artifacts pull requests
The same layers. The difference is the last row: Jenkins turns code into artifacts; Compass turns the state of a running account into code changes.
JenkinsCompass
Where it runsYour server, your networkYour machine or network: Docker Compose with a dashboard, an API, a daemon and DynamoDB
LicenceMITApache-2.0
Unit of extensionPluginCaptain: a Python package found by an entry point
Unit of workBuild, with a console logJob, with an event timeline
SchedulingBuild queue, executors, triggersJobs table, one daemon, captain services
Install an extensionManage Plugins → Available → restartSettings → Captains → Available → restart
Configuration UIGenerated from the plugin's descriptorGenerated from the captain's JSON Schema
Commercial editionCloudBees CI, on JenkinsBeamreach Compass, on the same open code through the host seams

Captains are plugins, and they are easy to write

In Jenkins even the features that feel built in, Git and Pipeline among them, are plugins. Compass takes the same view: the map, the decoys, code-as-cloud and the PR watcher are all captains, and they use exactly the interface a third-party captain does. Turn one off per workspace and its tab disappears, its background services stop, and its work is refused. Nothing is deleted.

A captain is a manifest and a commands module. This is the whole manifest of the example captain:

MANIFEST = CaptainManifest(
    name="hello",
    label="Hello",
    summary="Says hello. The example captain: copy it to start your own.",
    tier="open",
    feature="hello",
    commands="captains.hello.commands",
    routers=("captains.hello.routes:router",),
    route_prefixes=("/api/hello",),
    tabs=(TabSpec(key="hello", label="Hello", group="platform", feature="hello"),),
    config_schema={
        "type": "object",
        "properties": {
            "greeting": {"type": "string", "default": "hello", "x-help": "What to say."},
            "api_key": {"type": "string", "x-secret": True},
        },
    },
    requires_core=">=0.2,<1",
    version=__version__,
)

And the line in pyproject.toml that makes Compass find it:

[project.entry-points."compass.captains"]
hello = "captains.hello.manifest:MANIFEST"

From that, Compass gives the captain what a Jenkins plugin gets from Jenkins and a bit more:

The captain development guide goes from cp -R examples/captain-hello to a published captain in nine short sections.

An update centre, with a review

Jenkins' Update Center is a JSON file of plugins that every Jenkins polls. Compass has the same thing: compass_core/catalog.json. Merge an entry there and every Compass lists the captain under Available within ten minutes. An administrator installs it with one click and a restart, or by naming it in .env:

COMPASS_EXTENSIONS=compass-captain-weather==0.1.0

Because a captain runs with the install's AWS and GitHub access, the catalog is stricter than most plugin indexes. The pip line must be pinned (an exact version, a tag or commit, or a wheel with its sha256; a branch is rejected). A reviewer checks that the source is public and matches the tag, that the summary says what the captain does, and that it asks for no more access than it uses. A captain declares the core versions it supports with requires_core; a Compass outside that range lists it as incompatible and loads none of it.

From a captain repository to every Compass Tag a release, open a pull request to the catalog, a reviewer merges it, every Compass lists it within ten minutes, an administrator installs and restarts. your repotag v0.1.0 catalog PRpinned pip line reviewsource · access Availablewithin 10 min installedclick · restart Off per workspace at any time: the tab goes, services stop, writes under its routes are refused, data stays.
Publishing a captain. The review step exists because a captain runs with the install's cloud and GitHub access.

Updates you can leave on

Anyone who ran Jenkins for long remembers the banner: a new version is available. Compass has the banner too. It reads a release feed at most every six hours and shows what changed next to the Update button, with the notes an operator needs after applying it, taken from the changelog.

Applying it is where Compass is more careful than most self-hosted tools. The Compass containers cannot update themselves: they have no Docker socket. An opt-in updater service has one, and it is off by default, because whoever holds the socket holds the machine. When it is on, an update is one click, and the updater:

  1. refuses to start while a job is running, unless the request says force (Jenkins' "restart when no jobs are running");
  2. pulls the release's images and rejects any whose digest is not the one the release lists;
  3. backs up .env, sets the new version and recreates the services;
  4. waits up to five minutes for the API and the dashboard to answer, and rolls back to the previous version when they do not.

On the next start, Compass runs its data migrations and rebuilds installed captains against the new core. Without the updater it is still two commands: change COMPASS_VERSION in .env, then docker compose pull && docker compose up -d.

Open source with seams, like Jenkins and CloudBees

Jenkins is open source; CloudBees sells an enterprise product built on it. Compass is the open edition of Beamreach Compass, and the hosted product runs this same code. What makes that honest rather than a fork is that the extension points are in the open code and documented in the architecture guide:

SeamOpen defaultHook
Job queuethe jobs table, polled by the daemonset_job_queue
Workspace configa JSON fileset_workspace_config_loader
ModelAnthropic, or noneset_model_factory
Dashboard tabsthe open tabsapp/lib/extensions.ts

A host, registered under the compass.hosts entry point, uses these seams to change how a whole install behaves: where workspaces come from, which queue runs jobs, which model answers. It is how a larger deployment, ours or yours, runs on Compass without patching it. If you want Compass on SQS, or on your company's model gateway, you write a host, not a fork.

Where the analogy stops

Jenkins does what a pipeline tells it, when a trigger fires. Compass decides what to do from the map, which means it needs something Jenkins never did: limits on its own judgement. Every change it proposes is a pull request through your normal review and CI. A deterministic risk score and a gate decide what runs unattended. When a model revises a pull request it works inside a checkout with four tools and can only write the files the change already touches, and a guard that never calls a model checks the diff before anything is pushed. How those layers fit together is in Continuous Maintenance: the stage after CI/CD.

The rest is the part Jenkins got right: run it yourself, read the code, add what you need, and share it.

Related: Continuous Maintenance, obstacles for autonomous software, Compass pricing.