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 templatePATCH /api/v5/templates/<id>/- partial update a templateGET /api/v2/templates/<id>/- retrieve a template (or its draft payload)GET /api/v1/templates/<id>/versions/- list versionsGET /api/v1/templates/<id>/versions/<n>/- retrieve a specific versionPOST /api/v1/templates/<id>/versions/- publish the draft as a new versionPOST /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 byauth login --api-urlandaccounts use)$INTEGRY_HOME/credentials.json-{"access", "refresh", "obtained_at"}
Output
- Default format is TOON (token-efficient). Pass
--format jsonfor 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
- Template detail →
- Pass
--fullto 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:
INTEGRY_ACCOUNT_IDenv varaccount_idin$INTEGRY_HOME/config.json(set viaaccounts use)- 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 thestepsand 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:
- Fetches the template, verifies
type=FUNCTION, extractsmachine_name. - Gets workspace app
key/secretfrom/accounts/me/. - Computes signed-request credentials (
HMAC-SHA256). - Fetches connected accounts for the app. Single account → auto-selected; multiple → interactive prompt.
- Calls the function with
version: DRAFTheader.
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
docs/- architecture, conventions, version control, per-command feature docs- AXI principles
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
13d745a652c84e871c0a606679b18966d95e823473b3a46a79b420b20ffc1c11
|
|
| MD5 |
a6e48d5171c567ba44f59389d0d1527d
|
|
| BLAKE2b-256 |
7dbae25feb334ff58b4d6c147c36c8bda020dd11aa117f0634c27eed482c0d5f
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
13ad41cb5de4a0ea029dbc1633da093db4a3ae3c454aba9b6abe2d984d581b2e
|
|
| MD5 |
5e6bec0986748dcd61ca8f00ea142ca0
|
|
| BLAKE2b-256 |
3a5050f3eb915f85c851c901f66a80898f29e05e66f30b5f7e48105e6705d0b8
|