npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@cantinasecurity/apex-cli

v0.1.28

Published

Standalone CLI and MCP server for Apex.

Readme

Apex CLI

Standalone CLI client for Apex.

Installing And Updating

For a public install, use a global package manager install:

npm install -g @cantinasecurity/apex-cli
# or: pnpm add -g @cantinasecurity/apex-cli

Then run:

apex setup

apex setup is the lowest-friction path for agent clients. It:

  • registers Apex as an MCP server in any installed Codex CLI, Claude Code, and GitHub Copilot CLI clients
  • installs the Codex skill into $CODEX_HOME/skills/apex-cli
  • installs the Claude project skill into .claude/skills/apex-cli in the current repository
  • installs the GitHub Copilot CLI skill into $COPILOT_HOME/skills/apex-cli or ~/.copilot/skills/apex-cli

If you only want one client, run:

apex setup codex
apex setup claude
apex setup copilot

If one client is not installed yet, apex setup skips it automatically. If you target a client explicitly, its CLI must already be installed.

Update a global install with:

apex update

You can also update directly with your package manager:

npm install -g @cantinasecurity/apex-cli
# or: pnpm add -g @cantinasecurity/apex-cli

If you are running Apex CLI from a local checkout instead, update it with:

git pull --ff-only
pnpm install

For published installs, setup-managed MCP registrations launch the current npm release, so restarting the client picks up the current server instead of keeping an old global apex-mcp process indefinitely. Re-run apex setup after upgrading to refresh copied skill files, and run apex setup claude in each repository where you want the Claude project skill.

Restart any already-running MCP client after an Apex CLI upgrade before using trial redemption or claim. A process that loaded an older credential writer cannot adopt the new merge and generation-safety rules until it restarts.

When apex is run in an interactive terminal, it checks for updates periodically and offers to install them.

Local Development

  1. Install dependencies:
pnpm install
  1. Run the CLI:
pnpm apex

By default, the CLI targets https://ai.cantina.xyz/.

Use APEX_BASE_URL only when targeting a non-default Apex host. For on-prem deployments, set it to the same external HTTPS Bedrock origin configured as ONPREM_PUBLIC_BASE_URL; browser handoffs such as apex connect github and apex-connect-provider need that public origin for GitHub callback and success redirects.

APEX_BASE_URL=https://bedrock.customer.example pnpm apex

Try Apex With A Trial Code

A Cantina-issued trial code can start a temporary guest scan without a Cantina account, browser, or device login. Redeem it from the repository root, run the normal scan lifecycle, and create a Cantina account only after reviewing the findings:

apex redeem SPBT-DEVREL-XXXXXXXX --json
apex scan --non-interactive --json
apex status --json
apex findings --json
apex claim

apex redeem never opens a browser. It saves a machine-local onboarding fingerprint before the first request, exchanges the code for a seven-day guest session, and stores the single-use claim proof only in the mode-0600 Apex credentials file. A one-way code hash distinguishes safe same-code retries without retaining the trial code. apex claim is the one onboarding command that may open a browser; it creates or signs into a Cantina account, then moves the guest workspace, scans, and findings into the currently selected Cantina workspace when that account can run scans there. Personal workspace owners receive the trial in their existing workspace instead of getting a duplicate. Run it on the same machine within 30 days. Unclaimed guest data is retained only for the limited period disclosed during redemption and is then queued for deletion. If the selected Cantina workspace cannot run scans, switch to one that can and retry before the claim deadline. Trial redemption, claim, and revocation are hosted-only and fail before sending any onboarding secret when APEX_BASE_URL is not https://ai.cantina.xyz.

If the local claim proof is lost while the seven-day guest session is still active, run apex redeem <the-same-code> again on the same machine to rotate the guest credentials and re-mint the claim proof over the authenticated guest channel. After the guest session expires, Apex cannot safely recover a lost claim proof from the public trial code and machine fingerprint alone.

If the current credentials already belong to a real account, apex redeem exits with code 2 and outcome: "already_authenticated"; it never silently spends that account's credits. Re-redeeming the same code on the same machine is idempotent while the guest session remains active. A different active trial requires the explicit --replace flag, which revokes the outgoing guest session before redeeming the new code.

