Skip to main content

Agent-ergonomic CLI for the Integry backend

Project description

Integry CLI

Agent-ergonomic CLI over the Integry backend. Wraps the template-management endpoints:

  • GET /api/v1/templates/ - list templates (with search + type filter)
  • POST /api/v1/templates/ - create a template
  • PATCH /api/v5/templates/<id>/ - partial update a template
  • GET /api/v2/templates/<id>/ - retrieve a template (or its draft payload)
  • GET /api/v1/templates/<id>/versions/ - list versions
  • GET /api/v1/templates/<id>/versions/<n>/ - retrieve a specific version
  • POST /api/v1/templates/<id>/versions/ - publish the draft as a new version
  • POST /functions/<machine_name>/call/ - test a FUNCTION template draft

Designed following the AXI principles: TOON output by default, minimal default schemas, content truncation, structured errors, content-first default invocation, contextual disclosure of next-step commands.

Install

End users (Linux + macOS):

pipx install integry-app           # or: uv tool install integry-app
integry --help

Upgrade with pipx upgrade integry-app (or uv tool upgrade integry-app).

Develop

nix-shell                              # enter dev shell (latest stable Python + deps)
python -m integry_cli                  # run the CLI from inside the shell
nix-shell --run pytest                 # run tests
nix-shell --run 'python -m integry_cli --help'

If installed via pip install -e web/cli, an integry console script is exposed.

Publish

export UV_PUBLISH_TOKEN=<pypi-token>   # https://pypi.org/manage/account/token/
./scripts/publish.sh                   # bump version in pyproject.toml first

Configuration

Variable Purpose Default
INTEGRY_API_URL Backend base URL. Wins over stored config. https://api.integry.io
INTEGRY_HOME Config directory. ~/.integry
INTEGRY_ACCOUNT_ID Account id sent on every request as the X-Account-Id header. Wins over stored config. unset

Stored files (mode 0o600 on credentials):

  • $INTEGRY_HOME/config.json - {"api_url": "...", "account_id": <int>} (set by auth login --api-url and accounts use)
  • $INTEGRY_HOME/credentials.json - {"access", "refresh", "obtained_at"}

Output

  • Default format is TOON (token-efficient). Pass --format json for a machine-readable envelope.
  • Default schemas:
    • Template detail → id, name, type, machine_name, app_id, publishing_status, revision_number, live_or_latest_version, is_draft_empty
    • Template list rows → id, name, type, machine_name, publishing_status, revision_number, live_or_latest_version
    • Template versions → id, version, publishing_status, is_live, integration_count, changelog
  • Pass --full to skip field filtering and disable the 400-char string truncation.
  • Successful mutations always end with one or more next: lines suggesting plausible follow-ups.
  • Errors print to stdout as error: <code>: <message> with optional indented detail.

Exit codes

Code Meaning
0 Success
1 Backend API error (4xx/5xx other than 401)
2 Auth/credential problem (no credentials, or refresh failed)
3 Local usage error (bad flags, unreadable JSON file, mutually-exclusive flags)

Commands

integry (no args)

Prints ambient state and next-step hints - no help-text dump (AXI principle 8).

integry [--format toon|json]

Output (unauthenticated):

api_url: "https://api.integry.io"
authenticated: false
access_expires_in: null
account_id: null
next: integry auth login --username <you>
next: integry accounts list

Output (authenticated, no account selected):

api_url: "https://api.integry.io"
authenticated: true
access_expires_in: 3140
account_id: null
next: integry accounts list
next: integry accounts use <id>

Output (authenticated, account selected - templates hints kick in):

api_url: "https://api.integry.io"
authenticated: true
access_expires_in: 3140
account_id: 7
next: integry templates create --input ./template.json
next: integry templates update <id> --input ./patch.json

Exit code: 0 if authenticated, 2 if not.


integry auth login

Obtain an access + refresh token pair from POST /api/token/ and persist them.

integry auth login --username <name> [--password <secret>] [--api-url <url>] [--format toon|json]
Flag Effect
--username, -u (required) Account username.
--password, -p Password. Prompted (hidden) if omitted - the only interactive prompt anywhere in the CLI.
--api-url Override and persist api_url to $INTEGRY_HOME/config.json. INTEGRY_API_URL env var still wins.
--format toon (default) or json.

Output:

username: alice
api_url: "https://api.integry.io"
access_expires_in: 3599
refresh_expires_in: 86399
next: integry accounts list

Picking an account is the very next step after login - see integry accounts below.

Exits 2 on bad credentials (backend 401), 1 on other backend errors.


integry auth logout

Delete stored credentials. Idempotent.

integry auth logout [--format toon|json]

