Skip to main content

exd manifest

Move a manifest between a local directory and an exd-server. Three subcommands: push, pull, versions.

Synopsis

exd manifest push <tenant>/<slug> <dir> [flags]
exd manifest pull <tenant>/<slug> [flags]
exd manifest versions <tenant>/<slug> [flags]

All three subcommands require server coordinates:

FlagDefaultNotes
--server <url>$EXD_SERVER_URLHTTPS URL of the exd-server.
--token <secret>$EXD_API_TOKENBearer token. Required scope is per-subcommand.
--http-backend curl|in-processenv-resolvedTransport selector.
--format human|jsonhumanSee conventions.

Tokens needed by subcommand:

SubcommandToken scope
pushnamespace-write or higher (tenant-admin, superadmin)
pullnamespace-read or higher
versionsnamespace-read or higher

push

Lint a local directory and upload it as a new version of a server-hosted flag namespace.

Synopsis

exd manifest push <tenant>/<slug> <dir>
[--if-version <N>]
[--server <url>] [--token <secret>]
[--format human|json]
[--http-backend curl|in-process]

Use cases

  • CI promotion. Run on main after a merge to promote the linted manifest to production:

    exd manifest push acme/marketing ./namespaces/marketing \
    --server https://flags.acme.com --token $EXD_API_TOKEN
  • Optimistic concurrency. Two engineers each pushed; the second push needs to know it's not overwriting blindly:

    exd manifest push acme/marketing ./namespaces/marketing --if-version 12

    If the server's current version is not 12, exit 1 with version conflict.

  • Manual hotfix. Operator pushes a one-off fix from their workstation. (Prefer the git push flow at scale.)

Flags

FlagRequiredNotes
<tenant>/<slug> (positional)yesTenant + namespace slugs joined by /.
<dir> (positional)yesLocal manifest directory. Must lint clean (errors → exit 1).
--if-version <N>noOptimistic concurrency. Push succeeds only if server's current version is exactly N. Mismatch → exit 1.

Behavior

  1. Runs the full lint pipeline against <dir>. Any E-code → exit 1.
  2. Packs the directory into a tarball and uploads via PUT /api/v1/tenants/<tenant>/namespaces/<slug>/manifest.
  3. The server runs the same lint pipeline on receipt; a server-side lint failure is 422 LintFailed → exit 1. (Should never happen if the local lint passed; protects against version-skew bugs.)
  4. Version conflict (409) → exit 1 with the current server version printed.
  5. Success → exit 0 with the new version number.

Example

$ exd manifest push acme/marketing ./namespaces/marketing --if-version 12
Pushed namespace 'acme/marketing': version 12 → 13

Exit codes

CodeCondition
0Push succeeded.
1Local lint errors; server lint errors (422); version conflict (409); authorization failure (401/403).
2Bad CLI args; unreachable server.

pull

Download a server-hosted flag namespace to disk.

Synopsis

exd manifest pull <tenant>/<slug>
[--version <N>]
[--output <dir>]
[--server <url>] [--token <secret>]
[--format human|json]
[--http-backend curl|in-process]

Use cases

  • Bootstrap a local working copy from the server-of-record:

    exd manifest pull acme/marketing --output ./namespaces/marketing
  • Audit a historical version. Pull a prior version of the manifest by version number:

    exd manifest pull acme/marketing --version 11 --output /tmp/marketing-v11
  • Diff two versions. Pull both into tempdirs and run diff -r:

    exd manifest pull acme/marketing --version 11 --output /tmp/v11
    exd manifest pull acme/marketing --version 12 --output /tmp/v12
    diff -ruN /tmp/v11 /tmp/v12

Flags

FlagRequiredNotes
<tenant>/<slug> (positional)yesTenant + namespace slugs.
--version <N>noPull a specific historical version. Defaults to current.
--output <dir>noDestination directory. Must NOT exist (or must be empty). Defaults to the namespace slug under cwd.

Behavior

  1. Issues GET /api/v1/tenants/<tenant>/namespaces/<slug>/manifest (with ?version=<N> when supplied).
  2. Server returns a tarball; the client verifies the closure hash and extracts to --output.
  3. Unknown version → exit 1.

Example

$ exd manifest pull acme/marketing --output ./marketing
Pulled namespace 'acme/marketing' version 13 to ./marketing (3 flags, 5 segments)

Exit codes

CodeCondition
0Pull succeeded.
1Unknown namespace; unknown version; authorization failure.
2Output directory exists and is non-empty; bad CLI args.

versions

List the version history of a server-hosted flag namespace.

Synopsis

exd manifest versions <tenant>/<slug>
[--limit <N>]
[--after <cursor>]
[--server <url>] [--token <secret>]
[--format human|json]
[--http-backend curl|in-process]

Use cases

  • Audit who pushed what, when. Quick "what's been happening in this flag namespace?" check:

    exd manifest versions acme/marketing --limit 20
  • Programmatic version walk. Paginate through history in a script via --after:

    exd manifest versions acme/marketing --limit 50 --format json
  • Pre-rollback inspection. Find the version to roll back to before pulling it.

Flags

FlagRequiredNotes
<tenant>/<slug> (positional)yesTenant + namespace slugs.
--limit <N>noCap the page size. Default 50, max 200.
--after <cursor>noCursor for the next page (from the previous response's next_cursor).

Behavior

Calls GET /api/v1/tenants/<tenant>/namespaces/<slug>/versions?limit=&after=. Cursor pagination per server-api spec § Pagination.

Example

$ exd manifest versions acme/marketing --limit 5
version pushed_at commit pushed_by
13 2026-05-11T18:22:11Z a4b9c2… tok_01J5PAY... (github-actions-marketing-prod)
12 2026-05-10T09:45:33Z 9d8e7f… tok_01J5PAY...
11 2026-05-09T12:11:00Z 3c2b1a… tok_01J5PAY...
10 2026-05-08T16:30:42Z 6e5d4c… tok_01J5PBZ...
9 2026-05-07T11:22:18Z f0e1d2… tok_01J5PBZ...

(next: --after eyJ2IjoxMC4uLn0=)

JSON output carries next_cursor and per-row structured fields.

Exit codes

CodeCondition
0Listed successfully.
1Unknown namespace; authorization failure.
2Bad CLI args; invalid cursor.

See also