Guest standard scans validate the complete local archive before resolving or reserving a workspace. apex doctor is read-only for guest sessions. For an unbound renamed checkout, Apex may recover only the sole empty guest workspace when no explicit workspace name was supplied; it will not silently switch an explicit workspace selection or reuse a workspace that already contains scan history.

Logging out of an active guest trial, or discarding a proof-only trial stub, requires explicit confirmation (apex logout --force in non-interactive flows). Apex first attempts a proof-bound server revoke; an explicitly confirmed logout may discard a stale local proof when the server can no longer verify it. Logging out of a separately authenticated account preserves any unclaimed local trial proof so apex claim can still use it.

Agent-safe copy/paste prompt (substitute the issued code):

Install and run Cantina Apex CLI 0.1.28 to start one free standard security scan of this repository immediately.

Use this trial code only where <TRIAL_CODE> appears below: SPBT-DEVREL-XXXXXXXX

Run the commands yourself from the repository root; do not stop after setup or only explain the steps. Use terminal CLI commands only. Do not use an Apex MCP tool or run `apex setup`, `apex mcp`, `apex login`, `apex-auth-start`, or `apex-auth-wait`. Never use `--replace` or `--force`.

Use this exact command prefix for every Apex command:
  npx -y -p @cantinasecurity/[email protected] apex

1. Before redeeming, confirm every command will use the same persistent, user-accessible machine or container, HOME, filesystem, and repository root. Confirm Node.js 20+ and npx are available. If `APEX_BASE_URL` is set, continue only when its origin is `https://ai.cantina.xyz`. Run the exact prefix with `--help` and continue only if help lists both `redeem` and `claim`. If any check fails, STOP before sending the code; do not install system packages.
2. Redeem, with at most one response-loss recovery retry:
     npx -y -p @cantinasecurity/[email protected] apex redeem <TRIAL_CODE> --json
   This terminal command is the only allowed tool call containing the code. Never echo or restate the code, store it in a file or environment variable, put it in a URL or MCP call, or include it in your response. Parse the JSON from stdout only; do not merge stderr into stdout, because npm may write warnings to stderr. Continue when the command exits 0 and stdout is JSON with `redeemed: true` and `outcome` equal to `redeemed` or `idempotent`. `idempotent` means the existing guest session resumed and it may already own a workspace. If and only if the first attempt ends with an ambiguous transport/connection failure or an interrupted/missing response and no typed server error code, retry this exact same command once on the same machine, HOME, and repository root. Never retry a typed server rejection and never make more than one recovery retry. If the allowed retry does not return a successful JSON outcome, STOP.
3. Immediately start exactly one scan; do not wait for another instruction:
     npx -y -p @cantinasecurity/[email protected] apex scan --mode standard --non-interactive --no-open --json
   The CLI validates the complete guest local archive before it reserves a workspace. An unbound renamed checkout may recover only the sole empty guest workspace when no explicit workspace name was supplied. On any error or nonzero exit, STOP. After a successful scan JSON response, inspect `localPersistence.workspaceBindingSaved`. If it is `false`, the server scan already started: capture and report `binding.lastScanId`, then STOP; do not run status or findings until local repository permissions are repaired. Otherwise capture `binding.lastScanId` from the JSON as <SCAN_ID>; if it is absent, STOP.
4. About every 60 seconds, poll that exact scan:
     npx -y -p @cantinasecurity/[email protected] apex status --scan <SCAN_ID> --json
   Read `progress.progress.status`. Wait while it is `created`, `pending`, `queued`, `starting`, `running`, `in_progress`, or `processing`. Continue on `completed`. STOP on `failed`, `cancelled`, a missing or unknown status, or a command failure.
5. Fetch that exact scan's findings:
     npx -y -p @cantinasecurity/[email protected] apex findings --scan <SCAN_ID> --json
   On success, summarize findings by severity, most severe first, including identifier, title, status, and confidence. This command does not return file locations, so do not invent them. On failure, STOP.
6. Do not claim automatically. Tell me the claim deadline from step 2 and remind me to run this exact command myself from the same repository root, machine, and HOME:
     npx -y -p @cantinasecurity/[email protected] apex claim
   It may open a browser so I can create or sign in to a Cantina account and keep the results. Claim moves the trial into the currently selected Cantina workspace when I can run scans there, or into my existing personal workspace. If the selected workspace cannot run scans, tell me to switch to one that can and retry before the claim deadline.