Output:

cleared: true        # or false if there was nothing to clear
api_url: "https://api.integry.io"

Always exits 0.


integry auth status

Show the currently stored credentials' state.

integry auth status [--format toon|json]

Output (authenticated):

api_url: "https://api.integry.io"
user_id: 42
access_expires_in: 3140
refresh_expires_in: 86340

If no credentials exist, prints error: usage_error: not authenticated - run: integry auth login and exits 3.


integry accounts

Selects which account is sent on every request as the X-Account-Id header. The backend reads this header in app/permissions.py to scope the request to a specific tenant.

The active account is resolved in this order:

  1. INTEGRY_ACCOUNT_ID env var
  2. account_id in $INTEGRY_HOME/config.json (set via accounts use)
  3. None - the header is omitted

The active id (and null if unset) is included in the output of bare integry and integry auth status.

integry accounts list

integry accounts list [--search TEXT] [--page N] [--page-size N] [--format toon|json] [--full]
Flag Effect
--search, -s TEXT Case-insensitive substring filter on account name. Applied client-side.
--page N 1-indexed page number. Sliced client-side after --search.
--page-size N Results per page. Sliced client-side.
--format toon (default) or json.
--full Skip field filtering.

Default schema per row: id, name, is_currently_selected.

integry accounts use

integry accounts use <account_id> [--format toon|json]
Flag Effect
<account_id> (positional, required) Account primary key to send as X-Account-Id.
--format toon (default) or json.

integry accounts clear

integry accounts clear [--format toon|json]
Flag Effect
--format toon (default) or json.

integry accounts current

integry accounts current [--format toon|json]
Flag Effect
--format toon (default) or json.

Exits 3 if no account is selected.


integry templates list

List templates owned by the active account via GET /api/v1/templates/.

integry templates list \
    [--search TEXT] [--type TYPE]... \
    [--page N] [--page-size N] \
    [--format toon|json] [--full]
Flag Effect
--search, -s TEXT ?search= - server-side substring match against name, machine_name, and branding_app__name.
--type, -t TYPE Repeatable, joined into ?types=A,B,C. Valid: STANDARD, QUERY, ACTION, TRIGGER, FUNCTION, INTEGRATION, AGENT, FUNCTION_TRIGGER.
--page N 1-indexed page number.
--page-size N Results per page (backend default 10).
--format toon (default) or json.
--full Disable field filtering.

Default schema per row: id, name, type, machine_name, publishing_status, revision_number, live_or_latest_version - machine_name is the identifier for FUNCTION templates and is null for most other types.

Output:

total: 27
templates:
  [10] id,name,type,machine_name,publishing_status,revision_number,live_or_latest_version:
    101,send_email,FUNCTION,send_email,PUB,r4,3
    99,Onboarding,STANDARD,,DR,r1,
    ...
next: integry templates get <id>

JSON envelope additionally carries query and types reflecting the active filters.

Empty states: no templates found (unfiltered), no templates match the filter (with --search/--type).


integry templates create

Create a template by POST /api/v1/templates/. Body is forwarded verbatim - backend serializers are authoritative.

integry templates create --input <file|-> [--publish] [--example] [--format toon|json] [--full]
Flag Effect
--input, -i Path to a JSON file, or - to read from stdin. Required unless --example.
--publish Adds ?publish=true so the template is created with status PUB.
--example Print a comprehensive example body to stdout and exit. No API call. --input is ignored.
--format toon (default) or json.
--full Disable field filtering and string truncation.

Body (forwarded verbatim):

{
  "meta": {
    "title":       "My template",
    "description": "...",
    "app_id":      7,
    "branding_app_id": 7,
    "is_wizard":   false,
    "partial_trigger_response": false
  },
  "trigger": { /* validated server-side */ },
  "actions": [ /* validated server-side */ ]
}

Output:

id: 99
name: "My template"
app_id: 7
publishing_status: DR
revision_number: r1
next: integry templates update 99 --input ./patch.json

integry templates update

Partial-update a template by PATCH /api/v5/templates/<id>/.

integry templates update <id> --input <file|-> \
    [--version N] [--publish] [--archive] [--meta-only] [--revision N] \
    [--example] [--format toon|json] [--full]
Flag Effect
<id> (positional, required) Template primary key.
--input, -i Path to a JSON file, or - for stdin. Body must be an object containing a meta object. Required unless --example.
--version ?version=N - patch a specific template version.
--publish ?publish=true.
--archive ?archive=true.
--meta-only ?exclude_template_from_response=true. Mutually exclusive with steps in the body - fails fast (exit 3).
--revision Convenience: sets meta.revision_number in the body before sending. Lets you keep a static patch file and bump the revision via flag.
--example Print a comprehensive example body to stdout and exit. No API call. --input is ignored.
--format toon (default) or json.
--full Disable field filtering and string truncation.

