Skip to content

CLI

CLI overview

Install the Trace CLI and use its commands for auth, org context, pentest target setup, repositories, source uploads, and pentests.

The Trace CLI (tracecli) lets you authenticate, set up the applications you want tested, manage repositories, upload source archives, and review pentest findings directly from your terminal, including the pentest commands for listing engagements and pulling their findings.

Install

npm install -g securewithtrace

tracecli runs on the Bun runtime, so bun needs to be on your PATH. If it isn't, tracecli stops with install instructions instead of running. Any of these installs it:

curl -fsSL https://bun.sh/install | bash
# or
brew install oven-sh/bun/bun
# or
npm install -g bun

Verify the installation:

tracecli --help

Interactive pager

List commands (org list, repo list, repo filter, inbox list, inbox emails, upload list, pentest list, pentest findings list, pentest attestation list) render results through an interactive pager when stdout is attached to a TTY. Navigate with:

  • ↑ / ↓ or k / j: move selection by one line
  • PgUp / PgDn or b / f / Space: scroll by one page
  • Home / g: jump to first result
  • End / G: jump to last result
  • q, Esc, or Ctrl+C: exit the pager

The pager is skipped automatically when:

  • stdout is not a TTY (e.g. piped to another command or redirected to a file)
  • the NO_PAGER=1 or TRACECLI_NO_PAGER=1 environment variable is set
  • the command is invoked with --output json or --output tsv
  • the command is invoked with --no-pager

Command tree

tracecli
├── auth
│   ├── login
│   ├── logout
│   └── status
├── org
│   ├── list
│   ├── current
│   ├── switch [organization]
│   ├── update
│   └── invite <email>
├── application (alias: app)
│   ├── create <name>
│   ├── list
│   ├── get <applicationId>
│   ├── repos <applicationId> (alias: repositories)
│   ├── update <applicationId>
│   └── delete <applicationId>
├── environment (alias: env)
│   ├── create <name> --app <applicationId>
│   ├── list [--app <applicationId>]
│   ├── get <environmentId> --app <applicationId>
│   ├── update <environmentId> --app <applicationId>
│   └── delete <environmentId> --app <applicationId>
├── credential (alias: cred)
│   ├── create --env <environmentId> --type <type> [--label <label>]
│   ├── list --env <environmentId>
│   ├── get <credentialId> --env <environmentId>
│   ├── update <credentialId> --env <environmentId>
│   ├── delete <credentialId> --env <environmentId>
│   ├── set-mfa <credentialId> --env <environmentId>
│   ├── mfa-code <credentialId> --env <environmentId>
│   └── clear-mfa <credentialId> --env <environmentId>
├── inbox
│   ├── create <label>
│   ├── list
│   ├── emails <label>
│   ├── email <label> <messageId>
│   └── delete <label>
├── repo
│   ├── list
│   ├── filter
│   └── clone <repository> [directory]
├── upload (alias: code-upload)
│   ├── create <file> (alias: source)
│   ├── build <file> --app <applicationId>
│   ├── list
│   ├── get <codeUploadId>
│   ├── download <codeUploadId>
│   ├── resume <codeUploadId> <file>
│   ├── wait <codeUploadId>
│   ├── delete <codeUploadId>
│   └── link --app <applicationId> --upload <codeUploadId>
├── code-size
├── pentest
│   ├── list
│   ├── questionnaire <pentestId>
│   ├── findings
│   │   ├── list
│   │   ├── get
│   │   ├── repro
│   │   ├── status-update
│   │   └── attach-evidence
│   ├── report
│   │   └── download <pentestId>
│   └── attestation (alias: loa)
│       ├── list <pentestId>
│       └── download <pentestId>
├── upgrade (alias: self-update)
└── completion

Authentication

tracecli sends Authorization: Bearer <token> on every API request. Two credential sources are supported; the first match wins.

  1. TRACE_API_KEY — a long-lived Trace API key (trace_sk_...). When this environment variable is set and non-empty, it takes precedence over any files under ~/.trace/. Mint a key in the dashboard under API Keys. This is the path for CI and other non-interactive automation.
  2. Device-flow login — tracecli auth login stores a WorkOS JWT and refresh token under ~/.trace/ (token and refresh-token). Use this on a developer machine.

Create an API key

Mint a long-lived key for CI and other non-interactive automation.

Opens in your dashboard

Open dashboard

A malformed TRACE_API_KEY fails immediately with a shape error (expected trace_sk_...) rather than sending a request that would 401. API keys are not refreshed; a 401 means the key is invalid, expired, or revoked — check the dashboard API Keys page. auth login, auth logout, and org switch refuse to run while TRACE_API_KEY is set, because mutating ~/.trace would not change which credential is used. org current and org list still work: the API returns the key's bound organization.

Some commands require a human session and reject API keys (the API returns 403 Human principal required for this operation). That includes application / environment / credential writes, application repos, org update, org invite, source uploads, and staff-only routes. For those, unset TRACE_API_KEY and run tracecli auth login.

pentest findings status-update accepts either credential. With a key it posts to a separate automation endpoint, which your organization has to have finding automation enabled for; ask Trace to turn it on.

auth commands

Manage CLI authentication for your Trace account.

tracecli auth login

Starts the device authorization flow, opens a browser when possible, and stores tokens under ~/.trace/. Refuses to run when TRACE_API_KEY is set — unset the environment variable first.

tracecli auth login

tracecli auth logout

Removes local auth token files from ~/.trace/. Prompts for confirmation in interactive terminals. Refuses to run when TRACE_API_KEY is set; unsetting the environment variable is what actually drops API-key auth.

FlagShorthandDefaultDescription
--no-confirmSkip confirmation prompt (for CI/scripts).
# Log out interactively (prompts for confirmation)
tracecli auth logout

# Skip confirmation prompt (for CI/scripts)
tracecli auth logout --no-confirm

tracecli auth status

Shows current login status, including whether you are using a user session or an API key, token expiry (user sessions), and whether a refresh token is present. For an API key, only the public key id (trace_sk_<keyId>) is shown — never the secret half. When the key came from TRACE_API_KEY, the status output says so.

Exits with code 1 when not logged in, regardless of output format. This lets scripts use tracecli auth status || tracecli auth login without extra parsing. In json and tsv modes, the structured data is still written to stdout before exiting; the exit code signals whether action is needed.

FlagShorthandDefaultDescription
--output <format>-otableOutput format: table, json, tsv. TSV: header row then one data row, columns: loggedIn, authMethod, expired, hasRefreshToken, userId, orgId, activeOrg, activeOrgName, activeOrgSlug.
# Show login status (table mode, exits 1 and prints to stderr when not logged in)
tracecli auth status

# Machine-readable JSON (for scripts/CI, exits 1 when not logged in)
tracecli auth status --output json

# Use in scripts to auto-login when session is missing
tracecli auth status || tracecli auth login