Never paste raw command transcripts. For any failure, report only the step, exit code, and sanitized error. Redact the trial code and every `apex_at_`, `apex_rt_`, or `apex_ct_` value from all reports.

Trial codes and claim tokens must never be logged, telemetered, printed in JSON output, placed in URLs, or sent through MCP tool calls. The MCP server does not expose redemption or claim tools. After terminal redemption, its read-only apex-trial-status tool can report local guest and claim deadlines without returning either secret.

Interactive Shell

Bare apex opens the interactive shell:

$ apex

Apex CLI
Connected to https://ai.cantina.xyz/
Type /scan to start a scan for this directory, /workspaces to browse workspace names, /workspace use "<name>" to switch, /help for commands.
apex>

In interactive terminals, Apex now shows a loading indicator while it resolves workspaces, loads scans, and starts commands.

If Apex asks for a workspace name, that is the Apex workspace name for the current directory. Press Enter to accept the current folder name, or pass --workspace-name <name> explicitly.

Supported shell commands:

  • /credits
  • /scan [standard|audit|lite]
  • /scan pr <pr-number>
  • /scans
  • /findings [scan-id]
  • /findings workspace [filter...]
  • /findings comment <finding-id|finding-identifier> <comment>
  • /findings feedback <finding-id|finding-identifier> valid [comment]
  • /findings feedback <finding-id|finding-identifier> invalid <false-positive|by-design|not-relevant> [comment]
  • /findings fix-review <finding-id|finding-identifier>
  • /export [scan-id]
  • /workspaces
  • /cancel-scan [scan-id]
  • /status [scan-id]
  • /doctor
  • /update
  • /claim
  • /logout
  • /repos
  • /workspace
  • /workspace use <workspace-name|workspace-prefix|workspace-id>
  • /workspace name <name>
  • /company [id|handle]
  • /connect github
  • /connect gitlab
  • /open
  • /clear
  • /help
  • /exit

/workspace use accepts a workspace name, prefix, or ID. Quote workspace names that contain spaces, for example /workspace use "Core Platform".

Scripted Commands

  • apex credits
  • apex scan
  • apex scan --mode lite
  • apex scan --mode pr --pr <number> [--pr <number>] [--pr-path <path>]
  • apex scans
  • apex findings [--scan <scan-id>]
  • apex findings --workspace [--company <handle>] [--workspace-ref <name|prefix|id>] [--finding-state all|open] [--filter <[!]facet:value>]
  • apex findings comment <finding-id|finding-identifier> --content <markdown> [--parent-comment <comment-id>] [--scan <scan-id>]
  • apex findings feedback <finding-id|finding-identifier> <valid|invalid> [comment] [--comment <markdown>] [--scan <scan-id>] [--suggested-severity extreme|critical|high|medium|low|informational] [--dismissal-reason false-positive|by-design|not-relevant] [--label acknowledged|fixed] [--fix-pr-url <github-pr-url>]
  • apex findings fix-review <finding-id|finding-identifier> [--scan <scan-id>] [--review-target pull-request|repository-current] [--fix-pr-url <github-pr-url>]
  • apex export findings [--scan <scan-id>] [--format markdown|json|gitlab-sast] [--output <path>]
  • apex workspaces
  • apex workspace
  • apex workspace use <workspace-name|workspace-prefix|workspace-id>
  • apex cancel-scan [scan-id]
  • apex status [--scan <scan-id>]
  • apex doctor
  • apex login
  • apex redeem <code> [--json] [--replace]
  • apex claim [--json] [--no-open]
  • apex logout
  • apex service-key create --name <name> [--company <id-or-handle>] [--scope <scope[,scope]>] [--expires-at <ISO-8601>] [--json]
  • apex service-key list [--company <id-or-handle>] [--json]
  • apex service-key revoke <key-id> [--company <id-or-handle>] [--json]
  • apex setup [all|codex|claude|copilot]
  • apex telemetry [status|enable|disable]
  • apex update
  • apex connect github
  • apex connect gitlab

--workspace-ref is scoped to apex findings --workspace. For apex scans or apex export findings, bind the intended workspace first with apex workspace use <name|prefix|id>; unsupported or unknown flags fail instead of falling back to the local binding.

