bx

September 5, 2026 · View on GitHub

bx is on PATH in every xbin terminal. It talks to xbind with the session's credentials (XBIN_URL + XBIN_TOKEN — in a terminal, a token scoped to that terminal's tile; on the host, the owner token) and does local scaffolding. Anything bx does, you can also do with curl (protocol.md) or plain file edits — bx is convenience, not magic.

bx ls                                  list components (runtime, exposed roles, manifest errors)
bx status [<component>] [--all]         backend states (building/healthy/failed, generations);
                                       --all = workspace-wide, else this terminal's tile
bx new <path> [--runtime R] [--expose] [--title "Pretty Name"] [--owner user:U|org:O]
                                       scaffold a component (org-owned needs
                                       the org's Create knob, D25)
bx tile ls | import <name> [as <path>] list/install builtin tiles
bx template ls | new <source> [as <path>] | updates
                                       list/instantiate template components (blueprints)
bx builtin updates | update <id> [--replace|--merge|--pr]
                                       offer/apply newer embedded scaffold + tiles;
                                       also lists/installs MISSING essential tiles
                                       (upgraded workspaces predating them, D41)
bx user ls | add <id> [flags] | set <id> [flags] | invite <id> | signout <id> | rm <id>
                                       manage users (admin/xbin:users); add with
                                       an empty password (or --invite) prints a
                                       single-use invite link (D22); --email
                                       binds an SSO identity (docs/auth.md §SSO);
                                       add --sso --email a@b pre-provisions an
                                       SSO-only account (no password, no link;
                                       D52); add --org o[:level[:create[:admin]]]
                                       (repeatable) joins orgs at creation;
                                       signout ends every session + terminal
                                       token ("sign out everywhere", D53); set
                                       --disable/--enable pauses/restores the
                                       whole account (D34). ls shows last sign-in,
                                       a * on admins/memberships that come from
                                       IdP-group rules
bx defaults [set …]                    provisioning defaults (admin): what every
                                       NEW account starts with — --tiles p=level,
                                       --create p, --org o[:level[:create]]
                                       (repeatable), --term-api/--term-net —
                                       plus --default-tiles (the D27 baseline)
                                       and --tile-creation any|org-only (D52)
bx org ls|add|set|rm <id> [flags]      organizations (docs/auth.md, D24-D28)
bx org member <org> [<user> --level L [--create] [--admin]
                     [--suspend|--unsuspend] [--detach] | rm <user>]
                                       one membership per call (org admins too);
                                       --detach turns an IdP-synced membership
                                       manual (suspend: D34; sync: D53)
bx org sso-groups <org> [--add g[:level[:create[:admin]]]]… [--rm g]… [--set '<json>']
                                       IdP-group → membership rules (ws-admin):
                                       Google group email, GitHub org/team-slug,
                                       or the OIDC claim value; applied at each
                                       member's next SSO sign-in (D53)
bx org set <id> [--sets +s|-s] [--net +n|-n] [--allow +t|-t]   delegation + network sets (ws-admin)
bx netset ls | set <name> [--rules a,b|--add r|--rm r] | rm <name>
                                       organisation network sets (D54): named
                                       reach rules — internet, internet:<host|
                                       host-glob|ip|cidr>[:port], lan:<cidr>,
                                       host, provider:<tile-glob> — attached to
                                       orgs with `bx org set --net +<name>`; for
                                       an org's own tiles the union is the
                                       ceiling on net bindings, what its admins
                                       may bind without asking, the default
                                       binding `org`, and the egress of terminals
                                       opened on them (docs/auth.md §Network sets)
bx org policy [<org>] [--set '<json>'] policy-ceiling rows (workspace / org)
bx owner <tile> [--transfer user:U|org:O|workspace]   tile ownership (D24)
bx permset ls|set|rm <name> [--allow a,b] [--term-net]  permission sets (D28)
bx access <tile> [set|rm user:…|org:…=level | request [level] | approve <user> [level]]
                                       per-tile access entries — exact entries
                                       are authoritative (D31); user level
                                       `none` = explicit exclude; request files
                                       a human access request, approve grants
                                       it (D36; pending requests show in the
                                       plain listing)
bx logs [-f] <component>               backend logs (tail -f style with -f)
bx code prs [<component>|--from] [--all|--state=S]
                                       change proposals ("code PRs"): a tile's
                                       inbox (defaults to this terminal's tile),
                                       or --from = your outgoing ones
bx code pr <target> --title <t> [-m <msg>] [--base <rev>] <patch.mbox>…
                                       propose changes to a tile you can read
bx code pr show|fetch|comment|close <n> [<component>] [flags]
                                       review · fetch the series · discuss ·
                                       close (--merged|--rejected|--withdrawn)
bx api <component>                     roles + API.md — how to integrate with it
bx grants                              grant table + pending requests
bx grant <caller> <target>:<role>      approve/add a grant
bx grant --revoke <caller> <target>:<role>
bx iface                               interface requests, providers, bindings
bx bind <comp> <slot>=<p> | <slot>+=<p[#i]> | <slot>-=<p[#i]>
                                       wire interface slots (# = provider instance)
bx expose <tile> <slot>=<source> [--host H|--zone '*.Z'|--listen :P]
                                       publish an exposed endpoint (docs/ingress.md)
bx unexpose <tile> <slot>              unpublish it
bx ingress [routes]                    published endpoints + live routes/listeners
bx vault status|unseal|seal|rekey      encryption-at-rest barrier
bx vault ls|set|rm <component> [key] [value]
                                       write-only management — values are
                                       readable only by the tile's backend
                                       (D30; `get` lists/403s for humans)
bx cron ls                             scheduled jobs
bx enable | disable <component>        lifecycle: pause/resume a tile (plans/lifecycle.md)
bx hide | unhide <component>           hidden = disabled + out of sidebars (D42)
bx offload <component> [--full]        archive + free local bytes (--full incl. source)
bx backup <component>                  snapshot to the bound @archive provider
bx backups <component>                 list archived versions
bx restore <component> [--version V] [--file PATH]
                                       restore a whole version, or one file
bx backup-schedule [<component> --every 24h|--cron "…" [--keep N]|--rm]
                                       owner-scheduled backups
bx doctor                              workspace health checks

Notes per command

bx new — runtimes: go (module + backend/main.go + SDK wiring via the generated go.work), node, python, cgi (executable shell script), static (default). --expose adds a roles block to the manifest and the standard API.md skeleton. Never overwrites existing files. After scaffolding, frame it somewhere: <bx-frame src="apps/thing"></bx-frame>.

bx grant — the role goes after the last colon, so resource targets read naturally: bx grant apps/email res:apps/calendar/bus:reader. Grants are rows in the workspace xbin.json; revoking is deleting the row.

bx bind — wires a component's interface slots (plans/interfaces.md). Net slots take the builtin refs internet, host, lan:<cidr> — or the FILTERED form internet:<host|ip|cidr>[:port][,…] (D35), restricting egress to the named destinations (hostnames enforced by the relay's DNS pinning) — plus org and none (D54): on an org-owned tile whose org has network sets the slot defaults to org (the live union of the sets; bx iface shows it as satisfied) and any explicit ref must be inside the sets — the server refuses others naming the set; none pins a tile offline. A binding that a later set edit or transfer leaves outside the sets goes inert (bx iface / bx status say why). slot=provider replaces; on a multi:true http slot slot+=ref adds and slot-=ref removes, where a ref is provider[#instance] — instances are the runtime-registered sub-slots of a provider (bx iface lists them).

bx code pr — the cross-tile suggestion channel (plans/code-prs.md). You can read sibling tiles but write only your own, so changes to another tile travel as a PR: clone its repo out of the read-only mount, commit, git format-patch, file the series. Opening needs no approval — the capability to suggest is exactly the capability to read, and xbind never applies a patch; the target's terminal/agent reviews the diff and runs git am --3way itself. Typical flows:

# suggest (from your tile's terminal):
git clone "$XBIN_WORKSPACE/apps/b" /tmp/b && cd /tmp/b
# …edit, commit…
git format-patch --base=auto origin/main..HEAD
bx code pr apps/b --title "fix overflow" -m "why + how tested" 000*.patch

# receive (in apps/b's terminal):
bx code prs                                  # inbox (open PRs)
bx code pr show 3                            # message, thread, base rev
bx code pr fetch 3 | git apply --stat --check # review the shape FIRST
bx code pr fetch 3 | git am --3way           # apply with authorship kept
bx code pr close 3 --merged -m "applied as $(git rev-parse --short HEAD)"
bx code pr close 3 --rejected -m "why"       # or push back

--merged/--rejected are the target side's call, --withdrawn the author's; comments go both ways and both agents should read them.

bx vault set — with no value argument, reads the secret from stdin (so it stays out of shell history): pass show imap | bx vault set apps/email imap-pass.

bx vault unseal — prompts for the passphrase without echo (or reads it piped). First run creates the encryption barrier and encrypts existing plaintext; later runs unlock it after a restart. This is how you bring an env-less production instance online: boot leaves the vault locked, then an admin unseals once after login (the admin tile's vault tab does the same in the UI). bx vault rekey changes the passphrase (re-wraps the data key — nothing re-encrypted). bx vault status reports the mode (unsealed / sealed / plaintext / unconfigured); the boot modes are in docs/auth.md §vault.

bx doctor — checks: xbind reachable; manifest parse errors; dangling deps; expose without API.md; roles without descriptions; ownership/org sanity (orphaned owner entries, admin-less or member-less orgs, allowance entries that can never match, dead defaultTiles/share patterns); network sets (unknown attachments, rules that can't parse, orgs granted HOST networking, inert net bindings); go.work ownership; host inotify budget; toolchains present for the runtimes in use. Run it first when something "doesn't reload".

bx logs — reads .xbin/log/<compkey>.log directly; each backend generation is delimited by a --- gen N start … line.

Environment

VarDefaultMeaning
XBIN_URLhttp://127.0.0.1:8642xbind address
XBIN_TOKEN(set in terminals)bearer token — tile-scoped in terminals; the owner token on the host (.xbin/token)
XBIN_WORKSPACEwalk up from cwd to a dir with xbin.json + .xbinworkspace root

On the host (a root/operator shell — not a xbin terminal) nothing is injected, so bx reads the workspace owner token from .xbin/token — which requires being able to read that 0600 file, i.e. run as root or the xbin user:

sudo -u xbin bx ls

It locates the workspace via XBIN_WORKSPACE, else by walking up from the current directory, else the default /opt/xbin/workspace. A non-privileged user can't read the token, so bx there stays unauthenticated (by design). To point at a non-default listener, also set XBIN_URL.