Documentation

Copper CLI

copper-pp-cli

Install

npx -y @mvanhorn/printing-press-library install copper

Installs the CLI binary and the agent skill for Claude Code, Codex, Cursor, Gemini CLI, Copilot, and more. Add --cli-only or --skill-only for one half. Requires Node.

Documentation

The Copper CRM command line no one else built: full CRUD plus a local database, weighted pipeline forecasting, stale-deal detection, and the bulk operations Copper's own API refuses to provide.

Copper has no CLI, no Go client, and no agent-native tool. This turns a click-heavy web CRM into a scriptable, offline-queryable surface. It mirrors people, companies, leads, opportunities, projects, tasks, and activities into local SQLite, then adds the weighted forecast (forecast), cold-deal sweep (stale), and rate-limit-aware bulk editor (bulk) that the API and web UI leave out.

Authentication

Copper uses a multi-header API key. Set COPPER_API_KEY (System Settings -> API Keys -> Create a Key) and COPPER_USER_EMAIL (the email of the key owner). Every request sends X-PW-AccessToken, X-PW-UserEmail, and X-PW-Application: developer_api.

Quick Start

# Verify both credentials are wired before any live call
copper-pp-cli doctor --dry-run

# Mirror the pipeline graph into local SQLite
copper-pp-cli sync --resources opportunities,pipelines,pipeline_stages,users

# Weighted expected revenue, grouped by stage
copper-pp-cli forecast --by stage --agent

# Find open deals gone cold for 3+ weeks
copper-pp-cli stale --days 21 --agent

Unique Features

These capabilities aren't available in any other tool for this API.

Pipeline intelligence

  • forecast — Weighted expected-revenue roll-up: sums monetary_value x win_probability over open opportunities, grouped by stage, assignee, or close-month.

    Reach for this instead of exporting CSV and pivoting by hand for any expected-revenue or commit/quota question.

    copper-pp-cli forecast --pipeline 12345 --by stage --agent
    
  • stale — Surfaces open opportunities with no interaction in N days, sorted by staleness x value, across all reps.

    Use to find deals going cold before they die; pipe the output into bulk reassign.

    copper-pp-cli stale --days 21 --by assignee --agent
    
  • who — Joins an opportunity to its company, people, and recent activities into one related-records view.

    Use for one-call deal prep before nudging or logging a touch.

    copper-pp-cli who opportunity:88 --agent
    

Operations Copper's API refuses to provide

  • bulk — Applies field updates (stage, owner, custom fields) across many opportunities with bounded concurrency and heuristic 429 backoff.

    Use for mass updates to existing records; the safe way to avoid the rate-limit wall a naive loop hits.

    copper-pp-cli bulk move --query stale.json --set pipeline_stage_id=9 --concurrency 4 --dry-run
    
  • upsert — Match-then-create-or-update for people and leads; normalizes the people.emails[] vs leads.email shape difference.

    Use to sync external rows without creating duplicates; not a blind create.

    copper-pp-cli upsert person --match email --file contacts.json --dry-run
    
  • dedupe — Local SQLite self-join surfacing people or leads that share an email, name, or company.

    Run before or after a sync to catch duplicate contacts the API will not flag.

    copper-pp-cli dedupe people --on email --agent
    

CRM hygiene

  • log — Creates an activity with the type resolved by name (bumps interaction_count); log fix deletes and recreates to edit an immutable activity.

    Use to log or correct a single touch; for the same touch across many records use bulk.

    copper-pp-cli log call --on opportunity:88 --note "Left voicemail"
    

Recipes

Monday weighted forecast by rep

copper-pp-cli forecast --by assignee --agent --select assignee_name,weighted_value,open_value

Commit view per rep without a spreadsheet pivot.

Sweep then bulk-reassign cold deals

copper-pp-cli stale --days 30 --by assignee --agent

List cold deals grouped by owner. Save the JSON, then feed the ids into the bulk reassign command (with --set assignee_id=) to mass-reassign — preview with --dry-run before applying.

Idempotent contact import

copper-pp-cli upsert person --match email --file leads.json --dry-run

Create-or-update external rows without duplicating contacts.

One-call deal prep

copper-pp-cli who opportunity:88 --agent --select company.name,people.name,activities.details

Pull the deal's company, contacts, and recent touches in one narrowed view.

Usage

Run copper-pp-cli --help for the full command reference and flag list.

Paths & environment variables

This CLI separates local files into four path kinds:

KindContents
configUser-editable settings such as config.toml and saved profiles
dataDurable local data: credentials.toml, data.db, cookies, browser-session proof files, and other auth sidecars
stateRuntime state such as persisted queries, jobs, and teach.log
cacheRegenerable HTTP/cache files