# CI: authenticate with a dashboard API key instead of device-flow login
export TRACE_API_KEY=trace_sk_...
tracecli auth status --output json

org commands

Manage active organization context for CLI commands, update the active organization's homepage URL and logos, and invite members.

tracecli org list

Lists organizations available to your account and marks the currently active organization. Table output includes Title Case column headers (Name, Slug, Org ID).

FlagShorthandDefaultDescription
--output <format>-otableOutput format: table, json, tsv. TSV columns: name, slug, organizationId, active.
--limit <n>-LallMaximum number of organizations to display.
--filter <expression>-fRepeatable filter expression. Fields: name, slug. Operators: = exact, != not exact, : contains, !: not contains.
--web-wOpen the organization settings page in a browser instead of listing.
--no-pagerDisable the interactive pager and print all results at once.

tracecli org current

Shows the active organization context used by repo and pentest commands.

FlagShorthandDefaultDescription
--output <format>-otableOutput format: table, json, tsv. TSV columns: name, slug, organizationId, source.
--web-wOpen the organization settings page in a browser.

tracecli org switch [organization]

Switches the active organization context for subsequent CLI commands. The optional argument accepts organization ID, slug, or name. If omitted in an interactive terminal, tracecli prompts you to choose from your available organizations. Refuses to run when TRACE_API_KEY is set — API keys are bound to a single organization.

FlagShorthandDefaultDescription
--web-wOpen the organization settings page in a browser instead of switching. If [organization] is provided, opens that org's settings; otherwise opens the current org's settings.

tracecli org update

Updates the active organization's homepage URL and light/dark logos, the same fields as the dashboard's Settings > Profile page. Every flag is optional, but at least one is required. Requires an organization admin signed in via tracecli auth login; API keys are rejected.

A logo value is either an image file to upload or an http(s) URL to link. Files upload straight to storage (.png, .jpg, .jpeg, .gif, .svg, .webp; 2 MB max). Saving a file or URL for a slot replaces whatever that slot held before, and --clear-* empties it. --logos-from-homepage runs the same "fetch logos from homepage" action as the dashboard and can't be combined with explicit logo flags; when passed together with --homepage, the homepage is saved first.

