Managing integrations
truto integrations lists, creates, updates, and deletes integration definitions: the connectors behind every third-party app Truto talks to. This page also covers scaffolding, validating, linting, and the apply workflow that pushes a built integration live.
Quick reference
truto integrations list
truto integrations get <id> -o json
truto integrations create -b '{"name":"my-app","config":{"label":"My App","base_url":"https://api.example.com"}}'
truto integrations update <id> -b '{"category":"crm"}' --lock-version 1
truto integrations delete <id> -fScaffold a new integration (init)
init builds a starter config interactively, then creates it on Truto.
truto integrations init acme-crm
truto integrations init --label "Acme CRM" --auth oauth2 --base-url https://api.acme.com
truto integrations init acme-crm --print # print config only, no API call
truto integrations init acme-crm --out acme.json # write to fileValidate config (validate)
Check a config against the IntegrationConfig schema before you push it.
truto integrations validate <integration-id>
truto integrations validate -f ./config.json
cat config.json | truto integrations validate --stdinDiscovery helpers
See what an integration exposes before you build against it.
truto integrations tools <id-or-name> # tools/methods it exposes
truto integrations unified-apis <id-or-name> # unified APIs mapped to itCreate, update, and delete
List filter: --name. Create needs: name and config (JSON). category is optional.
truto integrations create
echo '{"name":"test","config":{"label":"Test"}}' | truto integrations create --stdinUpdate needs --lock-version, the record's current version from get. A stale version is refused, so fetch the latest first. To read an older version instead, use truto integrations get <id> --at-version <n>.
Update sends your whole config. The CLI refuses one that would drop a top-level key, resource, or method, unless you say how to send it:
| Flag | What it does |
|---|---|
--merge-config |
Merge your partial config over the live one, then send the result. |
--replace-config |
Send config exactly as given. Needed to remove keys, resources, or methods on purpose. |
--dry-run |
Print the plan and the config diff. Send nothing. |
- Changing
sharingoris_betaneeds--publish, or the update is refused. Sending back the value that's already live isn't a change, so it needs no flag. --stdintakes one record. More than one, in a JSON array or NDJSON, is refused, since every record would go to the same<id>.
Apply
Build the integration, then push it with apply. Apply re-checks the exact config and documentation, so running lint separately is optional.
Apply updates the integration named by the file's id. A new integration is created private and in beta. Pointing the same file at a different target makes a separate working copy; the original is untouched.
flowchart LR
file["Your file"] --> choice{"Safe or quick?"}
choice -->|"safe"| prepare["--prepare"]
prepare --> review["Review the plan"]
review --> run["--plan --expect-digest"]
choice -->|"quick"| direct["apply, no flags"]
# Safe: save a plan, review it, then run it
truto integrations apply acme.integration.json --prepare
cat acme.integration.json.plan.json
truto integrations apply acme.integration.json --plan acme.integration.json.plan.json --expect-digest <digest>
# Quick: apply directly
truto integrations apply acme.integration.jsonRead the plan --prepare saves before you run it with --plan. It is your last look before anything reaches Truto.
Apply compares three things: your file, the baseline from the last apply, and what's live. A few rules follow from that:
- A teammate's live edit is kept. Apply syncs it back into your file instead of overwriting it.
- A clash needs a choice. Pass
--resolve '<item>=mine'or--resolve '<item>=theirs'. - A config key you drop stays live. Apply never removes one. Use
truto integrations updateinstead. - Secrets are never lost. Apply holds, rather than sends, any write that would drop a credential secret.
Dropping a live method stops the whole run, before any write. Put it back in the file, or pass --allow-method-removal to remove it live too.
Mark a test account once, or pick one per run, to try real reads before you trust the result:
truto profiles set test-account.acme <account-id>
truto integrations apply acme.integration.json
truto integrations apply acme.integration.json --test-account <account-id>Only reads apply can prove are safe actually run. Apply also waits about 7 minutes for the config cache to refresh before it reads. Tests can still be pending when the run ends.
A read can still refresh tokens, flip Truto's reauth state, or emit ordinary webhooks. Apply discloses this before it runs one.
A prepared plan keeps the test account you chose at prepare time. Run --prepare again to switch it.
Check an account without applying anything, with the same safety check:
truto integrations audit acme.integration.json -a <account-id> --capability read-only| Flag | What it does |
|---|---|
--prepare |
Check, reconcile, and save a plan. No platform writes, no account tests. |
--plan <path> |
Run a saved plan. Stale inputs stop it. Optional --expect-digest <digest> checks it's the plan you reviewed. |
--dry-run |
Offline preview. No Truto reads, writes, or account tests. |
--diff |
UPDATE only. Print how the file differs from live. Writes nothing. |
--resolve |
Settle a clash: --resolve '<item>=mine' or --resolve '<item>=theirs'. |
--allow-method-removal |
Remove the live methods the file drops or renames. |
--docs-only |
Write documentation only. The integration must exist. |
--no-docs-refresh |
Skip documentation regeneration. No model call, no source fetch. |
--prune-docs |
Remove orphaned per-method docs once the writes finish. |
--test-account <account-id> |
Use this account for this run's read tests. |
A method with a blocking finding is skipped rather than failing the whole run, so other independent work still lands. Two documentation rows for the same method and auth type, with different content, are refused before anything is written.
| Exit | Meaning |
|---|---|
| 0 | Complete, or nothing needed to change. |
| 1 | Authentication or unexpected failure, even after some writes landed. |
| 2 | Writes landed and some work is still pending. |
| 3 | Nothing written. Work is pending, or the run is blocked. |
| 4 | Otherwise complete, but a test that ran failed. |
--prepare writes nothing, so it always exits 3 when its plan leaves something pending.
Results and recovery
-o json prints one structured result. Read the skipped, held, clash, and uncertain items, and the next command it suggests.
The CLI saves an automatic report and an authoritative <artifact>.committed pair. Edit only the artifact; reports, plans, and backups aren't apply inputs. If someone else edits the file while apply runs, their save is preserved too. Don't delete recovery state to make a conflict disappear.
Don't treat an exit-zero --dry-run, a saved file or a local check as production verification.
Secrets and restoring
Apply refuses a literal credential secret inside a build artifact. A write that would lose a stored secret is held until the backend's secret-preservation check passes for that host.
--replace-config acknowledges a deliberate removal, but it doesn't bypass a secret hold. For an intentional partial update, use --merge-config instead. A merge replaces a named credential whole, so send its secret in full.
To restore an older config on purpose:
truto integrations get <id> --at-version <previous-version> -o json
truto integrations update <id> --lock-version <current-version> --body-file restore.json --replace-configCheck the old and current values before you restore. Apply never rolls back live data on its own.
Lint
truto integrations lint statically audits a config. No LLM call, and for a file with an id, it checks that integration's live documentation rows too. Linting by slug instead of file fetches the live integration.
truto integrations lint ./acme.integration.json
truto integrations lint acme-crm # audit the live integration by slug
truto integrations lint ./acme.integration.json --ignore-warningsExit codes: 0 clean, 1 on any ERROR or WARN (--ignore-warnings: ERRORs only), 2 input error.
Info findings never change the exit code; --ignore-info only hides them from the table. An integration with no method description at all is a WARN, not an ERROR. It doesn't block apply by itself.
Next
- Build a new integration from API docs: AI-powered build.
- Add one method by hand, no LLM: Add method.
- List integration categories, such as
crmorats:truto categories list.