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.17

Published

Standalone CLI and MCP server for Apex.

Downloads

849

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

MCP registrations keep working across package updates because they point at the stable apex-mcp shim. Re-run apex setup after upgrading if you want to refresh copied skill files, and run apex setup claude in each repository where you want the Claude project skill.

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

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 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
  • /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 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 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

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 And The Hosted API

Use the hosted Apex API for HTTP-only, headless integrations such as serverless functions, cron jobs, and internal audit hubs. Use the CLI or stdio MCP server for local and interactive agent workflows. The full HTTP 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 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.

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

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

In v1, the GitHub repository must already be linked to an active Apex workspace. The hosted API never creates, binds, or mutates workspaces. Apex selects the workspace automatically when exactly one active workspace matches the repository; pass the optional workspaceId to disambiguate multiple matches. Zero matches, or multiple matches without a valid workspaceId, return HTTP 409.

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 HTTP API, not the Apex CLI or MCP server. Assume the GitHub repository is already linked to an active Apex workspace; this API must not create or mutate workspaces. 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 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 MCP. The GitHub repository must already belong to an active Apex workspace, and the adapter must not create or mutate workspaces. Implement scan trigger, 409 workspace-resolution handling, status polling with bounded backoff, terminal failure handling, and findings retrieval. Send repoUrl, 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, apex-auth-start followed by apex-auth-wait is enough to authenticate these write tools.

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

The CLI now ships an MCP server so LLM clients can drive Apex directly over stdio.

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 --scope user \
  -e APEX_MCP_CLIENT=claude \
  -e APEX_CLIENT_INTEGRATION=claude \
  -- apex apex-mcp

For GitHub Copilot CLI:

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

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 MCP server exposes Apex-specific tools for:

  • auth status and device login
  • doctor, credits, and provider connection URLs
  • workspace inspection and workspace binding
  • scan start, status, cancellation, findings, and findings export
  • 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

The MCP server does not expose service-key creation, listing, or revocation. For HTTP-only serverless and cron integrations, use the hosted Apex API directly instead of launching the stdio MCP server.

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

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, 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.17",
      "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

If a scan is already running in the current workspace, apex scan and /scan now require confirmation before starting another one. Scripted usage can opt in explicitly with --force. 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.