Loggie CLI
Agent-first discovery, API proxy calls, and event consumption. This README ships with the @loggie-ai/cli package; command flags are defined in cli.ts and exposed through loggie <command> --help.
Install and authenticate
Requires Node 20 or newer.
npm install -g @loggie-ai/cli
loggie init
loggie status
API key precedence: --api-key (alias --key) or --profile, LOGGIE_API_KEY, then the active profile in ~/.loggie/config.json. Prefer interactive init or an environment variable over putting a credential in shell history. loggie logout removes all saved profiles; it does not revoke the server-side key or unset environment variables.
The default server is https://app.loggie.ai. Set LOGGIE_SERVER_URL to override it, for example for local development. See config.ts for resolution and storage.
Switch profiles
Save each agent API key under a local name, then switch the profile used by subsequent commands:
loggie init --profile work
loggie init --profile personal
loggie profiles list
loggie profiles use work
loggie status
init validates the key before saving and activates the saved profile. Without --profile, it updates the active profile, or creates default if no config exists. Existing single-key configs appear as default and are preserved when adding another profile. Names can contain letters, numbers, dots, underscores, and hyphens, must start with a letter or number, and have a maximum length of 64 characters.
Each profile saves its server URL. Use loggie init --profile local --server-url http://localhost:5173 for a local profile; LOGGIE_SERVER_URL also supplies the URL during initialization. New profiles use the default server unless overridden. Reinitializing a profile retains its saved server unless overridden.
profiles list returns names, server URLs, and the active selection without keys. profiles use reports environment variables that still override the saved credentials or server. --api-key and LOGGIE_API_KEY retain precedence over the active profile; LOGGIE_SERVER_URL overrides its saved server. status reports the effective authentication sources. profile is an alias for profiles; use --pretty for readable JSON.
When using saved progress, event commands verify the profile through /api/setup. An explicit pull --since <cursor> reads the feed without loading saved progress. Cursors and retry counts are scoped to the server and profile ID, including named cursors, so rotating an API key preserves progress. If an unscoped cursor exists, the CLI stops and reports its position. After verifying the selected profile owns those events, pass --replay-from <cursor> to listen or watch (or --since <cursor> to pull). Use --replay-from latest to intentionally start at the current position. An explicit consumer resume is saved even when no events arrive; the original unscoped state remains intact.
Event HTTP reads retry rate-limit responses up to twice when Retry-After specifies a wait of at most 60 seconds. Each retry retains the same credentials and cursor.
Profile mutations are serialized across CLI processes. An interrupted write can leave a lock directory; the timeout error identifies it so you can remove it after confirming no writer is running.
Use a profile for one command
Pass --profile <name> to run one command as a saved profile without changing the active profile or writing ~/.loggie/config.json:
loggie status --profile work
loggie --profile=personal setup
loggie discover linear --profile work
loggie call linear GET /issues --profile work
loggie linear pending --profile work
loggie events --profile work pull
loggie events listen --profile work --exec ./handle-event.sh
setup, status (alias whoami), discover, call, every linear action, and events pull, listen, and watch accept the flag before or after the command, and event commands also accept it after events. Repeating the flag with the same name is accepted; different names are rejected.
The selected profile supplies both the API key and the server, overriding LOGGIE_API_KEY and LOGGIE_SERVER_URL. A profile with no saved server URL uses the default server. An unknown name, a malformed name, or a missing or malformed config fails before any request and never falls back to another credential. Combining --profile with --api-key or --key is rejected.
status reports the local name used by the command as auth.savedProfile and the persisted selection as auth.activeProfile. Both are omitted when no config exists. The top-level profile field is the server-side agent profile.
init --profile saves and activates the named profile, and accepts --api-key. logout and profiles manage all saved profiles, so they reject the flag before changing anything.
events listen and watch capture the selected key and server once at startup and use them for retries, polling, reconnects, and handlers. Later profile switches or key rotations do not redirect a running process; restart it to use the new values. Handlers inherit that pair as LOGGIE_API_KEY and LOGGIE_SERVER_URL, so a loggie command inside a handler uses the same account unless it passes its own --profile. Progress stays scoped to the server and server-side profile ID, so two local names for the same agent share progress.
Discover before calling
loggie discover
loggie discover asana --method POST --search tasks --limit 10
loggie discover asana --endpoint /tasks --method POST
loggie discover linear --endpoint / --method POST --graphql-type query --operation viewer
loggie call linear POST / -d '{"query":"query { viewer { id } }"}'
Slugs depend on your connections. Use catalog results for the actual paths and operations. loggie setup prints the agent setup payload; whoami aliases status.
Commands default to JSON, while call preserves the upstream response body. Use --pretty for JSON readability or discovery's --table for a human view. loggie call --help documents headers, query strings, multipart fields, and binary uploads.
loggie call has a 60-second request timeout, including response-body download. Use --timeout <seconds> to override it, or --timeout 0 to disable it. A timeout exits 1, writes a JSON TIMEOUT error to stdout, and prints a one-line error to stderr. GET and HEAD do not read stdin implicitly; native fetch does not support request bodies for those methods.
Request a policy
Discover the Loggie Admin connection, then propose a policy for human approval:
loggie discover loggie-admin --endpoint /policy-requests --method POST
loggie call loggie-admin POST /policy-requests -d '{"integrationId":"CONNECTION_UUID","prompt":"Only allow reading tasks; hide customer emails.","assignToAgent":true}'
loggie call loggie-admin POST /policy-requests -d '{"policy":{"integrationId":"CONNECTION_UUID","name":"Read access","permission":"read","endpointRuleMode":"NONE"},"assignToAgent":true}'
loggie call loggie-admin GET /requests/REQUEST_UUID
Use either a plain-language prompt with integrationId, or a complete policy drafted by the agent. A complete policy opens directly in Review without a Loggie AI call. A prompt prefills the same AI-assisted creator as the Policies tab; the human generates and edits its draft.
Use the actual Admin slug returned by discovery. Give the returned setupUrl to a workspace member. They review the complete policy and approve or reject it while signed in. Approval creates the policy and assigns it to the requesting agent for that connection, replacing any existing policy assignment. Set assignToAgent to false to create only a reusable policy. The proposal creates no policy and changes no assignments before approval. Poll pollUrl until COMPLETED returns policyId; EXPIRED and CANCELLED are terminal. Requests expire after 24 hours.
The discovery schema documents endpoint rules, approval rules, rate limits, response redactions, and request body restrictions. Connections must have a workspace provider draft to support reusable policies.
To update an existing policy, add its policyId to either request shape. Supply the complete desired policy; omitted optional restrictions are cleared when the reviewed replacement is applied.
loggie call loggie-admin POST /policy-requests -d '{"policyId":"POLICY_UUID","policy":{"integrationId":"CONNECTION_UUID","name":"Read access","permission":"read","endpointRuleMode":"NONE","rateLimitPerMinute":30}}'
loggie call loggie-admin POST /policy-requests -d '{"policyId":"POLICY_UUID","integrationId":"CONNECTION_UUID","prompt":"Allow only reading tasks and hide customer email addresses."}'
The reference connection must use the same provider and API type as the existing policy. Human rejection returns CANCELLED. Updates retain the policy ID and all existing assignments, so every assigned agent/connection is affected. assignToAgent defaults to false for updates; true is rejected. The review displays the saved policy, proposed changes, and affected assignments. If the policy or assignment set changes before approval, submit a new request. Completed polling returns the same policyId.
Events
loggie events pull --limit 10
loggie events listen --help
loggie events watch --help
pull fetches once. listen uses WebSocket delivery; watch polls. Both continuous modes require --exec and execute that command for events, passing JSON on stdin and in LOGGIE_EVENT. Configure a handler only when those actions are intended. Consult each command's help for replay and named-cursor options.
Work on the CLI
From the repository root:
pnpm build:cli
pnpm test:cli
node cli/dist/cli/src/bin.js --help
The CLI does not automatically load cli/.env. To use those credentials against the local dev server:
LOGGIE_SERVER_URL=http://localhost:5173 node --env-file=cli/.env cli/dist/cli/src/bin.js status
Linear agent deliveries
loggie linear pending recovers queued work independently of an event cursor. If the response has a non-null nextCursor, continue with loggie linear pending --cursor NEXT_CURSOR. Use claim, context, start, heartbeat, activity, and finish to execute a delivery; inspect and reconcile support interrupted runs. Commands emit JSON by default. See the Linear setup and recovery contract. Linear reads and writes continue through loggie call and the existing access policy.