# XBP
[](https://crates.io/crates/xbp)
[](https://docs.rs/xbp)
XBP (XYLEX Build Pack) is a deployment and operations CLI for single-service and multi-service projects.
It combines build/run workflows, PM2 process management, diagnostics, nginx helpers, secrets workflows, and project version synchronization in one tool.
## Features
- `monitoring`
- `docker`
- `kubernetes` [exp]
- `kafka` [exp]
- `pm2` [wip]
current version: `10.40.0`
## Repository Layout
- `crates/api`: standalone control-plane API runtime (`xbp_api`)
- `crates/athena`: Athena-backed control-plane repository layer (`xbp_athena`)
- `crates/cli`: CLI crate (`xbp_cli`) and binary entrypoint (`xbp`)
- `crates/core`: shared control-plane domain types (`xbp_core`)
- `crates/monitor`: internal monitoring crate (`xbp_monitor`)
- `crates/logs`: internal log streaming crate (`xbp_logs`)
- `apps/web`: XBP dashboard and frontend Worker
- `apps/docs`: Fumadocs documentation deployed at [docs.xbp.app](https://docs.xbp.app)
There is **no root `package.json`**. pnpm apps live under `apps/*` and are wired by the root `pnpm-workspace.yaml`. Run scripts with `pnpm --dir apps/<app> …`, not `pnpm run …` from the repository root.
## Documentation Site
Source content for the public docs site is primarily under `docs/` (MDX) and is built by the Fumadocs app in `apps/docs`.
```bash
# Install deps for the docs app (from repo root)
pnpm --dir apps/docs install
# Regenerate CLI reference JSON + MDX/sidebar (script name is generate:docs)
pnpm --dir apps/docs run generate:docs
# CLI reference exports only (after clap flag/help changes)
pnpm --dir apps/docs run generate:cli-reference
# Local preview
pnpm --dir apps/docs dev
```
Do **not** use `pnpm run docs:generate` (or any other script) at the repo root — that fails with `ERR_PNPM_NO_IMPORTER_MANIFEST_FOUND` because there is no root Node package.
## TL;DR (30-Second Start)
```bash
# 1) Install
cargo install xbp
# Debian/Ubuntu (after adding XBP apt source)
sudo apt install xbp
# 2) Check project/runtime state
xbp ports
xbp services
# 3) Run and inspect
xbp service build api
xbp service start api
xbp logs api
xbp ssh --host prod.example.com --username deploy
# 4) Discover services and keep versions aligned
xbp login
xbp version discover
xbp version
xbp version patch
```
## Why XBP
- One CLI for local service workflows and server-side operations.
- Supports Rust, Node.js, Next.js, Python, Express, and mixed repos.
- Handles PM2 lifecycle, logs, snapshots, and environment inspection.
- Includes version reconciliation across common manifest files and git tags.
- Adds operational helpers for ports, nginx, diagnostics, and secrets.
## Feature Overview
- Project and service orchestration: `services`, `service`, `redeploy`, `setup`.
- Process/runtime control: `list`, `start`, `stop`, `flush`, `snapshot`, `resurrect`, `env`, `logs`, `tail`.
- Remote operator access: `ssh` for interactive SSH sessions and `cloudflared tcp` for standalone Access forwarders.
- Network and infra helpers: `ports`, `nginx`, `diag`, `curl`.
- Configuration and security: `config`, `secrets`.
- Version workflows: `version` report, bump, explicit set, git-tag view, and `version discover` service registration.
- Optional monitoring command family (feature-gated build).
- Optional Kubernetes helper (feature-gated): `xbp kubernetes ...` for manifest generation, apply, readiness checks, and cert-manager issuer bootstrap. Build with `--features kubernetes`.
- Optional Docker helper (feature-gated): `xbp -l` / `xbp list` shows `docker ps` snapshot when built with `--features docker`.
- Optional systemd helper (feature-gated): `xbp -l` / `xbp list` also shows configured `systemctl status` output when built with `--features systemd`.
- Optional Athena control-plane persistence (feature-gated, **opt-in**): project/log/nginx/docker/schedule snapshots via `xbp-athena`. Build or install with `--features athena` (not enabled by default). Same flag on `xbp-api`, `xbp-daemon`, and `xbp-monitoring` (monitor runs without DB when off).
## Installation
### Option 1: Build From Source
```bash
git clone https://github.com/xylex-group/xbp.git
cd xbp
cargo build --release
./target/release/xbp --help
```
### Option 2: Install From Cargo
```bash
cargo install xbp
```
### Option 3: Install From APT (Debian/Ubuntu)
```bash
# Recommended (signed repository)
sudo mkdir -p --mode=0755 /usr/share/keyrings
curl -fsSL https://pkg.xbp.app/xbp-archive-keyring.gpg \
| sudo tee /usr/share/keyrings/xbp-archive-keyring.gpg >/dev/null
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/xbp-archive-keyring.gpg] https://pkg.xbp.app stable main" \
| sudo tee /etc/apt/sources.list.d/xbp.list > /dev/null
sudo apt-get update
sudo apt-get install -y xbp
```
```bash
# Fallback when repository signing is not configured yet
echo "deb [trusted=yes arch=amd64] https://pkg.xbp.app stable main" \
| sudo tee /etc/apt/sources.list.d/xbp.list > /dev/null
sudo apt-get update
sudo apt-get install -y xbp
```
### Windows note (Kafka feature)
- Standard install works on Windows:
```bash
cargo install xbp
```
- Kafka-enabled builds are currently Linux/WSL2-oriented because `rdkafka-sys` may require Unix tooling.
- On Windows, do not enable `kafka` during Cargo install/build.
- If you hit an `rdkafka-sys` error mentioning `cp -a` / `program not found`, rebuild without `kafka`:
```bash
cargo install xbp --no-default-features
```
or use WSL2/Linux for Kafka-enabled builds.
### Linux note (low `/tmp` quota)
If `cargo install xbp` fails with a `Disk quota exceeded` error under `/tmp`, direct Cargo's temp and target output into your home directory instead:
```bash
mkdir -p "$HOME/.cargo-tmp" "$HOME/.cargo-target"
TMPDIR="$HOME/.cargo-tmp" CARGO_TARGET_DIR="$HOME/.cargo-target" cargo install xbp
```
### Verify Installation
```bash
xbp --version
xbp --help
```
## Quick Start
```bash
# Discover project/runtime state
xbp ports
xbp services
# Build or run a service from xbp config
xbp service build api
xbp service start api
# Deploy flow shortcut
xbp redeploy api
# PM2 snapshots for recovery
xbp snapshot
xbp resurrect
# Interactive remote SSH shell
xbp ssh --host prod.example.com --username deploy
# Standalone Access forwarder
xbp cloudflared tcp --hostname bastion.example.com --listener 127.0.0.1:2222
# Persist a Hetzner dedicated-server vSwitch VLAN config
xbp network hetzner vswitch setup --ip 10.0.3.2 --vlan-id 4000 --interface enp0s31f6 --apply
# Version report across manifests and tags
xbp version
```
## Configuration
XBP resolves project config in this order:
1. `.xbp/xbp.yaml`
2. `.xbp/xbp.yml`
3. `.xbp/xbp.json`
4. `xbp.yaml`
5. `xbp.yml`
6. `xbp.json`
Both YAML and JSON are supported. If no explicit project version is set, default is `0.1.0`.
Use `xbp generate config` to generate or refresh `.xbp/xbp.yaml` (writes a `yaml-language-server` `$schema` header for editor IntelliSense; schema lives at `schemas/xbp.project.schema.json`), and
`xbp generate config --from-json .xbp/xbp.json` to convert legacy JSON configs.
With the opt-in `openapi-gen` feature, `xbp generate openapi --all` statically
generates validated per-service and aggregate OpenAPI 3.0/3.1 contracts. See
[`docs/openapi-generation.mdx`](docs/openapi-generation.mdx).
### Minimal YAML
```yaml
project_name: my-app
version: 0.1.0
port: 3000
build_dir: /path/to/project
```
### Multi-Service Example
```yaml
project_name: my-stack
version: 0.1.0
port: 3000
build_dir: /srv/my-stack
services:
- name: api
target: rust
branch: main
port: 3000
root_directory: apps/api
url: https://api.example.com
commands:
install: cargo fetch
build: cargo build --release
test: cargo test
lint: cargo clippy --all-targets
start: ./target/release/api
- name: web
target: nextjs
branch: main
port: 3001
root_directory: apps/web
commands:
install: pnpm install
build: pnpm run build
start: pnpm run start
```
### Core Fields
- `project_name`: logical project name.
- `version`: semantic version string for project-level versioning.
- `port`: primary project port.
- `build_dir`: absolute path to project root.
- `services`: optional service list.
- `environment`: optional environment variables.
Service `commands` accept arbitrary names, so commands such as `test`, `lint`,
`check`, and `publish` can be run with `xbp service <command> <service>`.
For npm projects, detected `package.json` scripts are included automatically.
Publishing can be scoped to a configured service. XBP resolves the service's
`version_targets` or its root manifest and infers npm versus crates.io from the
service target:
```bash
xbp publish --service web
xbp publish --service api --include-prereqs
```
### Service Fields
- `name`: service identifier.
- `target`: `rust`, `nextjs`, `nodejs`, `python`, or `expressjs`.
- `branch`: deploy branch.
- `port`: service port.
- `root_directory`: optional service-specific working directory.
- `url`: optional public URL.
- `healthcheck_path`: optional health route.
- `commands`: optional `pre`, `install`, `build`, `start`, `dev` commands.
## Command Cookbook
### Project and Service Commands
- `xbp services`: list services from config.
- `xbp service build <name>`: run service build command.
- `xbp service install <name>`: run service install command.
- `xbp service start <name>`: run service start command.
- `xbp service dev <name>`: run service dev command.
- `xbp redeploy <name>`: redeploy one service.
### Runtime and Operations
- `xbp list`: PM2 process list.
- `xbp logs [project]`: view logs for a configured service, Docker container, or PM2 process.
- `xbp logs --ssh-host <host> --ssh-username <user> --ssh-password <pw>`: remote logs.
- `xbp ports`: active listening ports.
- `xbp ports --kill --port 3000`: kill process(es) on a port.
- `xbp ports --nginx`: include nginx mapping view.
- `xbp ports --full`: include reconciled XBP project port data.
- `xbp diag`: run environment diagnostics.
- `xbp ports --exposure`: diagnose service bind + firewall exposure per port.
- `xbp nginx setup --domain <domain> --port <port> --email <email>`: provision HTTPS reverse proxy with Certbot.
- `xbp nginx list`: list discovered nginx sites.
- `xbp nginx show <domain>`: show nginx config.
- `xbp nginx update --domain <domain> --port <port>`: update upstream port.
- `xbp network floating-ip add --ip <IP>`: write persistent floating IP config on detected backend.
- `xbp network floating-ip add --ip <IP> --apply`: write and apply/reload network config.
- `xbp network floating-ip list`: list floating IPs from runtime + config.
- `xbp network config list`: list discovered network config files and backend detection.
- `xbp curl <url-or-domain>`: quick endpoint health/content check.
- `xbp fix-process-monitor-json <path>` / `xbp fix-pm-json <path>`: repair malformed Cursor process-monitor JSON exports (`--check`, `--stdout`).
- `xbp kubernetes addons list`: show full MicroK8s addon status (enabled/disabled).
- `xbp kubernetes addons enable <name>`: enable a MicroK8s addon.
- `xbp kubernetes addons disable <name>`: disable a MicroK8s addon.
- `xbp kubernetes dashboard-token`: extract the dashboard JWT token from `describe secret`.
- `xbp kubernetes observability-creds`: print decoded Grafana admin credentials from observability secret.
- `xbp kubernetes issuer --email <email>`: create/update a cert-manager Let's Encrypt issuer (feature-gated build).
### PM2 Shortcuts
- `xbp snapshot`: save PM2 process snapshot.
- `xbp resurrect`: restore PM2 state.
- `xbp stop <target>`: stop one process or all.
- `xbp flush [target]`: flush logs globally or for a process.
- `xbp monitor check`: one-shot monitor check.
- `xbp monitor start`: monitor daemon.
- `xbp env <pm2-name-or-id>`: show PM2 env.
### Config, Setup, and Secrets
- `xbp setup`: guided local setup helpers.
- `xbp generate config`: generate `.xbp/xbp.yaml` from project detection.
- `xbp generate config --update`: refresh missing defaults in `.xbp/xbp.yaml`.
- `xbp generate config --from-json <PATH>`: convert legacy `xbp.json` to `.xbp/xbp.yaml`.
- `xbp generate openapi --all`: generate configured service and aggregate OpenAPI contracts (requires `openapi-gen`).
- `xbp config`: show/open global XBP config paths.
- `xbp config --project`: show current project config.
- `xbp config openrouter set-key [KEY]`: store OpenRouter API key globally.
- `xbp config openrouter show [--raw]`: inspect stored OpenRouter key.
- `xbp config openrouter delete-key`: remove stored OpenRouter key.
- `xbp config github set-key [TOKEN]`: store GitHub OAuth2 token globally.
- `xbp config github show [--raw]`: inspect stored GitHub token.
- `xbp config github delete-key`: remove stored GitHub token.
- `xbp config linear set-key [TOKEN]`: store Linear API key globally for issue management, release-note linking, and initiative publishing.
- `xbp config linear show [--raw]`: inspect stored Linear API key.
- `xbp config linear delete-key`: remove stored Linear API key.
- `xbp config linear select-initiative`: pick a repo-scoped Linear initiative and save its ID to `.xbp/xbp.yaml`.
- `xbp linear`: interactive Linear issues hub (list/create/edit/status/priority/labels/assign/comments).
- `xbp linear list|show|create|edit|status|priority|labels|assign|comment|comments`: scriptable Linear issue operations.
- `xbp github` / `xbp gh`: interactive GitHub issues hub for the current git origin repo.
- `xbp github list|show|create|edit|status|labels|assign|comment|comments`: scriptable GitHub issue operations.
- `xbp issues setup`: interactive wizard to write `issues:` (+ optional Linear team) into `.xbp/xbp.yaml`.
- `xbp issues scan [--path] [--json] [--no-prompt]`: scan for `// TODO`, `# FIXME`, etc.; offers sync when unlinked markers exist.
- `xbp issues sync [--to linear|github|both] [--dry-run] [--yes] [--annotate]`: file code markers as issues (ledger `.xbp/issues/ledger.json`); optional source stamps like `// XLX-99 (#42)`.
- `xbp issues status`: per-marker Linear/GitHub linkage table + stale ledger count.
- `xbp issues prune [--dry-run]`: drop ledger entries for markers removed from code.
- `xbp todos ...`: deprecated compatibility alias for the same marker-to-issue workflow.
Example project automation (`.xbp/xbp.yaml`):
```yaml
linear:
default_team_key: XLX
issues:
default_to: both
auto_yes: true
prompt_sync_after_scan: true
annotate_source: false
linear_labels: [xbp-todo]
github_labels: [xbp-todo]
linear_assignee: me
linear_project: My Project # optional: name, id, or slug
watch_paths: # optional: only scan these prefixes
- crates/cli
- crates/core
linear_link_wait_secs: 20 # after GH creates, wait for Linear auto-link
purge_duplicate_linear: true # archive xbp-created Linear dups of auto-links
priority_by_kind:
FIXME: 1
HACK: 2
TODO: 3
```
`xbp issues sync --to both` creates **all GitHub issues first**, waits for Linear's GitHub integration to comment/attach (when enabled), then creates Linear issues only for still-unlinked markers and purges duplicates. Issue bodies stamp the **xbp CLI version** that filed them.
Existing `.xbp/xbp.yaml` files using `todos:` and existing `.xbp/todo-issues.json` ledgers remain readable. New setup/config writes use `issues:` and new ledger writes use `.xbp/issues/*`.
The global XBP config also carries an `openrouter:` block for AI generation defaults:
```yaml
openrouter:
commit_model: openai/gpt-4o-mini
commit_system_prompt: "..."
release_notes_model: openai/gpt-4o-mini
release_notes_system_prompt: "..."
```
New config files seed those keys with the built-in full system prompts so you can tune commit generation and release-note generation per machine without changing repo config.
- `xbp login`: approve a dashboard-backed CLI session in the browser.
- `xbp login status`: inspect the current CLI auth state, token source, and expiry.
- `xbp login logout`: revoke the current CLI session and clear local auth state.
- `xbp version discover`: discover marker-based service roots, upsert them into `.xbp/xbp.yaml`, and register the project plus services on `xbp.app` when logged in.
- `xbp version discover --dry-run`: preview discovery and registration without writing local config.
- `xbp version discover --no-register`: discover only; skip local yaml writes and dashboard sync.
- `xbp secrets list`: list required/local env keys.
- `xbp secrets push --file .env.local`: push app env vars into the default `xbp-dev` GitHub Actions environment.
- `xbp secrets push`: push the selected app env file to `xbp-dev` and, when `.dev.vars` exists, push it separately to `xbp-cf-dev`.
- `xbp secrets --environment xbp-preview pull --output .env.local`: pull app env vars from an opt-in environment target. When `.dev.vars` exists, the same command also pulls from `xbp-cf-preview` into `.dev.vars`.
- `xbp secrets --environment xbp-prod pull --include-dev-vars`: pull app env vars into `.env.local` and force-create/update `.dev.vars` from `xbp-cf-prod`.
- `xbp secrets verify`: validate required env key availability.
- `xbp secrets diag`: check GitHub repo access, standard environment setup, and token scope.
## Nginx HTTPS Setup
`xbp nginx setup` now covers the full native Certbot + Nginx wiring flow for both regular and wildcard domains.
```bash
# Standard domain (HTTP-01)
xbp nginx setup --domain api.example.com --port 3000 --email ops@example.com
# Wildcard domain with manual DNS-01 prompts
xbp nginx setup \
--domain '*.example.com' \
--port 3000 \
--email ops@example.com \
--dns-mode manual \
--include-base true
# Wildcard domain with DNS plugin automation
xbp nginx setup \
--domain '*.example.com' \
--port 3000 \
--email ops@example.com \
--dns-mode plugin \
--dns-plugin cloudflare \
--dns-creds /root/.secrets/certbot/cloudflare.ini
```
Setup behavior:
- Ensures `nginx` and `certbot` are installed.
- Ensures `/etc/letsencrypt/options-ssl-nginx.conf` and `/etc/letsencrypt/ssl-dhparams.pem` exist.
- Writes a temporary HTTP ACME config for regular domains, then final HTTPS config with redirect.
- Uses DNS-01 for wildcard domains (`manual` or `plugin` mode).
- Reuses existing certificates when present.
- Validates config with `nginx -t` and restarts nginx on success.
## Floating IP Persistence
XBP can persist Floating IP configuration for Linux hosts by auto-detecting the active backend in this order:
1. Netplan
2. NetworkManager keyfiles
3. ifupdown
4. RHEL ifcfg scripts
```bash
# Hetzner-style IPv4 floating IP persistence (write-only)
xbp network floating-ip add --ip 203.0.113.10
# IPv6 floating IP with explicit CIDR and apply
xbp network floating-ip add --ip 2a01:4f9:0:2a1::2 --cidr 64 --interface eth0 --apply
# Inspect persisted + runtime addresses
xbp network floating-ip list
xbp network config list
```
### Versioning
- `xbp commit`: analyze the current git worktree, generate a Conventional Commit message, stage the current worktree, and create the git commit.
- `xbp commit --dry-run`: preview the generated message and worktree summary without staging or committing.
- `xbp commit --no-ai`: skip OpenRouter and use deterministic local heuristics only.
- `xbp commit --scope <scope>`: force the conventional commit scope.
By default `xbp commit` also pushes the new commit after it is created. Set `github.auto_push_on_commit: false` in `.xbp/xbp.yaml` to keep the commit local.
- `xbp version`: full version report (manifests + tags + registry when configured).
- `xbp version --git`: show normalized git tag versions.
- `xbp version major`: bump major in tracked files.
- `xbp version minor`: bump minor in tracked files.
- `xbp version patch`: bump patch in tracked files.
- `xbp version <x.y.z>`: set tracked files to an explicit semver.
- `xbp version <package>=<x.y.z>`: update package assignment versions in tracked TOML files.
- `xbp version discover` (aliases: `register`, `register-services`) scans for `Cargo.toml`, `package.json`, `pyproject.toml`, `requirements.txt`, Docker manifests, and related markers, then idempotently upserts matching services into the root `.xbp/xbp.yaml`. After a successful local write, an authenticated `xbp login` session syncs the project snapshot to `POST https://xbp.app/api/cli/projects/register`.
- All other `xbp version` workflows now require a verified `xbp login` session before they run.
- When run from `crates/<crate>/...`, `xbp version` scopes manifest bumps to that crate and the matching workspace `Cargo.lock` entry instead of the whole repository.
- `xbp version release`: create/push `v<version>` git tag and publish GitHub release.
- `xbp version release --version <x.y.z>`: release an explicit version.
- `xbp version release --notes-file <PATH>`: use custom Markdown release notes.
When `openapi.yaml`, `openapi.yml`, `openapi.json`, or sibling variants such as `openapi-wss.yaml` exist at the repository root or the active service/crate root, XBP **stages** versioned copies under `.xbp/releases/<scope>/<version>/openapi/` (e.g. `openapi-3.15.2.yaml`, `openapi-wss-3.15.2.yaml`) and uploads those as GitHub release assets — same flow as Athena’s prepare-openapi script. The primary HTTP OpenAPI `info.version` must match the release version. This does **not** require `openapi.generate_on_release` (that flag only regenerates specs earlier in the pipeline).
When `linear.release.initiative_ids` is configured, XBP also posts the release into those Linear initiatives.
If no local CLI Linear key is configured, release automation falls back to the dashboard-held Linear key for the authenticated CLI user.
When run from `crates/<crate>/...`, release tags default to `<crate-package-name>-<version>` and release notes are generated from commits that touched that crate path.
- `xbp version domain init --name <name> --root <path> --write`: scaffold an explicit release-domain policy in `.xbp/xbp.yaml`.
- `xbp version domain doctor --domain <name>`: validate that configured domain surfaces still report the policy version.
- `xbp version domain sync --domain <name> --check|--write`: check or write configured domain surfaces from the domain policy.
- `xbp version domain diagnose --domain <name> --log <path>`: classify Cargo path dependency drift from build logs.
- `xbp version domain release --domain <name> --patch|--minor|--major|--version <x.y.z> --deploy`: run a guarded domain release and optional Cloudflare release.
Auto-generated release notes now default the release title to `<version>[-<flag>]-<service>` (service-scoped releases use the XBP service name from `.xbp/xbp.yaml`), render grouped sections with a short summary paragraph, list markdown-linked commit SHAs, add separate GitHub PR bullets and Linear issue bullets when those references are present, then append a single copyable **Install** block: when cargo-dist is configured, the real dist shell/PowerShell installers and download table; otherwise one registry command per published package (`cargo install` / `cargo add`, or `npm`/`pnpm`/`yarn` chosen from the lockfile — never dual alternatives). When an OpenRouter key is configured, XBP uses `openrouter.release_notes_model` and `openrouter.release_notes_system_prompt` from the global config to collapse repetitive commits into user-facing grouped bullets; otherwise it falls back to deterministic topic grouping.
### cargo-dist release assets
When `dist-workspace.toml` is present or `publish.dist.enabled` is true in `.xbp/xbp.yaml`, `xbp version release`:
1. Ensures dist config (and optionally generates GitHub Actions CI via `dist generate`)
2. Merges cargo-dist install/download markdown into the release notes
3. After the GitHub release exists, runs `dist build` for configured artifact modes (default `host` + `global`)
4. Uploads every file under `target/distrib` as a GitHub release asset
Upload progress is stored in the release ledger (`.xbp/releases/...`) per asset name so a failed mid-upload resume skips already-uploaded files. Multi-platform archives beyond the host machine are produced by the generated cargo-dist GitHub workflow on tag push (`[dist.github] create = false` so CI attaches to the release XBP already created).
```yaml
publish:
dist:
enabled: true
packages: [xbp]
installers: [shell, powershell]
artifacts_modes: [host, global]
generate_ci: true
allow_dirty: true
crates:
enabled: true
package_name: xbp
manifest_path: crates/cli/Cargo.toml
```
Other Cargo workspaces / services can enable the same block; packages opt in via `[package.metadata.dist] dist = true` (this repo ships `xbp` only by default).
`xbp commit` uses the same OpenRouter configuration path when available. It analyzes the current worktree with file-level stats, symbol extraction, and diff context, then asks the configured model for a strict Conventional Commits JSON payload. `xbp commit --model ...` overrides the per-machine `openrouter.commit_model`; otherwise XBP uses `openrouter.commit_model` and `openrouter.commit_system_prompt` from the global config. If no OpenRouter key is configured or the model response is unusable, XBP falls back to local conventional-commit heuristics.
Project config can disable the automatic push step:
```yaml
github:
auto_push_on_commit: false
```
If a repo has nested manifests that should always follow the project-level `.xbp/xbp.yaml` version even when they are not publish targets, declare them explicitly:
```yaml
version_targets:
- crates/cli/Cargo.toml
- apps/web/package.json
```
`xbp version`, `xbp version release`, and the release sync step treat these as additional version-coupled files owned by the project root.
Skip service discovery for paths that should not count as services (worktree-watch still records activity there):
```yaml
ignore_paths:
- packages/icons/
- e2e/
```
Use `watch_ignore_paths` only when worktree-watch itself should drop paths.
### Worktree-watch system tray
`xbp worktree-watch tray` opens a **native** tray icon for start/stop and live backlog stats (backgrounded by default; use `--foreground` to block the terminal):
| Platform | Backend |
|----------|---------|
| Windows | System tray NotifyIcon |
| Linux / GNOME | StatusNotifierItem (install an AppIndicator / tray extension on classic GNOME Shell) |
| macOS | Menu bar status item |
```bash
# Current git repo
xbp worktree-watch tray
# Parent folder of many repos
xbp worktree-watch tray --parent ~/Documents/GitHub
# Explicit set of repositories
xbp worktree-watch tray --repos ~/src/alpha ~/src/beta
```
Menu actions: **Start watching** (detached), **Stop watching**, **Refresh status**, **Show stats**, **Quit**. Tooltip and status text auto-refresh while the tray is open. The same `--repo` / `--parent` / `--repos` targeting works with `start`, `stop`, and `status`.
Disable versioning/releasing for one service or a series:
```yaml
services:
- name: docs
target: nextjs
branch: main
port: 3001
root_directory: apps/docs
versioning: false
release: false
versioning_disabled:
- packages/*
release_disabled:
- internal-tool
```
Interactive `xbp init` (nested service) and `xbp version discover` (new services) prompt for these flags when run in a TTY.
For monorepos where different services intentionally live on different release lines, declare explicit version domains:
```yaml
version_domains:
- name: auth
root: services/auth
version: 1.2.3
owned_package_prefixes:
- auth-
version_surfaces:
- kind: cargo_toml_package
path: services/auth/Cargo.toml
- kind: cargo_lock_packages
path: services/auth/Cargo.lock
- kind: wrangler_var
path: services/auth/wrangler.jsonc
key: APP_VERSION
allowed_bumps:
- patch
- minor
cloudflare_app: auth
```
Domain commands refuse cross-domain version alignment by default and treat a fully self-consistent but policy-wrong version as unsafe. `xbp cloudflare release --domain <name>` validates the domain before mutating Wrangler deploy vars.
Linear initiative publishing can be configured either per repo in `.xbp/xbp.yaml` or globally in XBP's `config.yaml`:
```yaml
linear:
release:
initiative_ids:
- "3f1f0f6f-7e1f-4a6f-9f28-8f8a52d0e9d0"
health: on_track
```
Set `enabled: false` in a repo config to opt that repo out of globally configured initiative publishing. Supported health values are `on_track`, `at_risk`, and `off_track`.
To pick a repo initiative interactively from your accessible Linear initiatives and write it into `.xbp/xbp.yaml`, run:
```bash
xbp config linear select-initiative
```
The dashboard at `apps/web` stores authenticated CLI project registrations in D1 (`xbp_project`, `xbp_project_service`), shows active CLI sessions and expiry metadata, exposes a dashboard-scoped Linear integration, and records version or release activity pushed by authenticated CLI workflows.
## Version Management Details
`xbp version` resolves versions from configured files, local/remote git tags, and configured package registries.
It normalizes prefixed tags (`v1.2.3`) and plain semver (`1.2.3`) into one comparison space.
### Package Assignment Updates In TOML
`xbp version <package>=<x.y.z>` updates both forms in tracked TOML files:
- `<package> = "x.y.z"`
- `<package> = { version = "x.y.z", ... }`
Example:
```bash
xbp version tokio=1.45.1
```
### Default Tracked Version Files
- `README.md`
- `openapi.yaml`
- `openapi.yml`
- `openapi.json`
- `Cargo.toml`
- `Cargo.lock`
- `package.json`
- `package-lock.json`
- `pyproject.toml`
- `xbp.yaml`
- `xbp.json`
- `.xbp/xbp.yaml`
- `.xbp/xbp.json`
The registry is synchronized into global XBP config as `versioning-files.yaml`.
Missing defaults are re-added without removing custom entries.
## PM2 Behavior
XBP uses PM2 as an execution/runtime layer for many commands.
- Deploy and start flows can (re)start services under PM2.
- `snapshot` stores recoverable process state.
- `resurrect` first tries native PM2 restore, then falls back to latest XBP snapshot.
- `env` maps PM2 names to IDs and prints effective runtime environment.
## Ports and Diagnostics
- `xbp ports` reconciles active listeners with detected project and nginx metadata.
- `xbp diag` validates common system dependencies and service expectations.
## MCP Server
XBP ships a built-in MCP server for AI agents (Cursor, Claude Desktop, etc.).
| Port | Service |
|------|---------|
| `1113` | MCP HTTP/SSE (`PORT_XBP_MCP`) |
| `1111` | Log tail WebSocket (`xbp_logs`) |
| `8080` | Host-ops API (`PORT_XBP_API`) |
### Quick start
```bash
# Foreground (dev)
xbp mcp serve
# Background + print Cursor config (Windows/macOS/Linux)
xbp mcp serve --detach
# Print Cursor MCP JSON
xbp mcp config
# MCP Inspector: prefilled connect URL + tool-call presets
xbp mcp inspector
xbp mcp inspector --launch
# Linux systemd (always-on)
xbp mcp install --port 1113
```
Add to Cursor MCP settings:
```json
{
"mcpServers": {
"xbp": {
"url": "http://127.0.0.1:1113/sse"
}
}
}
```
### MCP tools (full CLI surface)
The MCP server advertises **every leaf `xbp` command** as a tool (250+), generated from clap:
```bash
xbp mcp export-tools -o crates/mcp/generated/catalog.json
```
- Tool names: `xbp_<path_with_underscores>` (e.g. `linear list` → `xbp_linear_list`)
- Flags become tool properties (`--assignee me` → `"assignee": "me"`)
- Escape hatch: `xbp_raw` with `"args": ["linear", "list", "--assignee", "me"]`
- Handcrafted overrides keep special defaults for `xbp_workers_logs`, `xbp_workers_logs_build`, `xbp_todos_scan`, `xbp_todos_sync`
Regenerate the catalog after adding CLI commands, then rebuild `xbp-mcp`:
```bash
bash scripts/regen_mcp_catalog.sh # Linux/macOS/WSL
# or
pwsh scripts/regen_mcp_catalog.ps1 # Windows
# CI enforces freshness via scripts/check_mcp_catalog.sh
```
Example agent prompts:
- *"Use xbp_workers_logs_build with failed=true for worker CI errors."*
- *"Use xbp_todos_scan then xbp_todos_sync with dry_run true and to both."*
- *"Use xbp_linear_list with assignee me."*
- *"Use xbp_raw with args [\"version\", \"bump\", \"--dry-run\"]."*
### Cloudflare Worker + Container workflow
`xbp cloudflare` is the project-level workflow for Cloudflare Workers that own Cloudflare Containers. It reuses the existing Worker resolver and Wrangler execution helpers, but adds a canonical container contract under `.xbp/xbp.yaml`.
```bash
xbp cloudflare init --app auth --worker-root apps/auth-worker --container-port 8787 --health-path /health --write
xbp cloudflare doctor --app auth
xbp cloudflare deploy --app auth --rollout immediate --dry-run
xbp cloudflare deploy --app auth --rollout gradual
xbp cloudflare release --app auth --version 1.2.3 --rollout immediate
xbp cloudflare containers instances --app auth
xbp cloudflare jobs enqueue deploy --app auth --rollout immediate
xbp cloudflare jobs run --app auth --once
```
Container-backed Workers can add:
```yaml
workers:
- name: auth
root: apps/auth-worker
script_name: auth-worker
container:
class_name: AuthContainer
binding: AUTH_CONTAINER
dockerfile: Dockerfile
port: 8787
application_id: app_123
healthcheck_path: /health
required_secrets:
- AUTH_SECRET
version_var: AUTH_VERSION
instance_name_template: auth-${VERSION}
default_rollout: immediate
```
Local queued runs are stored as JSON records under `.xbp/jobs/cloudflare/`. V1 does not add database tables; hosted persistence can reuse the same payload shape later.
### Legacy stdio server
`scripts/xbp_mcp_server.py` remains available for stdio-only clients:
```bash
python3 scripts/xbp_mcp_server.py
# or
xbp mcp serve --stdio
```
### Server tests
```bash
python3 -m unittest scripts/test_xbp_mcp_server.py
cargo build -p xbp_mcp
```
## Repository Layout
- `src/main.rs`: binary entrypoint.
- `src/lib.rs`: library exports.
- `src/cli/`: clap command definitions and dispatch.
- `src/commands/`: command implementations.
- `src/strategies/`: deployment strategy and project detection.
- `src/sdk/`: PM2 and nginx integrations.
- `src/utils/`: shared helpers.
- `scripts/`: support scripts including MCP server.
- `docs/`: end-user docs, operator runbooks, and phased control-plane plans.
- `architecture/`: ADRs plus Mermaid/PlantUML design diagrams.
## Development
```bash
cargo fmt
cargo test
python3 -m unittest scripts/test_xbp_mcp_server.py
```
## Troubleshooting
- If `xbp` is not found, ensure Cargo bin path is on `PATH`.
- If PM2 commands fail, verify PM2 is installed and reachable in your shell env.
- If nginx commands fail, run with elevated permissions where required.
- If `xbp version` cannot update package assignments, confirm the target file is TOML and listed in versioning registry.
- If MCP command calls fail, confirm `xbp` is installed on the same environment where `xbp_mcp_server.py` is running.
## License
MIT