Helpful workspace flags:

  • --company <id-or-handle> to choose the Apex company when more than one is available
  • --workspace-name <name> to set the Apex workspace name for this directory

apex credits shows standard, audit, fix review, and Lite scan entitlements when the server returns them.

Service Keys, Hosted MCP, And The REST API

Use hosted MCP for production agents that need a normal HTTPS endpoint. Use the REST API for explicit HTTP/JSON integrations such as serverless functions, cron jobs, and internal audit hubs. Use the CLI or local stdio MCP server when an agent needs direct access to a repository checkout or local archive. The complete hosted integration contract is in the Apex API documentation.

An organization manager can create a service key with an existing Apex device-login session. Service-key commands never start device login implicitly, so run apex login first if needed:

apex service-key create \
  --name internal-audit-hub \
  --scope scans:create,scans:read,findings:read \
  --expires-at 2027-01-01T00:00:00Z

The CLI automatically uses your company when only one is available. If you belong to multiple companies, it prompts you to choose one. Pass --company <id-or-handle> to skip that prompt, or when a non-interactive or --json command cannot prompt.

The secret is returned only by create and cannot be retrieved later. Store it directly in a secret manager and do not put it in source control, prompts, chat messages, or logs. --json also includes the shown-once secret so it can be captured programmatically; handle that output as a credential.

Service keys are organization-level credentials. Grant only the scopes the integration needs: scans:create reads credit availability and triggers scans, scans:read polls status, and findings:read retrieves findings. Omit --scope to grant all three scopes. For a P1-only adapter that reads manually started scans, create a read-only key with --scope scans:read,findings:read.

A key with findings:read can retrieve unpublished draft findings for scans in its organization so an external hub can perform triage. Give the key only to systems that are allowed to handle those drafts.

List metadata or revoke a key without exposing its secret:

apex service-key list
apex service-key revoke <key-id>

Service-key management is intentionally available only through the scripted CLI. It is not exposed as an MCP tool or interactive-shell command, which keeps raw secrets out of model tool results and transcripts. The CLI requires an existing device-login bearer session, never initiates login from these commands, and never stores a created service key locally.

APEX_SERVICE_KEY authenticates hosted MCP and REST requests; it does not authenticate the local CLI or stdio MCP and does not replace apex login there. When apex doctor finds a service key but no active local device-login session, it reports that split before starting a login flow. APEX_API_KEY is also recognized for this diagnostic so older integrations receive migration guidance, but APEX_SERVICE_KEY is the documented hosted-integration variable.

Hosted HTTPS MCP

Point any Streamable HTTP MCP client at https://ai.cantina.xyz/mcp and send the service key as Authorization: Bearer <TOKEN>. No local apex-mcp process, browser, TTY, or device-login session is required.

Keep the key in the environment. For Codex:

export APEX_SERVICE_KEY='<service-key>'
codex mcp add apex \
  --url https://ai.cantina.xyz/mcp \
  --bearer-token-env-var APEX_SERVICE_KEY

Claude Code can expand the same environment variable from .mcp.json:

{
  "mcpServers": {
    "apex": {
      "type": "http",
      "url": "https://ai.cantina.xyz/mcp",
      "headers": {
        "Authorization": "Bearer ${APEX_SERVICE_KEY}"
      }
    }
  }
}

The hosted server exposes apex-credits, apex-workspaces, apex-scan, apex-status, apex-cancel-scan, apex-findings, and apex-workspace-findings. It operates only on repositories and workspaces available to the service key's organization. Use local stdio MCP for device auth, local filesystem/archive access, provider connection, setup, comments, feedback, fix reviews, and trial flows.

Hosted REST API

Use the service key as a bearer token with the hosted scan lifecycle:

curl \
  -H "Authorization: Bearer $APEX_SERVICE_KEY" \
  https://ai.cantina.xyz/api/apex/v1/credits

curl -X POST https://ai.cantina.xyz/api/apex/v1/scans \
  -H "Authorization: Bearer $APEX_SERVICE_KEY" \
  -H "Idempotency-Key: $APEX_IDEMPOTENCY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "repoUrl": "https://github.com/acme/example.git",
    "commit": "0123456789abcdef0123456789abcdef01234567",
    "paths": ["services/payments"]
  }'