Body:

{
  "meta": {
    "revision_number": 7,
    "app_id":          1,
    "branding_app_id": 1,
    "product_info":    { /* optional */ },
    "events":          [ /* optional */ ]
  },
  "steps": [ /* optional; omit for meta-only updates */ ]
}

steps is not partial - when included, the backend replaces all steps with what you send. Omitted steps are deleted. Fetch the full steps first via get-draft or get --full, modify, and send back the complete array. To update only meta, omit steps and use --meta-only.

Output (full update):

id: 42
name: "My template"
app_id: 1
publishing_status: PUB
revision_number: 8
next: integry templates update 42 --input ./patch.json

Output (--meta-only):

success: true
next: integry templates update 42 --input ./patch.json

Common backend rejections (exit 1):

  • Revision number does not match - your local revision is stale; refetch.
  • Template already being updated - the template is locked.
  • Cannot update template while integration update job is in progress - drop the steps and use --meta-only, or wait for the job.

integry templates get

Retrieve a template or one of its versions.

integry templates get <id> [--version N] [--format toon|json] [--full]
Flag Effect
<id> (positional, required) Template primary key.
--version N Fetch version N via GET /api/v1/templates/<id>/versions/<n>/.
--format toon (default) or json.
--full Disable field filtering and string truncation.

Output (no --version):

id: 42
name: "My template"
app_id: 7
publishing_status: PUB
revision_number: 8
live_or_latest_version: 3
is_draft_empty: true
next: integry templates list-versions 42

Output (--version 3):

id: 901
version: 3
publishing_status: PUB
is_live: true
integration_count: 12
changelog: "Added retry logic"
next: integry templates get-draft 42 --version 3

integry templates list-versions

List published versions of a template via GET /api/v1/templates/<id>/versions/.

integry templates list-versions <id> [--page N] [--page-size N] [--format toon|json] [--full]
Flag Effect
<id> (positional, required) Base template primary key.
--page N 1-indexed page number.
--page-size N Results per page (backend default 10).
--format toon (default) or json.
--full Emit each version's full payload instead of the default 6-field schema.

Output:

total: 3
versions:
  [3] id,version,publishing_status,is_live,integration_count,changelog:
    901,3,PUB,true,12,"Added retry logic"
    877,2,PUB,false,4,"Bumped action timeout"
    803,1,PUB,false,0,"Initial release"
next: integry templates publish 42

Empty state (no versions yet):

no versions yet - publish a draft to create one
next: integry templates publish 42

--format json always emits a structured envelope, including for the empty case ({"total": 0, "versions": []}).


integry templates publish

Publish the current draft as a new version via POST /api/v1/templates/<id>/versions/.

integry templates publish <id> \
    [--changelog "text"] [--beta] [--upgrade-integrations] \
    [--format toon|json] [--full]
Flag Effect
<id> (positional, required) Draft template primary key.
--changelog TEXT Optional changelog string sent in the request body.
--beta Adds ?publish_for_beta_users=true.
--upgrade-integrations Adds ?upgrade_integrations=true.
--format toon (default) or json.
--full Disable field filtering and string truncation.

Output (the id is the new version-template id, not the base id):

id: 904
name: "My template"
app_id: 7
publishing_status: PUB
revision_number: 9
next: integry templates list-versions 42

integry templates get-draft

Fetch a template (or a specific published version) reshaped into a draft body suitable for templates create. Calls GET /api/v2/templates/<base_id>/?return_as_draft=true[&version=N].

integry templates get-draft <template_id> [--version N] [--format toon|json] [--full]
Flag Effect
<template_id> (positional, required) Base template primary key.
--version N Specific version number to export as draft. Without it, returns the current draft state.
--format toon (default) or json.
--full Required if you intend to feed the output into templates create. Without it, only a 4-field summary is printed.

Default output (summary):

title: "My template"
app_id: 7
publishing_status: DR
step_count: 6
next: integry templates create --input <draft.json>

Round-trip example:

integry templates get-draft 42 --version 3 --full --format json \
  | jq '.data' > /tmp/draft.json
integry templates create --input /tmp/draft.json

integry templates diff

Show differences between a published version and the current draft, ignoring IDs and read-only fields.

integry templates diff <id> --version N [--context N] [--format toon|json]
Flag Effect
<id> (positional, required) Base template primary key.
--version N (required) Version number to compare against the current draft.
--context, -C N Number of context lines around each change. Default 5.
--format toon (default) or json.