Each kind resolves independently. The ladder is:

  1. Per-kind env var: COPPER_CONFIG_DIR, COPPER_DATA_DIR, COPPER_STATE_DIR, or COPPER_CACHE_DIR
  2. --home <dir> for this invocation
  3. COPPER_HOME for a flat relocated root
  4. XDG env vars: XDG_CONFIG_HOME, XDG_DATA_HOME, XDG_STATE_HOME, XDG_CACHE_HOME
  5. Platform defaults matching existing installs

For containers and agent sandboxes, prefer a single relocated root:

export COPPER_HOME=/srv/copper
copper-pp-cli doctor

Under COPPER_HOME=/srv/copper, the four dirs resolve to /srv/copper/config, /srv/copper/data, /srv/copper/state, and /srv/copper/cache.

MCP servers do not receive CLI flags from the host. Put relocation in the host env block:

{
  "mcpServers": {
    "copper": {
      "command": "copper-pp-mcp",
      "env": {
        "COPPER_HOME": "/srv/copper"
      }
    }
  }
}

Precedence matters in fleets: an ambient per-kind variable such as COPPER_DATA_DIR overrides an explicit --home for that kind. Use COPPER_HOME or the per-kind variables for durable fleet relocation; treat --home as the weaker per-invocation lever.

Relocation is one-way. Unsetting COPPER_HOME does not move files back to platform defaults, and doctor cannot find credentials left under a former root. Move the files manually before unsetting relocation variables.

Existing installs keep working because the platform-default rung matches the legacy layout. On the first auth write, stored secrets leave config.toml and are consolidated into credentials.toml under the data directory. Run copper-pp-cli doctor --fail-on warn to check path and credential-location warnings in automation.

Commands

account

Account details

  • copper-pp-cli account - Fetch account details

activities

Manage activities (notes and logged interactions)

  • copper-pp-cli activities create - Create a new activity
  • copper-pp-cli activities delete - Delete an activity
  • copper-pp-cli activities get - Fetch an activity by id
  • copper-pp-cli activities search - List/search activities

activity-types

Activity types

  • copper-pp-cli activity-types - List all activity types

companies

Manage companies

  • copper-pp-cli companies activities - List a company's activities
  • copper-pp-cli companies create - Create a new company
  • copper-pp-cli companies delete - Delete a company
  • copper-pp-cli companies get - Fetch a company by id
  • copper-pp-cli companies search - List/search companies
  • copper-pp-cli companies update - Update a company

contact-types

Contact types

  • copper-pp-cli contact-types - List all contact types

custom-activity-types

Custom activity types

  • copper-pp-cli custom-activity-types create - Create a new custom activity type
  • copper-pp-cli custom-activity-types get - Fetch a custom activity type by id
  • copper-pp-cli custom-activity-types list - List all custom activity types
  • copper-pp-cli custom-activity-types update - Update a custom activity type

custom-field-definitions

Custom field definitions

  • copper-pp-cli custom-field-definitions create - Create a new custom field definition
  • copper-pp-cli custom-field-definitions delete - Delete a custom field definition
  • copper-pp-cli custom-field-definitions get - Fetch a custom field definition by id
  • copper-pp-cli custom-field-definitions list - List all custom field definitions
  • copper-pp-cli custom-field-definitions update - Update a custom field definition

customer-sources

Customer (lead) sources

  • copper-pp-cli customer-sources - List all customer sources

lead-statuses

Lead statuses

  • copper-pp-cli lead-statuses - List all lead statuses

leads

Manage leads

  • copper-pp-cli leads activities - List a lead's activities
  • copper-pp-cli leads convert - Convert a lead into a person/company/opportunity
  • copper-pp-cli leads create - Create a new lead
  • copper-pp-cli leads delete - Delete a lead
  • copper-pp-cli leads get - Fetch a lead by id
  • copper-pp-cli leads search - List/search leads
  • copper-pp-cli leads update - Update a lead
  • copper-pp-cli leads upsert - Create or update a lead, matched by email or a custom field

loss-reasons

Opportunity loss reasons

  • copper-pp-cli loss-reasons - List all loss reasons

opportunities

Manage opportunities (deals)

  • copper-pp-cli opportunities create - Create a new opportunity
  • copper-pp-cli opportunities delete - Delete an opportunity
  • copper-pp-cli opportunities get - Fetch an opportunity by id
  • copper-pp-cli opportunities search - List/search opportunities
  • copper-pp-cli opportunities update - Update an opportunity