curl \
  -H "Authorization: Bearer $APEX_SERVICE_KEY" \
  https://ai.cantina.xyz/api/apex/v1/scans/$SCAN_ID

curl \
  -H "Authorization: Bearer $APEX_SERVICE_KEY" \
  https://ai.cantina.xyz/api/apex/v1/scans/$SCAN_ID/findings

For a remote GitHub scan, the repository must be connected to the service key's Apex organization. Apex reuses an active linked workspace when one exists; if none exists, the request creates and links a workspace named after the canonical repository before the scan starts. Pass workspaceId to disambiguate multiple matches. An explicit workspace/repository mismatch returns HTTP 409 instead of silently rewriting that workspace.

For a local or non-Git checkout, use the service API's source-upload flow instead. It can create or reuse a workspace, uploads a tar.gz archive, and starts the scan with a local_archive source. A newly created local workspace has no threat model to reuse, so its first scan must send generateThreatModel: true. See the Apex service API guide for the current request schemas and limits.

The optional paths array is a set of best-effort focus hints, not a hard repository boundary. Apex may inspect or report code outside those paths. Version one does not yet provide strict path isolation.

Every trigger request requires an Idempotency-Key. Generate one stable key for each intended scan and reuse that same key with the identical request body when retrying after a transport error, timeout, or 5xx. Idempotency is organization-scoped, so a retry remains safe if the service key is rotated between attempts. A definitive 4xx response is retained; after correcting its precondition, submit the request with a new key. Use a new key for every genuinely new scan. The trigger returns a scanId; poll the scan resource until it reaches a terminal status, then fetch findings. The findings response uses the GitLab SAST JSON shape, including unpublished drafts, finding IDs that remain stable when the same scan is re-fetched, titles, descriptions, severities, and source locations when available.

Example prompt for Claude Code:

Build an Apex adapter for our serverless audit hub using the hosted REST API, not the Apex CLI or local stdio MCP server. Read APEX_SERVICE_KEY from the environment, generate one stable Idempotency-Key per intended scan, and reuse it with the identical request body only after a transport error, timeout, or 5xx; after correcting a definitive 4xx, use a new key. POST the connected GitHub repository URL and exact commit to /api/apex/v1/scans, include workspaceId when needed to disambiguate matches, and handle a 409 workspace-resolution response. Treat optional paths as non-binding focus hints, not a security boundary. Poll /api/apex/v1/scans/{scanId} until terminal, then fetch /api/apex/v1/scans/{scanId}/findings. Preserve the raw GitLab SAST payload, including drafts, and deduplicate findings by stable ID. Never print or log the service key.

Example prompt for Codex:

Add Apex to this headless auditor integration using the hosted REST API. Use bearer auth from APEX_SERVICE_KEY; do not shell out to apex or start a local stdio MCP process. Implement scan trigger, 409 workspace-resolution handling, status polling with bounded backoff, terminal failure handling, and findings retrieval. Send the connected GitHub repoUrl, exact commit, optional paths, and optional workspaceId; treat paths as non-binding focus hints rather than a hard security boundary. Generate a stable Idempotency-Key for each intended scan. Preserve it only for an identical transport/timeout/5xx retry; after correcting a definitive 4xx, submit with a new key. Keep the returned scanId, and store the unmodified findings payload, including drafts, alongside normalized findings. Add tests with mocked HTTP responses and ensure credentials are redacted from errors and logs.

For a P1-only integration where scans are started in the Apex UI:

Given an Apex scanId, fetch /api/apex/v1/scans/{scanId}/findings with APEX_SERVICE_KEY, save the GitLab SAST JSON unchanged, and import each finding once using its stable ID. Do not trigger a new scan and never log the bearer token.

Finding Review Feedback

Finding review collaboration now has explicit write commands:

  • apex findings comment <finding-id|finding-identifier> --content "Needs auth check"
  • apex findings feedback <finding-id|finding-identifier> valid --comment "Reproduced on latest build"
  • apex findings feedback <finding-id|finding-identifier> invalid --dismissal-reason false-positive --comment "This path is unreachable"
  • apex findings feedback <finding-id|finding-identifier> valid --label fixed --fix-pr-url https://github.com/acme/app/pull/123 --comment "Fixed in PR #123"
  • apex findings fix-review <finding-id|finding-identifier>
  • /findings comment <finding-ref> <comment>
  • /findings feedback <finding-ref> valid [comment]
  • /findings feedback <finding-ref> invalid <false-positive|by-design|not-relevant> [comment]
  • /findings fix-review <finding-ref>