Strips id, version_template_id, version_of, version_number, last_modified, last_modified_by, created, publishing_status, revision_number from both sides before diffing. Output is unified diff format:

--- version 3
+++ draft
@@ -1,7 +1,7 @@
 {
   "meta": {
     "app_id": 7,
-    "description": "Original description",
+    "description": "Updated description",

When there are no semantic changes: no differences. --format json emits {"ok": true, "data": {"diff": "...", "has_changes": true/false}}.


integry templates test

Test a FUNCTION template's draft version by calling it via the signed-request API. Automatically fetches workspace app credentials, resolves connected accounts, and computes the HMAC hash.

integry templates test <id> [--input <file|->] [--connected-account-id N] [--format toon|json] [--full]
Flag Effect
<id> (positional, required) Template primary key. Must be type=FUNCTION.
--input, -i Path to a JSON file with function arguments, or - for stdin. Defaults to {} if omitted.
--connected-account-id N Use this connected account directly - skips the app lookup and selection prompt.
--format toon (default) or json.
--full Disable field filtering and string truncation.

Prerequisites: must be authenticated and have an account selected (accounts use <id>).

Flow:

  1. Fetches the template, verifies type=FUNCTION, extracts machine_name.
  2. Gets workspace app key/secret from /accounts/me/.
  3. Computes signed-request credentials (HMAC-SHA256).
  4. Fetches connected accounts for the app. Single account → auto-selected; multiple → interactive prompt.
  5. Calls the function with version: DRAFT header.

Output:

result: "sent"

Exits 1 on function call failure, 3 if the template is not FUNCTION, has no machine_name, no account is selected, or no connected accounts exist.


Examples

# Local backend, fresh login
export INTEGRY_API_URL=http://localhost:8000
integry auth login --username alice

# Discover the accounts you belong to, then pin one
integry accounts list
integry accounts list --search acme   # narrow the list when you belong to many
integry accounts use 7

# List templates in the active account, narrow to FUNCTION templates
integry templates list
integry templates list --type FUNCTION
integry templates list --search send --type FUNCTION --type ACTION
# ...or one-shot via env (wins over the persisted value)
INTEGRY_ACCOUNT_ID=7 integry templates list-versions 42

# Create a template from a file
integry templates create --input ./examples/my-template.json

# Pipe a body through stdin
jq '.template' big.json | integry templates create --input -

# Bump a template's revision number and patch its name
integry templates update 42 --input ./patch.json --revision 11 --meta-only

# Ask for full JSON output for an agent
integry templates update 42 --input ./patch.json --meta-only --format json

# Publish a draft
integry templates update 42 --input ./empty-meta.json --publish --meta-only

# Inspect a template and its version history
integry templates get 42
integry templates list-versions 42
integry templates get 42 --version 3

# Publish the current draft as a new version with a changelog
integry templates publish 42 --changelog "Added retry logic"

# Clone a published version back into a fresh draft
integry templates get-draft 42 --version 3 --full --format json | jq '.data' > /tmp/draft.json
integry templates create --input /tmp/draft.json

# Diff a version against the current draft
integry templates diff 42 --version 3
integry templates diff 42 --version 3 --context 10

# Bootstrap a template body from --example
integry templates create --example > template.json
integry templates update 42 --example > patch.json

# Test a FUNCTION template draft
integry templates test 42
integry templates test 42 --input args.json
integry templates test 42 --input args.json --connected-account-id 12345

Further reading

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

integry_app-0.1.0.tar.gz (47.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

integry_app-0.1.0-py3-none-any.whl (36.6 kB view details)

Uploaded Python 3

File details

Details for the file integry_app-0.1.0.tar.gz.

File metadata

  • Download URL: integry_app-0.1.0.tar.gz
  • Upload date:
  • Size: 47.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"NixOS","version":"25.05","id":"warbler","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for integry_app-0.1.0.tar.gz
Algorithm Hash digest
SHA256 13d745a652c84e871c0a606679b18966d95e823473b3a46a79b420b20ffc1c11
MD5 a6e48d5171c567ba44f59389d0d1527d
BLAKE2b-256 7dbae25feb334ff58b4d6c147c36c8bda020dd11aa117f0634c27eed482c0d5f

See more details on using hashes here.

File details

Details for the file integry_app-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: integry_app-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 36.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"NixOS","version":"25.05","id":"warbler","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for integry_app-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 13ad41cb5de4a0ea029dbc1633da093db4a3ae3c454aba9b6abe2d984d581b2e
MD5 5e6bec0986748dcd61ca8f00ea142ca0
BLAKE2b-256 3a5050f3eb915f85c851c901f66a80898f29e05e66f30b5f7e48105e6705d0b8

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page