FlagShorthandDefaultDescription
--homepage <url>Homepage URL (https://...).
--clear-homepageRemove the homepage URL.
--logo <file-or-url>Light-mode logo: an image file to upload, or an http(s) URL.
--clear-logoRemove the light-mode logo.
--dark-logo <file-or-url>Dark-mode logo: an image file to upload, or an http(s) URL.
--clear-dark-logoRemove the dark-mode logo.
--logos-from-homepageFetch light and dark logos from the homepage (after saving --homepage, if given).
--output <format>-otableOutput format: table, json, tsv. TSV columns: name, slug, homepageUrl, logoUrl, darkModeLogoUrl.
# Set the homepage and pull logos from it in one go
tracecli org update --homepage https://acme.com --logos-from-homepage

# Upload logo files for both themes
tracecli org update --logo ./logo.svg --dark-logo ./logo-dark.svg

# Link an externally hosted logo instead of uploading
tracecli org update --logo https://cdn.acme.com/logo.png

# Remove the dark-mode logo
tracecli org update --clear-dark-logo

tracecli org invite <email>

Sends an invitation email to join the active organization, the same action as the Invite member form on the dashboard's Settings > Members page. The invitee gets an email with a link to accept and joins the org with the granted role. Requires an organization admin or analyst signed in via tracecli auth login; API keys are rejected. Only admins can invite someone as an admin.

Fails before any network call when the email is malformed or the role is unknown. The API returns a conflict when the address already belongs to a member or has a pending invitation; revoke pending invitations from the dashboard.

FlagShorthandDefaultDescription
--role <role>-rdeveloperRole to grant: admin, analyst, developer.
--output <format>-otableOutput format: table, json, tsv. TSV columns: invitationId, email, roleSlug.
# Invite a developer (the default role)
tracecli org invite dev@acme.com

# Invite an analyst
tracecli org invite sec@acme.com --role analyst

# Invite an admin (admins only) and capture the invitation ID
tracecli org invite cto@acme.com --role admin --output json | jq -r .invitationId
# List available orgs and see which one is active
tracecli org list

# JSON output for scripting
tracecli org list --output json | jq '.[].slug'

# Show current active org
tracecli org current

# Switch by slug
tracecli org switch engineering

# Switch by org ID
tracecli org switch org_01KJTJFFG497Z1C54Z07AP6NA3

# Prompt and choose interactively
tracecli org switch

application commands

Manage applications in the active organization. Applications are the scope object for environments, credentials, and pentests.

Reads list and get are available to any member with view access. repos is not: link details (role, path, scan state) require an organization admin or Trace staff signed in with a browser session — API keys are rejected. Writes (create, update, delete) require an organization admin signed in with a browser session (or Trace staff) on a pentest-enabled organization — API keys are rejected for these writes.

All commands accept --output <format> (-o) with table (default), json, or tsv. The group is also available under the app alias.

tracecli application create <name>

Creates an application. --type is case-insensitive (web, cli, mobile, desktop, api-service; default web). Web and API applications require --url; CLI, mobile, and desktop applications must not have one, the CLI checks this locally before calling the API.

FlagShorthandDefaultDescription
--type <type>webApplication type: web, cli, mobile, desktop, api-service.
--url <url>Application URL. Required for web/api-service; rejected for cli/mobile/desktop.
--repo <id-or-url>Link a repository at creation. Accepts a repository UUID, a URL, or owner/repo shorthand (resolved against the org's repositories).
--repo-path <path>Path within the linked repository (ignored without --repo).
--output <format>-otableOutput format: table, json, tsv.
# Create an API application
tracecli application create "Billing API" --type api-service --url https://billing.acme.com

# Create a web app and link a repository at creation
tracecli application create "Web Store" --url https://store.acme.com --repo acme/store --repo-path apps/web

tracecli application list

Lists applications in the active organization.

FlagShorthandDefaultDescription
--output <format>-otableOutput format: table, json, tsv. TSV columns: applicationId, name, type, applicationUrl, repositories, createdAt.
--no-pagerDisable the interactive pager for table output.
tracecli application list
tracecli application list --output json | jq '.[].name'

tracecli application get <applicationId>

Shows a single application by UUID. Accepts --output <format> (-o): table (default), json, tsv.

The Repos line counts every link, including scan-disabled ones. That total is not a readiness signal: scans and pentest start-readiness both skip disabled links. Use application repos for the per-link scan state.

tracecli application repos <applicationId>

Lists the repositories linked to an application, with the SCAN column showing whether each link is scan-enabled. Also available as application repositories.

A link with SCAN=no is still linked — it counts in application get's Repos total — but scans skip it and it does not satisfy the repository precondition for starting a pentest. This is the command to reach for when an application appears to have repositories but work won't start.

FlagShorthandDefaultDescription
--output <format>-otableOutput format: table, json, tsv. TSV columns: repositoryId, repositoryName, scanEnabled, role, roleLabel, repositoryPath, repositoryStatus. TSV/JSON carry the raw role enum; the table shows the same human label as the dashboard.
--no-pagerDisable the interactive pager for table output.
tracecli application repos <appId>
# count only the links that actually count
tracecli application repos <appId> -o json | jq '[.[] | select(.scanEnabled)] | length'

tracecli application update <applicationId>

Updates an application. The update is partial: only the flags you pass are changed. The application type cannot be changed, and repository links are managed separately (not via update). Pass at least one field.

FlagDefaultDescription
--name <name>New name.
--url <url>New application URL (web/api-service only).
--help-center-url <url> / --clear-help-center-urlSet or remove the help center URL.
--docs-url <url> / --clear-docs-urlSet or remove the documentation URL.
--output <format>tableOutput format: table, json, tsv.

tracecli application delete <applicationId>

Deletes an application. Prompts for confirmation in interactive terminals; in non-interactive shells (CI, pipes) it refuses unless --yes is passed. Deletion is blocked by the API when pentests still reference the application.

FlagShorthandDefaultDescription
--yes-ySkip the confirmation prompt (required in non-interactive shells).

environment commands

Manage the environments of an application (e.g. staging, production). Environments are nested under an application, so every environment command requires --app <applicationId> — except list, where it is optional (omit it to list every environment in the organization).

Reads (list, get) are available to any member with view access; writes (create, update, delete) require an organization admin (or Trace staff) on a pentest-enabled organization, and reject API keys. All commands accept --output <format> (-o): table (default), json, tsv. The group is also available under the env alias.

tracecli environment create <name> --app <applicationId>

Creates an environment. The name must be lowercase letters, digits, or dashes, starting with a letter (validated locally). An application may have at most one production environment. Mobile applications do not have environments; the API rejects create on that type.

Whether --url applies depends on the parent application's type. Web and API applications require it: the URL is the target that drives DAST and recon. CLI and desktop applications are credential contexts with no network target, so they must omit it, and the API rejects a URL on those types. --additional-url follows the same rule.

FlagDefaultDescription
--app <applicationId>requiredParent application UUID.
--url <url>Primary URL for the environment. Required for web and API applications, rejected for CLI and desktop.
--description <text>Free-text description.
--productionoffMark as the production environment.
--output <format>tableOutput format: table, json, tsv.
tracecli environment create staging --app <appId> --url https://staging.acme.com
tracecli environment create production --app <appId> --url https://acme.com --production
tracecli environment create pentest-sandbox --app <cliAppId>

tracecli environment list [--app <applicationId>]

With --app, lists that application's environments. TSV columns: environmentId, name, primaryUrl, isProduction, description, createdAt.

Without --app, lists every environment in the organization with an APPLICATION column naming its owner, so you can find a target without already knowing its application UUID. TSV columns for this form: environmentId, applicationId, applicationName, name, primaryUrl, isProduction, createdAt.

There is no org-scoped environments endpoint, so the unscoped form fans out one request per application. If any of those requests fails the command aborts and names the application rather than printing a short list that would look complete.

tracecli environment list
tracecli environment list --app <appId>

tracecli environment get <environmentId> --app <applicationId>

Shows a single environment by UUID. Accepts --output <format> (-o).

tracecli environment update <environmentId> --app <applicationId>

Updates an environment. Partial, only the flags you pass are changed. Pass at least one. Use --production / --non-production to set the production flag (passing both is an error). Other fields: --name, --url, --description.

tracecli environment delete <environmentId> --app <applicationId>

Deletes an environment. Prompts for confirmation interactively; refuses without --yes in non-interactive shells. The API blocks deletion while any pentest still includes the environment, finished or not, and names the engagements that hold it (other than any hidden from your organization).

credential commands

Manage the credentials attached to an environment. Credential records nest under an environment (--env on create/list/get/update/delete). Mint a Trace-hosted inbox first with inbox create when the test account needs a magic-link or OTP address.

Secrets are never displayed. list/get return only the label, type, and (non-secret) auth config, never the secret value. With --output json the body also carries passkeys: for each passkey Trace's agent created on the account, the site (rpId), the user name the site recorded, when it was added and last used. Never the key. Reads are available to any member with view access; writes require an organization admin (or Trace staff) on a pentest-enabled organization, and reject API keys. The group is also available under the cred alias.

Secret input

Secret material is read from one of --secret-stdin, --secret-file <path>, or --secret-env <name>, or a no-echo prompt when none is given on a TTY. There is no inline --secret flag, so secrets don't leak through shell history, ps, or CI logs. For username-password, both the username and password use the same mechanism (--username-* and --password-*); at most one secret may come from stdin.

tracecli credential create --env <environmentId> --type <type> [--label <label>]

Creates a credential. --type is one of bearer-token, jwt-token, api-key, passphrase, username-password, cookie, magic-auth, session-state, ssh-private-key.

FlagDefaultDescription
--env <environmentId>requiredParent environment UUID.
--type <type>requiredCredential type (see list above).
--label <label>Human-readable label (unique per environment). When omitted, Trace picks a unique default from the type (or username when available), qualified with the environment name.
--secret-stdin / --secret-file / --secret-envSecret value source (all types except username-password). For ssh-private-key this is the private key PEM; --secret-file ~/.ssh/<key> is the usual form.
--username-stdin / --username-file / --username-envUsername source (username-password).
--password-stdin / --password-file / --password-envPassword source (username-password), or the key passphrase for an encrypted ssh-private-key (optional; read only when one of these is set).
--output <format>tabletable, json, tsv.

Per-type authConfig convenience flags (each rejected if it doesn't match --type):

TypeFlags
bearer-token, jwt-token--header-name, --token-prefix
api-key--placement <header|query>, --key-name (required together)
cookie--cookie-name (required), --cookie-domain, --cookie-path
magic-auth(none)
username-password--method <form|basic|json> (required), --login-url, --username-field, --password-field, --session-cookie-name, --csrf-token-selector, --csrf-field-name
passphrase(none)
session-state(none) (the origin is read from the capture)
ssh-private-key--ssh-host (required), --ssh-username (required), --ssh-port (1-65535, default 22), --ssh-host-key-fingerprint <SHA256:…>

An ssh-private-key credential stores where to connect (host, port, username) alongside the encrypted key. Accepted PEM labels: OPENSSH PRIVATE KEY, RSA PRIVATE KEY, EC PRIVATE KEY, PRIVATE KEY, ENCRYPTED PRIVATE KEY. The key can't be read back through the API or the dashboard; to replace it, rotate the secret from the dashboard.

When a pentest session starts, Trace loads the key into an in-memory SSH agent on the session's own container and points the testing agent at it. The key is never written to that container's disk: the testing agent authenticates through the agent socket rather than holding the key material itself. Treat the key as scoped to that engagement anyway, and prefer one that only reaches a host you're happy for us to test. One current limit: the key has to be passphrase-free, because nothing can answer a passphrase prompt unattended. Trace's testing traffic reaches you from the address on your engagement's scope page, so allow it before testing starts.

# Bearer token piped from a secrets manager (label defaults to "Bearer token (<env name>)")
vault read -field=token secret/x | tracecli credential create --env <envId> --type bearer-token --secret-stdin

# API key with placement config
tracecli credential create --env <envId> --type api-key --label "prod key" --secret-env API_KEY --placement header --key-name X-API-Key

# Username/password with form-login config (label defaults to "<username> (<env name>)")
tracecli credential create --env <envId> --type username-password \
  --username-env LOGIN_USER --password-env LOGIN_PASS --method form --login-url https://acme.com/login

# Passwordless login that reads a Trace-hosted inbox (mint the address first)
ADDRESS=$(tracecli inbox create portal -o json | jq -r .address)
echo "$ADDRESS" | tracecli credential create --env <envId> --type magic-auth --secret-stdin

# SSH private key with its connection details (label defaults to "SSH private key (<env name>)")
tracecli credential create --env <envId> --type ssh-private-key \
  --secret-file ~/.ssh/bastion_ed25519 --ssh-host bastion.example.com --ssh-username deploy

# Encrypted key: the passphrase rides the --password-* flags
tracecli credential create --env <envId> --type ssh-private-key \
  --secret-file ./key.pem --password-env KEY_PASSPHRASE --ssh-host 10.0.0.5 --ssh-port 2222 --ssh-username ops

tracecli credential list --env <environmentId>

Lists the environment's credentials (no secrets). TSV columns: credentialId, label, credentialType, authConfig, mfa, createdAt. The mfa column is the second-factor kind (TOTP) or empty.

tracecli credential get <credentialId> --env <environmentId>

Shows a single credential (no secret).

tracecli credential update <credentialId> --env <environmentId>

Updates a credential's label, environment, or auth config. This command does not change the secret — rotate a secret from the dashboard (Applications → environment → credential → Rotate secret), which keeps the same credential and its scan history. Auth-config flags must match the credential's existing type, which the CLI looks up automatically. Use --move-env <environmentId> to move it to another environment in the same application, or --clear-auth-config to remove the auth config.

tracecli credential delete <credentialId> --env <environmentId>

Deletes a credential. Prompts for confirmation interactively; refuses without --yes in non-interactive shells. The API blocks deletion while the credential is in use by an active pentest.

tracecli credential set-mfa <credentialId> --env <environmentId>

Attaches a TOTP second factor to an account credential, so Trace can log into a target that enforces MFA. Only username-password and magic-auth credentials can carry one — a bearer token or API key has no login step for a factor to sit in front of.

The setup key is either a full otpauth:// URI or the bare base32 key a setup page shows under "can't scan the QR code?" — not a 6-digit code. Like every secret in this CLI it is read from stdin, a file, or an environment variable, never an inline flag, so it stays out of shell history and CI logs.

Trace stores the key encrypted under its own KMS envelope, separate from the password, so rotating one leaves the other intact. There is no command, endpoint, or dashboard view that reads the key back out; the only thing Trace will return is a generated code.

FlagDefaultDescription
--setup-key-stdin—Read the setup key from stdin.
--setup-key-file <path>—Read the setup key from a file.
--setup-key-env <name>—Read the setup key from an environment variable.
--output <format>tabletable, json, tsv.
tracecli credential set-mfa <credentialId> --env <envId> --setup-key-stdin
tracecli credential set-mfa <credentialId> --env <envId> --setup-key-env TOTP_SETUP_KEY

Re-running it replaces the existing factor in place, keeping the same credential and its scan history.

tracecli credential mfa-code <credentialId> --env <environmentId>

Prints the account's current TOTP code. Use it to confirm an enrolment took. The code always has a few seconds of life left — if the current window is nearly over, the API waits for the next one rather than returning a code that would be rejected as stale.

--output tsv prints the bare code with no surrounding text, for piping into a form filler.

tracecli credential clear-mfa <credentialId> --env <environmentId>

Removes the second factor. Succeeds whether or not one was enrolled.

inbox commands

Provision and read org-scoped Trace-hosted email inboxes. These are the addresses you register as magic-link / OTP identities (or as the username on a username-password account). They do not take --env.

tracecli inbox create <label>

Provisions a Trace-hosted inbox. <label> must be lowercase letters, digits, or dashes, starting with a letter, at most 40 characters. Creates require an organization admin (or Trace staff) on a pentest-enabled organization. The minted address is {org-slug}-{label}@pentest.securewithtrace.com.

FlagDefaultDescription
--output <format>tabletable, json, tsv.
tracecli inbox create portal
ADDRESS=$(tracecli inbox create qa-admin -o json | jq -r .address)

Use the printed address as the test-account email when creating a magic-auth or username-password credential.

tracecli inbox list

Lists the organization's inboxes and the per-org quota. TSV columns: address, label, createdAt. Available to any member with view access.

tracecli inbox emails <label>

Lists emails in a Trace-hosted inbox the active organization owns. Newest first. An inbox that is not assigned to your organization looks the same as a missing label.

FlagDefaultDescription
--output <format>tabletable, json, tsv. TSV columns: messageId, from, to, subject, receivedAt, unread.
--limit <n>Max emails to return (1-50).
--since <timestamp>Only emails received after this ISO-8601 timestamp.
--no-pagerDisable the interactive pager for table output.
tracecli inbox emails portal
tracecli inbox emails portal --limit 10 -o json

tracecli inbox email <label> <messageId>

Reads one email, including its body. <messageId> comes from the ID column of inbox emails (or from JSON/TSV). TSV columns: messageId, from, to, subject, receivedAt, unread, truncated, links, body.

tracecli inbox email portal m-1

tracecli inbox delete <label>

Deletes an inbox. Prompts for confirmation interactively; refuses without --yes in non-interactive shells.

repo commands

Manage repositories connected to your Trace organization. These are the sources Trace clones for a whitebox pentest.

tracecli repo list

Lists all repositories in your organization with their connection status, platform, and whether they're included in scanning.

tracecli repo list
FlagShorthandDefaultDescription
--output <format>-otableOutput format: table, json, tsv. Table columns: Repository URL, Platform, Status, Scanning. TSV columns: repositoryUrl, platform, status, githubDefaultBranch, scanningBranch, language, scanning. JSON includes repositoryId and includedInScanning.
--limit <n>-L30Maximum repositories to display per page (max 100).
--page <n>1Page number to display when matching results exceed --limit.
--allShow all matching repositories (disables pagination).
--platform <platform>Filter by platform: GITHUB, GITLAB, BITBUCKET.
--status <status>Filter by status: CONNECTED, DISCONNECTED.
--query <query>Case-insensitive search across URL, repo name, branch, and language.
--includedOnly repositories included in scanning.
--excludedOnly repositories excluded from scanning.
--filter <expression>-fRepeatable advanced filter expression.
--web-wOpen the repositories dashboard in a browser instead of listing.
--no-pagerDisable the interactive pager and print all results at once.

Advanced filter expression syntax:

  • Format: <field><operator><value>
  • Fields: platform, status, url, repo, branch, language, scanning (included or excluded)
  • Operators: = exact, != not exact, : contains, !: not contains
# List all repositories
tracecli repo list

# Filter by platform and status
tracecli repo list --platform GITHUB --status CONNECTED

# Search by name and show only repositories excluded from scanning
tracecli repo list --query payments --excluded

# JSON output for automation (CI: export TRACE_API_KEY)
tracecli repo list --output json | jq '.[].repositoryUrl'

# Advanced repeatable filter expressions
tracecli repo list --filter "platform=GITHUB" --filter "repo:trace" --filter "scanning=included"

# Return every matching repository in one command
tracecli repo list --all

tracecli repo filter

Filter repositories using the same options and behavior as tracecli repo list. Accepts all flags from repo list, including --output, --limit, --filter, and --web.

# Filter by expression
tracecli repo filter --filter "platform=GITHUB" --filter "status=CONNECTED"

# JSON output for automation
tracecli repo filter --output json | jq '.[].repositoryUrl'

tracecli repo include <repository...> and tracecli repo exclude <repository...>

Include repositories in scanning or exclude them from it. Excluded repositories are skipped by every scan (webhook, scheduled, manual, and retest) and left out of your code size until you include them again. The setting is yours and survives provider re-syncs. Requires the analyst or admin role.

Each <repository> is a repository ID (from repo list --output json), a URL, or owner/repo shorthand (expanded to GitHub). Every reference is resolved before anything is written; an unknown reference stops the command with nothing changed.

FlagShorthandDefaultDescription
--output <format>-otabletable prints one line per repository plus a summary. json prints includedInScanning, updatedCount, notFoundRepositoryIds, and the resolved repositories with their previous state.
# Exclude one repository
tracecli repo exclude acme/legacy-api

# Include several repositories at once
tracecli repo include https://github.com/acme/api https://bitbucket.org/acme/worker

# Search first, then exclude everything that matched
tracecli repo list --query legacy --output json | jq -r '.[].repositoryUrl' | xargs tracecli repo exclude

tracecli repo clone <repository> [directory]

Clone a repository by URL or shorthand. When the repository is connected to Trace, a short-lived access token is used automatically: a GitHub App installation token for GitHub repositories, or a vended app token for Bitbucket repositories. Credentials are never stored in the Git remote URL. Repositories on other hosts (or cloned over SSH) fall back to your local Git credentials.

Supported <repository> formats:

  • https://github.com/owner/repo
  • https://bitbucket.org/workspace/repo
  • git@github.com:owner/repo.git
  • owner/repo (expanded to GitHub HTTPS)
FlagShorthandDefaultDescription
--branch <branch>Clone a specific branch.
--depth <depth>Shallow clone depth.
--web-wOpen the repository URL in a browser instead of cloning. SSH remotes are converted to their HTTPS equivalent automatically.
# Clone by owner/repo shorthand
tracecli repo clone securewithtrace/trace

# Clone into a custom directory
tracecli repo clone securewithtrace/trace trace-src

# Clone a specific branch with depth 1
tracecli repo clone securewithtrace/trace --branch main --depth 1

# Clone a connected Bitbucket repository
tracecli repo clone https://bitbucket.org/workspace/repo

upload commands

Upload a source ZIP when the application is not on GitHub, or attach an APK/IPA build to an existing application and download it back later. The group is also available under the code-upload alias.

Uploads require an organization admin (or Trace staff) signed in with a browser session on a pentest-enabled organization. API keys are rejected.

upload create is a code upload: a .zip that becomes an uploaded repository after malware scanning finishes. Link it with upload link. upload build --app is a mobile build attached to an existing application. The two are not interchangeable.

The file is hashed locally, then uploaded in 10 MB parts straight to storage. Interrupted transfers resume from the parts that already landed, as long as you pass the same file (size and SHA-256 must match).

tracecli upload create <file>

Uploads a .zip source archive. Also available as upload source. APK and IPA files are rejected and pointed at upload build --app.

FlagDefaultDescription
--name <displayName>filename without extensionDisplay name (1-200 characters).
--waitBlock until malware scanning finishes (READY, REJECTED, or FAILED).
--output <format>tabletable, json, tsv.
tracecli upload create ./checkout.zip
tracecli upload create ./checkout.zip --name "Checkout" --wait

If the transfer is interrupted, the command prints a upload resume line with the upload id.

tracecli upload build <file> --app <applicationId>

Uploads an .apk or .ipa and attaches it to an existing application. Source ZIPs are rejected and pointed at upload create.

FlagDefaultDescription
--app <applicationId>Application that owns this build (required).
--name <displayName>filename without extensionDisplay name (1-200 characters).
--waitBlock until malware scanning finishes.
--output <format>tabletable, json, tsv.
tracecli upload build ./app-release.apk --app <applicationId>
tracecli upload build ./app.ipa --app <applicationId> --name "iOS build"

tracecli upload list

Lists uploads in the active organization.

FlagDefaultDescription
--kind <kind>Filter: source (code ZIP), apk, or ipa.
--app <applicationId>Filter build uploads for one application.
--output <format>tabletable, json, tsv. TSV columns: codeUploadId, repositoryId, displayName, originalFilename, artifactKind, status, sizeBytes, archiveSha256, malwareScanResult, rejectionReason, applicationId, createdAt, readyAt.
--no-pagerDisable the interactive pager for table output.
--webOpen the source uploads page in a browser.

tracecli upload get <codeUploadId>

Shows one upload by UUID. Accepts --output <format> (-o): table (default), json, tsv.

tracecli upload download <codeUploadId>

Downloads an APK or IPA build back to disk. The build must be READY with a clean malware scan; a build that's still scanning gets an upload wait hint. Source ZIPs can't be downloaded.

The file lands under the name it was uploaded with (path components stripped) in the working directory, or wherever --out points. Bytes stream to a .part sibling first and only move into place once the size and SHA-256 match the upload record, so an interrupted or tampered transfer never leaves a plausible file behind. An existing file at the destination is left alone unless you pass --force.

FlagDefaultDescription
--out <path>working directoryFile to write, or an existing directory to write the original filename into.
--force (-f)Overwrite an existing file.
--output <format>tabletable, json, tsv. JSON and TSV report the saved path, sizeBytes, and archiveSha256.
tracecli upload download <codeUploadId>
tracecli upload download <codeUploadId> --out ./builds/
tracecli upload download <codeUploadId> --out ./release.apk --force

tracecli upload resume <codeUploadId> <file>

Resumes an interrupted upload. <file> must be the same bytes as the original (size and SHA-256). Parts already stored are skipped. Accepts --wait and --output.

tracecli upload resume <codeUploadId> ./checkout.zip

tracecli upload wait <codeUploadId>

Polls until the upload reaches READY, REJECTED, FAILED, or DELETING. Exits 0 only on READY. Accepts --output.

tracecli upload delete <codeUploadId>

Deletes the upload and its stored bytes. Prompts for confirmation interactively; refuses without --yes in non-interactive shells.

Links a ready source ZIP to an application. The upload must be READY with a clean malware scan. APK and IPA builds cannot be linked this way (upload build --app attaches them at upload time).

FlagDefaultDescription
--app <applicationId>Application UUID (required).
--upload <codeUploadId>Upload UUID (required).
--path <repositoryPath>Path within the archive.
--output <format>tabletable, json, tsv.
tracecli upload link --app <applicationId> --upload <codeUploadId>

code-size command

tracecli code-size

Show the billable lines of code across your connected repositories: the same number shown on the integration settings pages, for the active organization (tracecli org current).

Billable SLOC is counted from each repository's current scanning branch, or from the snapshot for uploaded code. Blanks, comments, tests, docs, config and vendored code are excluded, which is why the billable number is roughly half what a plain scc run reports. The "What's counted" table sums exactly to the raw line total, so you can reconcile the two. How counting works covers the rules and how to reproduce them.

tracecli code-size
Code size for acme

  4,256,689 billable SLOC
  of 15,359,962 total lines across 30 measured repositories

What's counted
  Billable code                            4,256,689
  Blank & comment lines in billable files  1,137,136
  Tests                                    2,869,063
  Documentation                              410,265
  Configuration & data                     6,242,480
  Vendored & generated                       444,329

By repository
  acme/platform             490,858
  acme/portal               308,114
  ... 10 more

Repositories connected but not yet measured are named in the summary and left out of the totals, rather than counted as zero.

Options

OptionDescription
-o, --output <format>table (default), json, or tsv
-n, --repos <count>Per-repository rows in table output (default 20; 0 shows every repository)
-w, --webOpen the code size panel in a browser
# Every repository, no collapsing
tracecli code-size --repos 0

# Just the number, for a script
tracecli code-size --output json | jq '.totals.billableSloc'

# Repository and count, tab-separated
tracecli code-size --output tsv | cut -f1,2

pentest commands

Work with penetration tests from the terminal: list the engagements in your organization, fill the optional intake questionnaire, pull findings, update finding status as you remediate, and download the report and letters of attestation once Trace shares them. These operate on the active organization (tracecli org current).

tracecli pentest list

List pentests for your organization, including status, date range, and finding counts.

FlagShorthandDefaultDescription
--status <status>Filter by status: SCOPING, IN_PROGRESS, REMEDIATION, CLOSED.
--limit <n>-L30Maximum results to return (max 100).
--output <format>-otableOutput format: table, json, tsv. TSV columns: displayId, title, status, startedAt, endedAt, findingsTotal.
--web-wOpen the pentests dashboard in a browser instead of listing.
--no-pagerDisable the interactive pager and print all results at once.
# List pentests
tracecli pentest list

# Filter by status
tracecli pentest list --status IN_PROGRESS

# JSON output for scripting
tracecli pentest list --output json | jq '.[].title'

tracecli pentest questionnaire <pentestId>

View or fill the optional customer intake questionnaire for a pentest (identified by display ID like PT-1 or UUID). Answers help Trace scope the engagement. You can edit your answers until testing starts. The form is never required to start a pentest.

FlagShorthandDefaultDescription
--showGET and print current answers using shared customer-facing labels.
--file <path>PUT answers from a JSON file. The file must be the answers object itself (not { "answers": … }); the CLI wraps it for the API. Whole-object replace.
--submitMark the questionnaire as done. You can still edit until testing starts. Combine with --file to upload and submit, or use alone.

Modes

  • --show — print answers (and whether editing is still open).
  • --file <path> — upload a full answers object (overwrite).
  • --submit — mark the questionnaire as done. Combine with --file, or use alone.
  • TTY default (no flags) — load-merge-write: GET existing answers, prompt each question with @clack/prompts (skip / empty keeps the previous value; first-time skip omits the key), confirm, then PUT the merged object. Free-text answers are multi-line: Enter starts a new line and Enter on an empty line finishes the answer; option lists toggle with Space and advance with Enter.
  • Non-TTY without --show / --file / --submit — exits 2 with guidance.

Auth: reads accept a browser session or API key. Writes require an organization admin (or Trace staff) signed in via tracecli auth login — API keys are rejected.

# Print current answers
tracecli pentest questionnaire PT-1 --show

# Upload answers from a file (answers object only)
tracecli pentest questionnaire PT-1 --file answers.json

# Upload and submit
tracecli pentest questionnaire PT-1 --file answers.json --submit

# Submit the current answers
tracecli pentest questionnaire PT-1 --submit

# Interactive fill / edit (TTY)
tracecli pentest questionnaire PT-1

Example answers.json (partial objects are valid — omit keys you are not setting):

{
  "issueClasses": ["AUTHZ_IDOR", "INJECTION"],
  "issueClassesNotes": "Webhook replay worries us too",
  "focusAreas": "Billing API and admin console",
  "surfaces": ["WEB", "PUBLIC_API"],
  "surfacesNotes": "Plus an internal admin console on its own host"
}

Each question also takes free text, so the two option-list questions (issueClasses, surfaces) carry an issueClassesNotes / surfacesNotes companion for anything the options don't cover.

tracecli pentest findings list

List findings for a specific pentest, sorted by severity. The pentest can be identified by display ID (e.g. PT-3) or UUID. Results are filtered client-side and limited to 30 by default.

FlagShorthandDefaultDescription
--pentest <id>Required. Pentest display ID (e.g. PT-3) or UUID.
--severity <severity>Filter by severity: CRITICAL, HIGH, MEDIUM, LOW, INFORMATIONAL.
--status <status>Filter by status: OPEN, IN_PROGRESS, CONTESTED, REMEDIATED, VERIFIED_FIXED, VERIFIED_OPEN, PARTIALLY_FIXED, ACCEPTED_WITH_CONTROLS, DISMISSED.
--limit <n>-L30Maximum results to return (max 100). With --detail, defaults to every finding and is uncapped.
--detailReturn every field, including the full finding write-up. Requires --output json. See Pulling full findings.
--output <format>-otableOutput format: table, json, tsv. TSV columns: severity, status, category, title, cweIds, cvssScore.
--web-wOpen the pentest detail page in a browser (navigates to the specific pentest, not the list).
--no-pagerDisable the interactive pager and print all results at once.
# List findings for a pentest
tracecli pentest findings list --pentest PT-3

# Filter to critical findings only
tracecli pentest findings list --pentest PT-3 --severity CRITICAL

# Show open findings, limit to 20
tracecli pentest findings list --pentest PT-3 --status OPEN --limit 20

# JSON output, pull structured findings into your own tooling
tracecli pentest findings list --pentest PT-3 --output json

# TSV output for awk/cut (severity + title)
tracecli pentest findings list --pentest PT-3 --output tsv | cut -f1,4

Without --detail, every output format returns a summary row per finding: title, severity, category, status, CWE IDs, CVSS vector and score, and the affected repository/file/line references. That is enough to triage, ticket, or chart, but it does not include the finding's write-up. For the finding lifecycle and what each status means, see How an engagement works.

Pulling full findings

--detail returns the same findings with every prose section attached: description, proof of concept, remediation, root cause analysis, impact, attack scenario, severity considerations, and verification. It is the form to use when something other than a person is going to read the findings — a coding agent that fixes them, or your own remediation tooling.

# Every finding for an engagement, full write-up included
tracecli pentest findings list --pentest PT-3 --detail --output json

# Narrow it first — the filters apply the same way
tracecli pentest findings list --pentest PT-3 --detail --output json --severity CRITICAL

# Hand the whole engagement to an agent to work through
tracecli pentest findings list --pentest PT-3 --detail --output json > findings.json

A few things worth knowing:

  • --detail requires --output json. Prose does not survive the table or TSV layouts, so those combinations are rejected rather than silently truncated.
  • Pagination is handled for you. The command walks every page and prints one JSON array, and there is no default cap on the result count — you get the whole engagement unless you pass --limit yourself.
  • A Trace API key works here, so this runs unattended in CI, and --pentest PT-3 works with one — the detail endpoint resolves the display ID itself rather than looking it up first. Findings stay scoped to your organization, and you get the ones published to you.
  • After the agent finishes a fix, mark the finding with status-update (IN_PROGRESS while working, REMEDIATED when it is ready for retest, or ACCEPTED_WITH_CONTROLS with a --note when the risk is accepted instead). An API key can drive those writes once finding automation is enabled for your organization.

tracecli pentest findings get

Fetch one finding with every section attached: description, impact, attack scenario, proof of concept, root cause analysis, remediation, severity considerations, verification, the affected repositories and lines, and the finding's tags when staff have tagged it. The default output is markdown, so the result pastes straight into a coding agent; --output json returns the API response instead.

FlagShorthandDefaultDescription
--pentest <id>Required. Pentest display ID (e.g. PT-3) or UUID.
--finding <id>Required. Finding number (PTF-7 or 7) or UUID.
--output <format>-otextOutput format: text (markdown), json.
# One finding as markdown
tracecli pentest findings get --pentest PT-3 --finding PTF-7

# Save it for an agent to work from
tracecli pentest findings get --pentest PT-3 --finding PTF-7 > finding.md

# The raw API response
tracecli pentest findings get --pentest PT-3 --finding 7 --output json

The terminal icon in a finding's header on the dashboard copies this command pre-filled; the one in the pentest header shows the install command and the --detail pull. A Trace API key works here, the same as for --detail.

When Trace confirmed the finding with a script, the markdown has a "Reproduce it" part after the proof of concept, with the repro command for that finding.

tracecli pentest findings repro

Print the bash script Trace ran to confirm a finding: the same file the finding's Reproduce tab downloads. Run it to see the issue, then again after your fix. It asks for the base URL and the test-account logins, or reads them from the environment, so it also runs in CI. The last line is REPRODUCED (exit 1) while the issue is there, NOT REPRODUCED (exit 0) once it's fixed, and INCONCLUSIVE (exit 2) when the script couldn't tell. It needs bash and curl, and jq for most findings.

FlagShorthandDefaultDescription
--pentest <id>Required. Pentest display ID (e.g. PT-3) or UUID.
--finding <id>Required. Finding number (PTF-7 or 7) or UUID.
tracecli pentest findings repro --pentest PT-3 --finding PTF-7 > repro.sh
bash repro.sh

Only findings with a Reproduce tab have a script; the others print an error and exit 1. A Trace API key works here.

tracecli pentest findings status-update

Move a published finding to IN_PROGRESS, REMEDIATED, or ACCEPTED_WITH_CONTROLS — the same customer transitions as the dashboard, so an agent that pulled findings with --detail can mark them as it works. Leave a finding IN_PROGRESS (and skip REMEDIATED) to keep it out of the retest queue. ACCEPTED_WITH_CONTROLS closes the finding as an accepted risk with no Trace review; the --note is its rationale and lands in the finding's history and the report.

FlagShorthandDefaultDescription
--pentest <id>Required. Pentest display ID (e.g. PT-3) or UUID.
--finding <id>Required. Finding number (e.g. PTF-7) or UUID.
--status <status>Required. IN_PROGRESS (start work), REMEDIATED (ready for retest), or ACCEPTED_WITH_CONTROLS (accept the risk; ACCEPTED and ACCEPT are accepted spellings). Hyphen and space spellings (in-progress) are accepted.
--note <text>Optional context when reporting remediation; required rationale when accepting. Not valid with IN_PROGRESS.
--output <format>-otextOutput format: text, json.

IN_PROGRESS is allowed from OPEN, VERIFIED_OPEN, or PARTIALLY_FIXED. REMEDIATED and ACCEPTED_WITH_CONTROLS are allowed from OPEN, IN_PROGRESS, VERIFIED_OPEN, or PARTIALLY_FIXED; an accept is refused while the finding has a dispute under review. The identifiers are sent as typed — the API resolves PT-3 / PTF-7 itself.

Auth: a browser session attributes the change to you. A Trace API key works once Trace enables finding automation for your organization, and the CLI routes key traffic to a separate automation endpoint. Key-driven changes are recorded as api-key:<key name> and appear as yours (not Trace's) in the finding's history, and the key's REMEDIATED is a claim like any other: only a Trace retest can mark a finding verified fixed.

# Agent starts a fix
tracecli pentest findings status-update --pentest PT-3 --finding 7 --status IN_PROGRESS

# Fix is ready for Trace to re-test
tracecli pentest findings status-update --pentest PT-3 --finding PTF-7 --status REMEDIATED

# Same, with a note, machine-readable
tracecli pentest findings status-update --pentest PT-3 --finding 7 --status REMEDIATED \
  --note "Fixed in PR 412" --output json

# Accept the risk; the note is required and becomes the recorded rationale
tracecli pentest findings status-update --pentest PT-3 --finding 7 --status ACCEPTED \
  --note "Internal-only endpoint behind SSO; residual risk accepted"

tracecli pentest findings attach-evidence

Attach a screenshot, screen recording, HTTP transcript, HAR, or data export to a finding — for proof captured by hand rather than by an agent. Trace staff only.

The file uploads directly to storage rather than through the API, so recordings of any reasonable size work. The exhibit kind and content type are derived from the file extension.

FlagShorthandDefaultDescription
--pentest <id>Required. Pentest display ID (e.g. PT-3) or UUID.
--finding <id>Required. Finding number (e.g. PTF-7) or UUID. Unpublished findings have no number yet — use the UUID.
--file <path>Required. Path to the evidence file.
--caption <text>What the exhibit shows. Rendered as its label in the dashboard and the report.
--section <section>Report section it backs: description, rootCauseAnalysis, impact, attackScenario, severityConsiderations, proofOfConcept, remediation, verification.
--kind <kind>Override the derived exhibit kind (SCREENSHOT, HAR, HTTP_TRANSCRIPT, POC_FILE, COOKIE_JAR, AGENT_TRANSCRIPT, DATA_EXPORT, VIDEO, OTHER).
--customer-facingPublish the exhibit to the customer. Rejected for HAR and video.
--output <format>-otextOutput format: text, json.
# Attach a screenshot as internal working material
tracecli pentest findings attach-evidence --pentest PT-3 --finding 7 --file ./poc.png

# Attach a screen recording with a caption, placed under Proof of Concept
tracecli pentest findings attach-evidence --pentest PT-3 --finding PTF-7 --file ./poc.mov \
  --caption "Cookie survives logout, replayed 40s later" --section proofOfConcept

# Attach a data export and publish it to the customer
tracecli pentest findings attach-evidence --pentest PT-3 --finding 7 --file ./roster.json \
  --caption "Full member roster returned to a non-member" --customer-facing

New exhibits are staff-internal unless --customer-facing is passed, and they append after the finding's existing evidence. HAR captures and video are always staff-internal at attach — a HAR can carry a live session token, and a recording needs a redaction pass — so publish a video with the toggle in the staff console's evidence panel after reviewing it. Evidence can only be attached while the pentest is open; reopen a closed one first.

tracecli pentest report download <pentestId>

Downloads the pentest report Trace has shared with your organization: the issued version when one exists, otherwise the current shared draft. The pentest can be identified by display ID (e.g. PT-3) or UUID. Until Trace publishes a report to your dashboard, the command exits with a message saying so.

The file lands in the working directory (or wherever --out points) under the report's document ID, for example TR-PT-2026-03-ACME.pdf. Bytes stream to a .part sibling first and only move into place once the transfer ends at the length storage declared, so an interrupted download never leaves a plausible file behind. An existing file at the destination is left alone unless you pass --force.

Organizations on a partner report template receive a .zip carrying the PDF, the Word document, the markdown report, and the evidence files, the same package the dashboard's Download button hands over. --docx fetches the Word document on its own; it's a clear error when your report doesn't ship one.

An engagement that covers several applications can come with a report for one or more of them beside the full report, each with its own document ID (for example TR-PT-2026-03-ACME-MOBILE.pdf). Without --report you get the full report. --report "Acme Mobile" downloads the report for that application: a report named exactly after it wins, otherwise the one report that covers it. A name that matches no report, or several, exits with the reports you can download and the ID for each, which --report also takes.

Auth: a browser session from tracecli auth login or a Trace API key (TRACE_API_KEY). A key makes this usable from CI, for filing deliverables with a vendor or into a compliance folder on a schedule.

FlagShorthandDefaultDescription
--report <id|application>the full reportA report for some of the engagement's applications, by application name or report ID.
--out <path>working directoryFile to write, or an existing directory to write the document ID filename into.
--force-fOverwrite an existing file.
--docxDownload the Word document instead of the PDF (partner templates only).
--output <format>-otabletable, json, tsv. JSON and TSV report the saved path, sizeBytes, the artifact, and the report metadata.
tracecli pentest report download PT-3
tracecli pentest report download PT-3 --report "Acme Mobile"
tracecli pentest report download PT-3 --out ./reports/
tracecli pentest report download PT-3 --out ./acme-q3.pdf --force
tracecli pentest report download PT-3 --docx
tracecli pentest report download PT-3 --output json | jq -r '.path'

tracecli pentest attestation list <pentestId>

Lists the letters of attestation Trace has shared for a pentest, newest first, with each letter's document ID, version, classification, issue date, finding counts, and UUID. The group is also available under the loa alias.

Auth: a browser session from tracecli auth login or a Trace API key (TRACE_API_KEY).

FlagShorthandDefaultDescription
--output <format>-otabletable, json, tsv. TSV columns: attestationId, documentId, version, classification, issuedDate, totalFindings, fileSizeBytes, createdAt.
--no-pagerDisable the interactive pager and print all results at once.
tracecli pentest attestation list PT-3
tracecli pentest loa list PT-3 --output json | jq -r '.[0].attestationId'

tracecli pentest attestation download <pentestId>

Downloads a letter of attestation. Without --attestation it takes the newest letter shared for the pentest and tells you when older ones exist. The file is named after the letter's document ID, for example TR-LOA-2026-03-ACME-1A2B3C.pdf, and follows the same .part staging and --force rules as report download.

Auth: a browser session from tracecli auth login or a Trace API key (TRACE_API_KEY). Same as report download, so a CI job can pull the letter without a person in the loop.

FlagShorthandDefaultDescription
--attestation <id>newest letterAttestation UUID from pentest attestation list.
--out <path>working directoryFile to write, or an existing directory to write the document ID filename into.
--force-fOverwrite an existing file.
--output <format>-otabletable, json, tsv. JSON and TSV report the saved path, sizeBytes, and the letter metadata.
tracecli pentest attestation download PT-3
tracecli pentest attestation download PT-3 --out ./compliance/
tracecli pentest attestation download PT-3 --attestation <attestationId> --out ./loa.pdf --force
tracecli pentest loa download PT-3 --output json | jq -r '.path'

upgrade command

Check for new versions and upgrade tracecli in one step.

The command supports both:

  • tracecli upgrade (recommended)
  • tracecli self-update (alias)
FlagShorthandDescription
--checkCheck for updates without installing.
--no-confirmSkip interactive confirmation prompt (for CI/scripts).
--yes-ySkip interactive confirmation prompt (alias: --no-confirm).
# Check if an update is available
tracecli upgrade --check

# Upgrade to latest version
tracecli upgrade

# Non-interactive upgrade (CI/scripts)
tracecli upgrade --no-confirm

When a newer version is available, tracecli also shows a lightweight upgrade notice in interactive terminals.

completion command

Generate and install shell completion scripts.

tracecli completion --shell bash
tracecli completion --shell zsh
tracecli completion --shell fish

If --shell is omitted, tracecli auto-detects from the SHELL environment variable.

Generated files are written under ~/.trace/:

ShellFile
Bash~/.trace/tracecli-completion.bash
Zsh~/.trace/_tracecli
Fish~/.trace/tracecli-completion.fish

Each shell requires a one-time setup line added to your shell config. tracecli completion --shell <shell> prints the exact instructions after writing the file.