Identifiers such as KERN2-25 are resolved against the selected or latest scan for the current workspace binding. Pass --scan <scan-id> when you need a specific scan, or pass the finding UUID directly to skip workspace-based resolution.

Finding comments, valid/invalid feedback, and fix review scan starts use the same Apex login credentials as read commands. In MCP clients, call apex-auth-start, then pass both its returned deviceCode and opaque credentialGeneration to apex-auth-wait to authenticate these write tools safely.

Never copy a browser cookie or set CANTINA_AUTH_TOKEN for these tools. If an MCP server asks for that variable, it is an outdated pre-device-auth server. Update Apex CLI, re-run apex setup <client>, restart the client, and retry.

Invalid feedback requires a dismissal reason. Valid feedback can include --suggested-severity extreme|critical|high|medium|low|informational.

Fix review scans can review either a Fix PR or the current repository state:

  1. For PR-based reviews, either save fixed feedback on the finding with --label fixed and one or more --fix-pr-url values, or pass --fix-pr-url directly to apex findings fix-review.
  2. For current-repository reviews, run apex findings fix-review <finding-id|finding-identifier> without Fix PR URLs. Bedrock must have original scan repository context for the finding.

The matching MCP flow is apex-finding-fix-review with optional fixPrUrls. Agents that need to record fixed feedback first can still call apex-finding-feedback with status: "valid", labels: ["fixed"], and fixPrUrls, then call apex-finding-fix-review.

The matching CLI and MCP flows intentionally use the same device-login session so agents should not ask users to paste browser cookies or auth tokens.

Local Source Scans

apex scan now works against any local source root you point it at. By default, that source root is the current working directory:

  • clean GitHub or GitLab checkouts can stay on the remote-materialization path
  • dirty git worktrees fall back to a local snapshot upload by default
  • plain directories that are not git repositories are scanned through a local snapshot upload

Useful flags:

  • --repo <path> to scan one or more explicit local roots instead of the current directory
  • --source-mode auto|remote|local to control remote-first fallback behavior
  • --mode standard|audit|lite|pr to choose the scan mode
  • --pr <number> to select one or more GitHub pull requests for --mode pr
  • --pr <number:path,path> or --pr-path <path> to limit a PR scan to changed paths

auto is the default. remote requires Apex to materialize from a remote repository. local forces a local snapshot upload even when a clean remote path is available.

Audit scans use audit as the scan mode and still require provider-backed GitHub or GitLab repositories that Apex can materialize remotely without a local snapshot fallback. ultra remains accepted as a backwards-compatible alias.

Lite scans use lite as the scan mode and require the Lite Scan beta feature plus provider-backed GitHub or GitLab repositories that Apex can materialize remotely. Local snapshot uploads are not supported for Lite scans.

PR scans require exactly one provider-backed GitHub repository. If the current directory resolves to multiple sources, pass --repo <path> to select the one that contains the pull request.

LLM / MCP Usage

Apex has two MCP transports:

  • Hosted Streamable HTTP at https://ai.cantina.xyz/mcp, authenticated with an organization service key, for production agents that do not need the caller's filesystem.
  • The apex-mcp stdio server shipped by this package, authenticated with device login, for repository-local and interactive agent workflows.

See Hosted HTTPS MCP for the production URL and Bearer-token configuration. The rest of this section configures the local stdio server.

If Apex is installed globally, prefer:

apex setup

That registers Apex for installed Codex CLI, Claude Code, and GitHub Copilot CLI clients automatically. Codex and Claude registrations also set APEX_MCP_CLIENT and APEX_CLIENT_INTEGRATION so Apex can distinguish agent-driven MCP usage from direct CLI usage.

If you want to wire clients manually instead, Apex ships a stable apex-mcp binary. For Codex:

codex mcp add apex \
  --env APEX_MCP_CLIENT=codex \
  --env APEX_CLIENT_INTEGRATION=codex \
  -- apex-mcp

For Claude Code:

claude mcp add apex \
  --scope user \
  -e APEX_MCP_CLIENT=claude \
  -e APEX_CLIENT_INTEGRATION=claude \
  -- apex-mcp

