Skip to main content

Directory CLI

Command-line client for the IB1 Directory member API. Built to make the API easy to exercise as it grows, and to be drivable by scripts and code agents (machine-readable output, real exit codes, no prompts).

Authenticate either by logging in (browser, authorization-code + PKCE, token cached in the OS keyring) or by pasting a token (--token / DIRECTORY_TOKEN) for short runs and CI.

Install

pip install ib1-directory-cli

For local development from a clone:

pip install -e ".[dev]"   # or: uv sync --extra dev

This installs a directory command.

Configuration

Option Env var Default
--api-url DIRECTORY_API_URL https://directory.core.sandbox.trust.ib1.org
--token DIRECTORY_TOKEN (none)
--organization DIRECTORY_ORGANIZATION (none)
--json pretty-printed

The default API is the sandbox. Point --api-url or DIRECTORY_API_URL at another environment, or at http://localhost:8000 for a locally running API.

Login needs no configuration beyond the API URL. directory login asks the API for its Cognito hosted UI domain, client id and scopes (GET /.well-known/directory-cli). These optional variables override what the API publishes, e.g. against an API that doesn't publish it:

Env var Meaning
DIRECTORY_COGNITO_DOMAIN Hosted UI base URL, e.g. https://<prefix>.auth.<region>.amazoncognito.com
DIRECTORY_COGNITO_CLIENT_ID The public (no-secret) CLI app client id
DIRECTORY_OAUTH_SCOPES Space-separated scopes. Default: whatever the API publishes, else openid email
DIRECTORY_REDIRECT_PORT Default 8400 (must match the client's registered callback)

The API is only asked when DIRECTORY_COGNITO_DOMAIN and DIRECTORY_COGNITO_CLIENT_ID aren't both set.

Login

directory login     # opens a browser, caches the token in your OS keyring
directory logout    # clears the cached token for this API
directory token     # prints a current id token (refreshing if needed)

After directory login, me get / me update use the cached token automatically. Token precedence is --token then DIRECTORY_TOKEN then the keyring cache.

Tokens are cached per API URL, so you can be logged in to several environments at once and --api-url picks which token is used. The Cognito client that issued a token is cached with it, so refreshing the token doesn't call the API.

directory token is the bridge for agents/CI that can't open a browser: a human runs it and passes the value as DIRECTORY_TOKEN. The token is short-lived, so this suits short runs.

Usage

# Read your organisation
directory --token "$ACCESS_TOKEN" me get

# Same, token from the environment, compact JSON for piping
export DIRECTORY_TOKEN=...
directory --json me get | jq .identifier

# Partial update (only the flags you pass are sent — a merge-patch)
directory me update --street-address "1 New Road" --email ops@acme.example
directory me update --country GB --postal-code "AB1 2CD"

Editable fields: --email, --street-address, --locality, --region, --state, --postal-code, --country, --privacy-policy, --data-protection-url.

Organisations (owning more than one)

Most users own a single organisation and need nothing extra. Some own several — for example an energy data provider that also owns an example CAP organisation, which it acts as to generate test certificates. List the ones you own, then pass --organization <identifier> (or set DIRECTORY_ORGANIZATION) on any command to say which one you are acting as.

# List the organisations you own
directory me orgs

# Act as a specific organisation
directory --organization cap12345 me get
directory --organization cap12345 cert sign abc12345 client

# Or set it once for the session
export DIRECTORY_ORGANIZATION=cap12345
directory me get

If you own more than one organisation and don't pass a selector, the API returns an error asking you to pick one. There is no -o short flag for --organization because -o is the output-path flag on ca download and cert download.

Applications

# List your applications (optionally filter by scheme short name)
directory apps list
directory apps list --scheme perseus

# Read one application by identifier
directory apps get abc12345

# Create an application under a scheme (roles are repeatable role identifier URLs)
directory apps create --scheme perseus --title "My App" \
  --role https://registry.trust.ib1.org/scheme/perseus/role/data-provider \
  --home-page-url https://app.example.com

# Create with a data service (title, conforms-to and endpoint-url go together)
directory apps create --scheme perseus --title "My App" \
  --data-service-title "My Feed" \
  --data-service-conforms-to https://standard.example.com \
  --data-service-endpoint-url https://api.example.com

# Partial update (only the flags you pass are sent; --role replaces the whole set)
directory apps update abc12345 --title "Renamed" --support-url https://support.example.com

# Delete (destructive, so --yes is required; the API refuses with 409 if certificates exist)
directory apps delete abc12345 --yes

The publisher on a data service is set by the server to your organisation, so there is no flag for it. Application create/update accept --description, --home-page-url, --support-url, --message-delivery, --role, and the four --data-service-* flags.

Administration

Admin commands require your Cognito account to be in the directory admin group; other users get a 403.

# Onboard a new organisation (creates the org, its scheme membership + role, and the
# officer contacts). The scheme is fixed per environment; the role is a slug within it.
directory admin create-org \
  --legal-name "Acme Ltd" --email contact@acme.example \
  --street-address "1 Main St" --locality London --postal-code "AB1 2CD" \
  --company-number 12345678 --role energy-data-provider \
  --data-officer-name "Dana" --data-officer-email dana@acme.example \
  --licence-officer-name "Lee" --licence-officer-phone "+441234567890"

# Add a user to an organisation and send them a Cognito invite (they become an owner)
directory admin add-member <organization-identifier> --email new.owner@acme.example

Each officer needs an email or a phone. --region and --effective-date (ISO YYYY-MM-DD, default today) are optional. Onboarding = create-org, then add-member for each owner.

Certificates

# Sign a certificate for an application. With no --csr, a private key and CSR are
# generated locally; the key is written to disk (mode 0600) and the signed cert saved.
directory cert sign abc12345 client
# → my-app writes abc12345-client-key.pem and abc12345-client-cert.pem, prints the cert id

# Use your own CSR instead of generating one (no key is written):
directory cert sign abc12345 signing --csr my.csr --cert-out signing.pem

# Download a certificate by id (default filename comes from the server)
directory cert download <certificate-id> -o cert.pem

# Revoke a certificate (destructive, so --yes is required; this is a soft revoke)
directory cert revoke <certificate-id> --yes

cert sign takes the application identifier and the type (client or signing). The CA forces the certificate subject to your organisation regardless of the CSR, so a generated CSR's subject does not matter. Download the CA root/intermediate bundle with directory ca download <client|signing>.

Exit codes

Code Meaning
0 Success
1 API or transport error (4xx/5xx, connection failure)
2 Usage error (no token, update with no fields, delete without --yes, login against an API that publishes no login configuration)

Prerequisites for login (one-time, out of this repo)

Interactive login needs a public Cognito app client on the existing user pool:

  • no client secret
  • authorization-code grant with PKCE
  • callback URL http://localhost:8400/callback (the exact port must match DIRECTORY_REDIRECT_PORT)
  • scopes openid email

The API it logs in to must then be configured with:

  • COGNITO_ALLOWED_CLIENT_IDS including the client id, so the API accepts tokens it issues
  • COGNITO_DOMAIN and COGNITO_CLI_CLIENT_ID, so the API publishes them at /.well-known/directory-cli for the CLI to discover

These are deploy/infra steps (AWS and the deployments repo), not part of the CLI.

Tests

pip install -e ".[dev]"   # or: uv sync --extra dev
pytest                     # or: uv run pytest

Metadata

Release files for ib1-directory-cli 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ib1-directory-cli 0.5.0
File Size Uploaded Provenance Actions
ib1_directory_cli-0.5.0.tar.gz 55.9 kB With provenance Details for ib1_directory_cli-0.5.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for ib1-directory-cli 0.5.0
File Interpreter ABI Platform Actions
ib1_directory_cli-0.5.0-py3-none-any.whl Python 3 none any Details for ib1_directory_cli-0.5.0-py3-none-any.whl

Total release size: 73.8 kB

Release files / ib1_directory_cli-0.5.0.tar.gz

Download URL ib1_directory_cli-0.5.0.tar.gz
Size 55.9 kB
Tags Source
SHA-256 checksum
How to use checksums
130c735b2476cb03f7dda2239af163457f72a4c46a68e22949b5832df984f65a
BLAKE2b-256 checksum
How to use checksums
6a20d064da39b16d039e362ab1461377483a5b779c0e689b58d34b79e9e02738
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.

Transparency log

Release files / ib1_directory_cli-0.5.0-py3-none-any.whl

Download URL ib1_directory_cli-0.5.0-py3-none-any.whl
Size 17.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7c7dee4083da51dd4b1fecb98ab2c0b5237cfd28bc7a16b2809c73f734b65c50
BLAKE2b-256 checksum
How to use checksums
8134897911ee6ad9a98add7531b4017c8ce942ba4a06dbf7e987dc1b0d916892
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.

Transparency log

Security for ib1-directory-cli 0.5.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for ib1_directory_cli-0.5.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page