xbp 10.40.0

XBP is a zero-config build pack that can also interact with proxies, kafka, sockets, synthetic monitors.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
# XBP
[![crates.io](https://img.shields.io/crates/v/xbp.svg)](https://crates.io/crates/xbp)
[![docs](https://docs.rs/xbp/badge.svg)](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