apex setup claude uses Claude's name-first stdio command syntax and checks whether the installed Claude CLI supports --scope user. If a Claude build omits that option or advertises it but rejects it at runtime, setup safely merges the same user-level mcpServers.apex entry into ~/.claude.json without replacing other settings or servers.

For GitHub Copilot CLI:

copilot mcp add apex --tools "*" -- apex-mcp

The command after -- selects the local stdio transport; no version-specific transport flag is needed.

For any other MCP client, configure it to launch:

{
  "mcpServers": {
    "apex": {
      "command": "apex-mcp",
      "env": {
        "APEX_MCP_CLIENT": "custom-mcp-client",
        "APEX_CLIENT_INTEGRATION": "custom-mcp-client"
      }
    }
  }
}

From a local checkout during development, prefer the repo-local binary so the MCP stream stays clean:

{
  "mcpServers": {
    "apex": {
      "command": "/path/to/apex-cli/bin/apex-mcp",
      "env": {
        "APEX_MCP_CLIENT": "local-dev",
        "APEX_CLIENT_INTEGRATION": "local-dev"
      }
    }
  }
}

If you need to launch through pnpm, use --silent:

{
  "mcpServers": {
    "apex": {
      "command": "pnpm",
      "args": ["--silent", "mcp"],
      "cwd": "/path/to/apex-cli",
      "env": {
        "APEX_MCP_CLIENT": "local-dev",
        "APEX_CLIENT_INTEGRATION": "local-dev"
      }
    }
  }
}

Do not point an MCP client at plain pnpm mcp. pnpm writes its script banner to stdout before the protocol stream, which can break the initialize handshake.

The local stdio MCP server exposes Apex-specific tools for:

  • auth status and device login
  • local guest-session deadlines through apex-trial-status (never the code or claim token)
  • doctor, credits, and provider connection URLs
  • workspace inspection and workspace binding
  • scan start, status, cancellation, findings, and findings export
  • cross-scan workspace findings through apex-workspace-findings, including direct workspace selection, first-class open state, web UI lifecycle fields, and server-side filters
  • Lite scan start by calling apex-scan with mode: "lite"
  • PR scan start by calling apex-scan with mode: "pr" and pullRequests
  • finding comments and valid/invalid feedback with apex-finding-comment and apex-finding-feedback
  • Fix PR and current-repository fix review scans with apex-finding-fix-review, optionally after apex-finding-feedback

Neither MCP surface exposes trial redemption, trial claim, or service-key creation, listing, or revocation as tools. When a user supplies a Cantina trial code, run apex redeem <code> in a terminal instead of starting device login or putting the code in an MCP call. Production MCP clients should connect to https://ai.cantina.xyz/mcp; HTTP applications can use the hosted Apex REST API directly. Do not launch the local stdio server as an HTTP adapter.

For repository-scoped operations, pass cwd explicitly so the server can resolve the right .apex/workspace.json binding and repository roots.

Use apex-workspace-findings when an agent needs the same cross-scan finding set as the workspace browser. Pass company, workspaceRef, and findingState: "open" to select any accessible workspace without changing the local binding and return only findings that still need review:

{
  "company": "apex-internal",
  "workspaceRef": "BEDR9",
  "findingState": "open"
}

Open state excludes fixed, invalid, dismissed, and duplicate findings. It is a first-class selection, not status:open; actual finding status values are proposed, partially_valid, valid, invalid, and duplicate. The response includes status, validity, reviewState, duplicate metadata, repository, and source file fields used by the web UI. Supported filter facets are severity, scan, repo, review, impact, likelihood, status, validation, visibility, duplicate, and source. Repeated filters in one facet are ORed; filters across different facets are ANDed, and a leading ! negates a filter.

For Codex-style clients, the packaged skill can be installed with apex setup codex. For GitHub Copilot CLI, the same skill is installed into ~/.copilot/skills/apex-cli with apex setup copilot. The repo-local source lives at skills/apex-cli/SKILL.md.

For Claude Code, the packaged project skill can be installed into the current repository with apex setup claude. The repo-local source lives at .claude/skills/apex-cli/SKILL.md. Anthropic documents project skills as filesystem directories under .claude/skills/<name>/SKILL.md, and the Claude Agent SDK uses the same location when the Skill tool is enabled.