people

Manage people (contacts)

  • copper-pp-cli people activities - List a person's activities
  • copper-pp-cli people create - Create a new person
  • copper-pp-cli people delete - Delete a person
  • copper-pp-cli people fetch-by-email - Fetch a person by email address
  • copper-pp-cli people get - Fetch a person by id
  • copper-pp-cli people search - List/search people
  • copper-pp-cli people update - Update a person

pipeline-stages

Pipeline stages

  • copper-pp-cli pipeline-stages - List all pipeline stages

pipelines

Sales pipelines

  • copper-pp-cli pipelines list - List all pipelines
  • copper-pp-cli pipelines stages - List stages within a specific pipeline

projects

Manage projects

  • copper-pp-cli projects create - Create a new project
  • copper-pp-cli projects delete - Delete a project
  • copper-pp-cli projects get - Fetch a project by id
  • copper-pp-cli projects search - List/search projects
  • copper-pp-cli projects update - Update a project

tags

Tags used across records

  • copper-pp-cli tags - List all tags

tasks

Manage tasks

  • copper-pp-cli tasks create - Create a new task
  • copper-pp-cli tasks delete - Delete a task
  • copper-pp-cli tasks get - Fetch a task by id
  • copper-pp-cli tasks search - List/search tasks
  • copper-pp-cli tasks update - Update a task

users

Users in the account

  • copper-pp-cli users get - Fetch a user by id
  • copper-pp-cli users search - List/search users

webhooks

Webhook subscriptions

  • copper-pp-cli webhooks create - Create a new webhook subscription
  • copper-pp-cli webhooks delete - Delete (unsubscribe) a webhook subscription
  • copper-pp-cli webhooks get - Fetch a webhook subscription by id
  • copper-pp-cli webhooks list - List all webhook subscriptions

Output Formats

# Human-readable table (default in terminal, JSON when piped)
copper-pp-cli account

# JSON for scripting and agents
copper-pp-cli account --json

# Filter to specific fields
copper-pp-cli account --json --select id,name,status

# Dry run — show the request without sending
copper-pp-cli account --dry-run

# Agent mode — JSON + compact + no prompts in one flag
copper-pp-cli account --agent

Agent Usage

This CLI is designed for AI agent consumption:

  • Non-interactive - never prompts, every input is a flag
  • Pipeable - --json output to stdout, errors to stderr
  • Filterable - --select id,name returns only fields you need
  • Previewable - --dry-run shows the request without sending
  • Explicit retries - add --idempotent to create retries and --ignore-missing to delete retries when a no-op success is acceptable
  • Confirmable - --yes for explicit confirmation of destructive actions
  • Piped input - write commands can accept structured input when their help lists --stdin
  • Offline-friendly - sync/search commands can use the local SQLite store when available
  • Agent-safe by default - no colors or formatting unless --human-friendly is set

Exit codes: 0 success, 2 usage error, 3 not found, 4 auth error, 5 API error, 7 rate limited, 10 config error.

Health Check

copper-pp-cli doctor

Verifies configuration, credentials, and connectivity to the API.

Configuration

Run copper-pp-cli doctor to see the resolved config, data, state, and cache directories. The platform-default config path is ``; --home, COPPER_HOME, and per-kind env vars can relocate it.

Static request headers can be configured under headers; per-command header overrides take precedence.

Environment variables:

NameKindRequiredDescription
COPPER_API_KEYper_callYesSet to your API credential.

agentcookie (optional)

If you use agentcookie to sync secrets across machines, this CLI auto-adopts agentcookie-managed credentials with no extra setup. When the daemon writes to this CLI's config, copper-pp-cli doctor reports agentcookie: detected and auth-status labels the source as agentcookie. Skip this section if you don't use agentcookie - the CLI works the same as any other.

Troubleshooting

Authentication errors (exit code 4)

  • Run copper-pp-cli doctor to check credentials
  • Verify the environment variable is set: echo $COPPER_API_KEY Not found errors (exit code 3)
  • Check the resource ID is correct
  • Run the list command to see available items

API-specific

  • 401 authentication error — Set both COPPER_API_KEY and COPPER_USER_EMAIL; the email must be the key owner's account email
  • 429 Too Many Requests on a bulk run — Lower --concurrency (Copper caps near 180 req/min and sends no rate-limit headers)
  • forecast or stale returns nothing — Run sync --resources opportunities first; these commands read the local mirror

Sources & Inspiration

This CLI was built by studying these projects and resources:

Generated by CLI Printing Press

For agents: pass /documentation/copper/agents.md to install this CLI from a prompt.