Skip to main content

planeops: a control plane for a personal AI setup

CI Coverage OpenSSF Scorecard PyPI Python versions License: Apache-2.0

Install · Quickstart · Features · Docs · Spec

planeops is an inventory and drift detector for the AI tooling on your machine: coding assistants, MCP servers, local models, background services, API keys. You declare what should exist and why in plain YAML; planeops tells you when reality disagrees, and changes nothing without showing the diff and asking first.

$ plane status --short
drift:2

$ plane drift
✗ 2 alert(s) on mymac 16:20

alerts (2)
  ✗ launchd/ai.gateway  ungoverned always-on service; declare it or add an unmanaged glob
  ✗ ollama/qwen3:8b     expected present, not observed

  full report ~/planeops/observed/mymac/DRIFT.md

A machine with six things running that nobody wrote down, caught by one read-only scan.

Why

Your machine accretes AI tooling: coding harnesses, MCP servers wired into three different clients, local models, background services, API keys in dotfiles. Nobody writes down what is installed, how it is wired, or why it is there. Six months later, something is listening on a port and you cannot say what put it there.

An ungoverned pile of tools on the left; the same tools declared and connected on the right

planeops turns the pile into a registry: every asset declared with its reason for existing, every scan diffed against that intent, every fix a rendered change you confirm one at a time.

Features

  • Catches what package managers can't: ungoverned always-on services, an MCP server wired into one client (or one project) but not the others, a pruned model your tooling depends on.
  • One loop, three verbs: observe scans read-only, drift diffs desired against observed, apply converges with per-change confirmation.
  • Lifecycles drive the triage: parked is deliberately dormant, so nothing nags while a project sleeps; a finished retirement asks for registry cleanup instead of alerting forever.
  • No daemon, no open ports: every command exits; the ambient loop is your OS scheduler running plane reconcile.
  • Onboarding is pruning, not authoring: plane init --seed proposes the registry from what is already installed.
  • Typos are load errors: tolerence: fails with "did you mean 'tolerance'?", never a silent no-op.
  • Secrets stay references: names and presence are tracked; a value is only ever written to the one file its entry declares.
  • Exit codes are a contract: 0 clean, 1 operator error, 2 drift, so your prompt and your cron both know the state.
  • Provider-neutral core: adapters, schedulers, and stores are discovery seams; a fitness test bans vendor names from the engine.

Install

$ uv tool install planeops        # or: pipx install planeops / pip install planeops

Installs the plane command. Python 3.12+, macOS and Linux.

Want your AI assistant to query the plane over MCP? Install the extra: uv tool install "planeops[mcp]" (adds plane-mcp).

From source (development)
$ git clone https://github.com/albertorsesc/planeops
$ cd planeops
$ uv sync            # engine + plane CLI
$ make check         # the full gate: lint, format, types, tests

Quickstart

# scaffold an instance and seed the registry from what's already installed
$ plane init --seed
create the instance at /Users/you/planeops? (path or Enter to accept)
instance ready at /Users/you/planeops
  wrote 73 entries to /Users/you/planeops/registry/imported.yaml; prune, then `plane drift`

# scan the machine, diff it against the registry
$ plane observe
✓ observed 73 facts on mymac /Users/you/planeops/observed/mymac/snapshot.json
  brew 21 · mcp 14 · ollama 9 · npm 8 · launchd 6 · ...
$ plane drift
✓ no drift on mymac 16:04

# keep it fresh: an OS timer, previewed and confirmed
$ plane schedule --every 6h

# one glance forever after (empty means clean; wire it into your prompt)
$ plane status --short
drift:3

From there, plane apply walks the drift one confirmed change at a time.

plane init created an instance: a directory that is yours, not the tool's. Git it like a dotfiles repo:

~/planeops/
├── registry/           desired state: the YAML you declare, edit, and prune
├── instance.yaml       this machine's adapter settings
├── secrets.sops.yaml   encrypted values, if you use the secrets store
└── observed/<host>/    generated per machine: snapshot.json, DRIFT.md

registry/ and instance.yaml are your setup's documentation; observed/ is regenerated by every scan. Layout, multi-machine use, and the tool's exact footprint: docs/instance.md.

Going further

  • SPEC.md: the architecture, entry schema, adapter contracts, and exit codes.
  • docs/instance.md: your instance directory, several machines on one registry, the tool's footprint.
  • docs/secrets.md: the secrets flow (declare, secrets add/list/remove with the store bootstrapped on first use, apply materializes) and how values stay sealed.
  • docs/mcp.md: every MCP server across every client in one view, the opt-in unwire of retired servers, and the read-only server your assistant can query.
  • CHANGELOG.md: releases and what is coming.

What planeops is not

  • Not a runtime. It never sits in any request path and starts no long-running process.
  • Not an installer. Adapters shell out to the tools you already trust (brew, systemctl, ollama); planeops decides whether, they do how.
  • Not a fleet manager. One human, their machines, their intent. Multi-host is on the roadmap as bundles of the same registry, not an agent mesh.

Status

Pre-1.0: the loop, eleven adapters, scheduling, secrets, importers, and the MCP server work on macOS and Linux and govern this project's own machines daily. Contracts may still move; a breaking change bumps the minor and lands in the CHANGELOG with its migration.

Built on

planeops delegates instead of reinventing: sops and age hold the secrets, chezmoi reproduces config files, your OS's own scheduler runs the ambient loop, and the package managers you already use keep doing the installing. The engine rides on ruamel.yaml for the registry, Rich with rich-argparse for the console, and the MCP Python SDK for the optional server, and is built with uv, ruff, mypy, and pytest. Thanks to all of them.

Contributing, security, license

CONTRIBUTING.md has the dev setup, the quality gate, and how to write an adapter. Security posture and reporting: SECURITY.md. Licensed Apache-2.0.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

planeops-0.8.0.tar.gz (248.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

planeops-0.8.0-py3-none-any.whl (128.7 kB view details)

Uploaded Python 3

File details

Details for the file planeops-0.8.0.tar.gz.

File metadata

  • Download URL: planeops-0.8.0.tar.gz
  • Upload date:
  • Size: 248.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for planeops-0.8.0.tar.gz
Algorithm Hash digest
SHA256 b79e9d4ebc4507c15cd332d9ce19ab698e0ac4371f08aadd37491f6bce2fc372
MD5 f3f035e8668d5bbc4757e970db0873cf
BLAKE2b-256 b2512ed13b26c684ce8adc7eabf683480f2c0c5accdcd2b0ea68fbc86c3650a5

See more details on using hashes here.

Provenance

The following attestation bundles were made for planeops-0.8.0.tar.gz:

Publisher: release.yml on albertorsesc/planeops

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file planeops-0.8.0-py3-none-any.whl.

File metadata

  • Download URL: planeops-0.8.0-py3-none-any.whl
  • Upload date:
  • Size: 128.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for planeops-0.8.0-py3-none-any.whl
Algorithm Hash digest
SHA256 fc22c58f4369400dc2e487bb02d3a66d02e4f908f78c932560b252f0d75a5ab3
MD5 91852b41b862bf7a1bbc3d8d13620e14
BLAKE2b-256 646294a48d1029275ff74d00d16d7c55445e39dd42b264110e3f223d2d08d8a3

See more details on using hashes here.

Provenance

The following attestation bundles were made for planeops-0.8.0-py3-none-any.whl:

Publisher: release.yml on albertorsesc/planeops

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page