Usage Telemetry

Apex CLI emits first-party, privacy-preserving usage telemetry so Cantina can understand how people use the direct CLI, the interactive shell, and MCP tools in Codex, Claude, GitHub Copilot CLI, or other clients.

Telemetry is enabled by default and can be disabled locally:

apex telemetry status
apex telemetry disable
apex telemetry enable

Environment opt-outs override local config:

APEX_TELEMETRY_DISABLED=1 apex scan
# also honored: APEX_DISABLE_TELEMETRY=1 or DO_NOT_TRACK=1

Telemetry records lifecycle events such as command/tool start and completion, duration, success/failure category, CLI version, Node/platform basics, anonymous install/session IDs, and sanitized command metadata. It also adds attribution headers to Apex API requests, including surface (cli, interactive_shell, or mcp), client integration, invocation ID, command/tool name, and CLI version.

Telemetry does not send raw cwd paths, repository URLs, finding IDs, scan IDs, PR URLs, comments, file paths, trial codes, claim tokens, onboarding fingerprints, bearer tokens, or raw flag values. Sensitive inputs are reduced to booleans, counts, enum values, or length buckets.

Telemetry event posts do not include bearer tokens. The telemetry endpoint is POST /api/cli/v1/telemetry/events with a batch payload:

{
  "events": [
    {
      "schemaVersion": 1,
      "event": "apex.invocation.completed",
      "cliVersion": "0.1.28",
      "invocation": {
        "surface": "mcp",
        "command": "apex-scan",
        "mcpTool": "apex-scan",
        "metadata": {
          "mode": "pr",
          "pullRequestCount": 1,
          "cwdProvided": true
        }
      },
      "client": {
        "integration": "codex"
      },
      "outcome": {
        "success": true,
        "durationMs": 1234
      }
    }
  ]
}

Plugin And Marketplace Packaging

The npm package also includes marketplace-ready plugin artifacts:

  • .codex-plugin/plugin.json and .mcp.codex.json for Codex plugin installs
  • .claude-plugin/plugin.json and .mcp.claude.json for Claude Code plugin installs
  • .claude-plugin/marketplace.json for a Claude marketplace entry backed by the public npm package

These plugin installs launch the pinned npm package with npx -y -p @cantinasecurity/[email protected] apex-mcp, so users do not need to install apex globally before enabling the plugin.

The repository also includes .agents/plugins/marketplace.json for local Codex marketplace testing from a checkout.

For local Claude validation:

claude plugin validate .
claude plugin marketplace add ./ --scope local
claude plugin install apex-cli@cantina-tools --scope local

For local Codex validation, add this repo as a local marketplace, then install apex-cli from the Cantina Tools marketplace in the Codex plugin directory:

codex plugin marketplace add ./

See MARKETPLACE.md for the official Claude, Anthropic Connectors Directory, and OpenAI/Codex submission checklist. The local stdio MCP server is plugin-ready, but remote marketplace submissions still require the external review steps documented there.

Development Notes

The CLI uses the Apex /api/cli/v2/** local-source routes for scan planning and snapshot uploads, with legacy /api/cli/v1/** routes still used for provider-backed flows such as audit scans. Local state is stored under:

  • ~/.config/apex/config.json
  • ~/.config/apex/credentials.json
  • .apex/workspace.json

When starting a non-PR scan, any active workspace scan (including a PR scan) requires confirmation. Scripted usage can opt in explicitly with --force. Starting a PR scan skips that client preflight and may run alongside active workspace scans without --force, matching Bedrock's one-directional scan concurrency contract. Active-looking workspace scan rows are checked against the scan progress endpoint before the CLI treats them as blockers, so stale list entries do not hide terminal states such as cancelled.

To move between existing Apex workspaces from the CLI:

  1. Run apex workspaces to list the workspaces available to your active company.
  2. Run apex workspace use <workspace-name|workspace-prefix|workspace-id> to bind the current directory.
  3. If the workspace name contains spaces, quote it, for example apex workspace use "Core Platform".
  4. Use apex scans, apex status --scan <scan-id>, apex findings, and apex export findings against that binding.
  5. Use apex findings --workspace --company <handle> --workspace-ref <ref> --finding-state open for the workspace browser's cross-scan findings that still need review, without changing the local binding.