Configuration#

This page lists every key you can set in lockpin.json, the config file Lockpin reads at start, and the environment variables Lockpin reads. It is for anyone who runs Lockpin with settings other than the defaults.

The config file#

lockpin init writes lockpin.json, and lockpin -config lockpin.json reads it. lockpin init -schema prints every key the file may set. The file has three fields:

Field

What it holds

providers

The providers you use, which lockpin doctor checks.

flags

Any of the keys in the key table, each named as the flag is, without the dash.

projects

Budgets per project, each with day, week, month and total limits in USD and optional folders. "*" is every project not named. A project’s limit can only refuse calls.

{
  "providers": ["anthropic", "openai"],
  "flags": {
    "listen": "127.0.0.1:8787",
    "default-budget": 2.5,
    "compact": true,
    "ask-at-cap": "5m"
  }
}

Order of precedence#

  1. A flag given on the command line.

  2. The config file.

  3. The default in the key table.

A signed machine policy sets floors that all of these can only tighten. Run lockpin policy show to see the settings in force and where each one comes from (see Signed policy).

Checks#

A key that is not in the table is an error naming the nearest key that is. Every problem is reported at once, with the key and what it accepts, both when Lockpin starts and by lockpin doctor -config lockpin.json.

lockpin doctor -config lockpin.json

Secrets stay out of the file#

Provider keys stay in environment variables (lockpin providers lists them). A value that looks like an API key, a token, a URL with a password or a Slack, Teams, Discord or ntfy.sh webhook URL is refused. Give alert destinations in the LOCKPIN_ALERT_* environment variables instead (see Environment variables).

Note

Automatic price updates from the signed price feed are not set here: the machine’s signed policy turns them on (price_feed, off by default), and only the machine policy can choose the feed or the keys it must be signed by. lockpin prices update applies the feed by hand. The prices-url key below is the older, unsigned refresh. See Prices and the price feed.

Value types#

Type

Accepts

bool

true or false

int

A whole number

number

A number (USD or a percent)

duration

A string such as 30s, 5m or 1h

string

A string

Keys#

Each key is also a flag of lockpin with a dash in front (default-budget is -default-budget). Some keys change what the model sees; the table says so.

Budgets, caps and approvals#

Key

Type

Default

Meaning

default-budget

number

1

Budget in USD for tasks that set none. 0 means meter only, no cap.

day-limit

number

20

The most every task on this machine may spend together per UTC day, in USD, whatever task or project a call names (solo mode; team keys have -day of their own). 0: no ceiling.

ask-at-cap

duration

3m0s

When a call would pass its task’s budget while the meter (or VS Code) is open, hold it this long and ask there whether to allow it. With nobody watching, or no answer in time, it is refused. 0 never asks. At most 9m: clients give up on a call after 10.

ask-headless

bool

false

Hold calls at the cap for -ask-at-cap even when no screen reads the meter: for a server, container or CI node whose operator answers with lockpin approve, -approvals-api or the approval webhook (LOCKPIN_APPROVAL_WEBHOOK_URL, which turns this on). A held call nobody answers waits the whole -ask-at-cap, then gets its 402.

ask-remote

bool

false

Also ask about held calls in Slack, Teams and ntfy (the -alert-* destinations) and on paired phones (lockpin phone pair), with Stop, Allow this call and Raise budget. Answers come back through -relay, which this polls. While the relay answers, someone counts as watching, so calls are held up to -ask-at-cap.

allowance-pct

number

50

How far, in percent of its budget, a task’s budget may be raised without the meter page (its control token), once per task per day; anyone may use it, an agent too. Beyond it, and to remove a cap, needs the meter page. 0: every raise does. On a team node a team’s own allowance, set on the admin page, replaces it for that team’s tasks.

approvals-api

bool

false

Team mode: serve the held calls on the -listen port at /lockpin/api/remote/approvals, to a team key whose role is owner or workspace admin, and to the approval webhook’s answer tokens; never without one of them.

approvals-url

string

none

With -approvals-api: its base URL as a webhook’s receiver reaches it (https://lockpin.example.com), put in the webhook’s answer_url.

allow-pause

bool

false

Team mode: let lockpin pause and the meter’s Pause button pass every member’s calls through uncapped for a while. Off by default, since a pause uncaps the whole team.

projects

bool

true

Charge each call to its project as well as its task: the repository its agent works in (from Claude Code’s and Codex’s working folder, lockpin run’s folder, X-Lockpin-Project or /p/<project>/ in the base URL), with the limits under "projects" in lockpin.json. A project’s limit can only refuse calls. false names no project.

auto-tasks

bool

true

Charge an agent’s call that names no task (no X-Lockpin-Task, no /t/<task>/ base URL, no Claude Code or Codex session) to its conversation, as task auto-<hash of its first message>, so each conversation gets -default-budget of its own. Calls without tools stay on the default task. false charges them all to the default task.

session-tasks

bool

true

Charge a Claude Code or Codex call that names no task to its session, as task claude-<id> or codex-<id>, so each session gets -default-budget of its own. false charges them all to the default task.

degrade

bool

true

Degrade before refusing: once a task has spent -degrade-at percent of its budget, fit its calls’ own output limits to what is left, trim old tool results harder, and keep Anthropic calls on the 5-minute cache. The cap never rises, and key, team, user and tag limits never degrade. Per request: X-Lockpin-Degrade: off.

degrade-at

number

80

The percent of a task’s budget, spent or in flight, at which -degrade starts.

fit-output

bool

true

Give capped calls that set no output limit one, so the cap holds for them too: -fit-output-max tokens, or less near the cap. Near the cap, lower an Anthropic call’s own limit (down to 4096) instead of refusing it.

fit-output-max

int

32000

Largest output limit -fit-output adds (also never above the model’s maximum).

default-output-reserve

int

4096

Output tokens reserved when a request sets no limit and the model’s maximum output is unknown.

preflight

string

auto

auto (estimate, and ask Meta for exact input tokens only near the cap), count (always ask) or estimate (never ask).

charge-failed

bool

true

Charge failed calls their input cost (Meta can bill them).

breaker-usd

number

0

Circuit breaker: refuse a task or key (429) that is charged more than this in -breaker-window. 0 is off.

breaker-window

duration

1m0s

How far back the circuit breaker counts spend.

breaker-cooldown

duration

5m0s

How long a tripped task or key is refused.

breaker-by

string

both

What the circuit breaker watches: task, key (team mode) or both.

fallbacks

string

none

JSON file mapping a model (or "provider/*") to models to try when it keeps failing, and, under "downgrades", to cheaper models to serve a call that does not fit its budget instead of refusing it (none unless listed).

on-fault

string

block

When Lockpin’s own ledger file or keys file fails: block (refuse the call with a 503, the safe default) or allow (go on and mark the call). See Troubleshooting.

Alerts and digest#

Key

Type

Default

Meaning

alert-at

number

80

Alert when spend reaches this percent of a task budget or key limit, once per period. 0: only when the cap blocks a call.

task-warn-at

string

75,95

Warn when a task has spent these percents of its budget, once each: an alert and the X-Lockpin-Task-Warning header. Empty: one alert at -alert-at.

alert-slack

string

$LOCKPIN_ALERT_SLACK

Slack incoming webhook URL for alerts.

alert-teams

string

$LOCKPIN_ALERT_TEAMS

Microsoft Teams Workflows webhook URL for alerts (“Post to a channel when a webhook request is received”).

alert-ntfy

string

$LOCKPIN_ALERT_NTFY

ntfy topic URL for alerts, such as https://ntfy.sh/<a long random topic> or your own ntfy server. Whoever knows the topic can read them.

alert-webhook

string

$LOCKPIN_ALERT_WEBHOOK

URL that gets every alert as JSON.

alert-drift-usd

number

0.5

Alert when drift tracking flags wasted or lost work costing at least this many USD. 0: never.

spike-x

number

3

Alert when a task’s, key’s or user’s spend today (UTC) reaches this many times its usual day (the median of its days with spend in the last 14; it needs 3), once per day. 0: never.

spike-min

number

5

Spike alerts only for days of at least this many USD, so small days never alert.

loop-check

bool

true

Alert when a task repeats the same tool call with the same result 3 times. While the meter or VS Code is open, also hold the call and ask there whether to continue (for up to -ask-at-cap).

digest-at

string

mon 09:00

When to post the weekly digest to the alert destinations, as a weekday and time on this machine. off never posts it (lockpin digest prints it any time).

relay

string

https://app.lockpin.dev

The relay -ask-remote polls for answers and whose page phones answer on. It sees only question ids and answers, signed by this machine.

Network, ledger and listener#

Key

Type

Default

Meaning

listen

string

127.0.0.1:8787

Address to listen on. Keep it on localhost unless -keys is on (the meter has no login, so team mode serves it to localhost only).

admin-listen

string

none

Serve the meter and the breaker API on this address instead of -listen (for example 127.0.0.1:8790). In team mode an address other machines can reach is served only over the remote admin channel. Empty serves them on -listen.

meter-hosts

string

none

Comma-separated host names the meter, and outside team mode the model routes, also answer to, besides localhost, IP addresses and the -listen and -admin-listen names. They refuse others, which stops DNS-rebinding pages.

open

bool

false

Open the meter in your browser once Lockpin is running (the setup page until the first call). If Lockpin is already running on -listen, just open it.

ledger

string

lockpin-ledger.jsonl

File that keeps spend across restarts.

ledger-sync

string

interval

When the ledger file is flushed to disk: always (every event), interval (at most once a second), never (the OS decides).

audit-export

string

none

Folder to keep writing the ledger to as JSON Lines, for the machine’s log agent (Splunk, Sentinel, Elastic, Datadog) to collect. Off when empty. It reads the ledger file off the call path and never changes a decision.

ca-file

string

none

PEM file of extra root certificates (a corporate TLS-inspection root) trusted in addition to the system store for every outbound connection. LOCKPIN_CA_FILE is read when the flag is empty. Verification is never turned off.

upstream

string

https://api.meta.ai/v1

Meta Model API base URL.

retry-attempts

int

1

Tries per call on 429, 5xx and connection errors, first included. 1 means no retries. A retried call reserves once and only the successful try settles.

retry-base

duration

500ms

Wait before the first retry; doubles each time, with jitter.

retry-max

duration

20s

Longest wait between retries.

retry-after-max

duration

30s

Longest Retry-After to wait out. A provider that asks for more gets its reply passed to the client.

allow-uncapped

string

none

Comma-separated paths under a provider’s /v1, such as /embeddings,/images, that may be sent although Lockpin cannot meter them, so no cap holds for them. * sends every such call. Empty refuses them (reads always pass).

helicone-compat

bool

true

Read Helicone’s request headers (Helicone-Property-*, Helicone-User-Id, Helicone-Session-*) as Lockpin’s, and say which were ignored.

v

bool

false

Log every request.

Prices#

Key

Type

Default

Meaning

prices

string

none

Catalog file(s), comma-separated and merged in order, with extra or changed providers and model prices (see lockpin providers).

prices-url

string

none

HTTPS URL of an unsigned catalog to fetch into the first -prices file (default lockpin-prices.json) every -prices-refresh, and reload without a restart. Not fetched while the machine policy names a signed price_feed.

prices-refresh

duration

1h0m0s

How often -prices-url is fetched.

prices-max-drop

number

50

A fetched catalog that lowers a price by more than this percent, or changes where calls go, is refused (lockpin prices update -force accepts it). The signed price feed’s refresh keeps the same rule.

unknown-model-price

string

none

Price a model the catalog does not know at this USD per 1M tokens, "input,output[,cached]" (e.g. 15,75), instead of refusing it. The reply says X-Lockpin-Price: fallback, the charge counts as estimated, and the meter alerts once a day per model so you add it to the catalog.

allow-unpriced

bool

false

Send capped calls that use a tool fee or tier Lockpin cannot price, at the standard price, instead of refusing them with 400.

azure-deployments

string

none

JSON file mapping Azure OpenAI deployment names to the models they run ({"prod-chat": "gpt-6-sol"}), merged over AZURE_OPENAI_DEPLOYMENTS. Reloaded with the -prices files.

suggest-cheaper

bool

false

Say when a task would have cost less on its model’s cheaper step in the catalog, priced from its own calls, in the meter’s task API and lockpin suggest. Advice only: Lockpin never switches models. A team admin can also turn it on in the dashboard.

Savings and caching#

Key

Type

Default

Meaning

auto-cache-key

bool

true

Add prompt_cache_key (or the provider’s cache header) per task when a request sets none, to keep its prompt cache warm.

auto-cache-marker

bool

true

Turn on Anthropic’s prompt cache for calls that mark none, when the task’s last call was under 5 minutes ago.

anthropic-cache-ttl

string

client

Lifetime of Anthropic calls’ prompt cache: client (as the client asks), 1h (writes cost 2x instead of 1.25x, but a pause of 5 to 60 minutes no longer rewrites the whole history), or auto (1h for a task once it has paused past 5 minutes).

cache-anchor

bool

false

Mark the system prompt of Anthropic calls that mark the cache elsewhere but not there, so trimmed or edited history keeps it cached.

cache-economics

bool

false

Let each Anthropic task decide for itself, from its own pauses and context, whether the 1-hour cache and keep-alive pay, with the arithmetic in X-Lockpin-Cache-Plan. Until a task has 5 calls, -anthropic-cache-ttl and -cache-keepalive apply as set.

cache-keepalive

duration

0s

Keep an idle task’s 1-hour Anthropic cache warm for this long after its last call (e.g. 4h), by resending that call every 55 minutes with an output limit of 1. Each ping is charged to the task. Use with -anthropic-cache-ttl auto or 1h.

cache-ttl

duration

20m0s

How long Meta’s prompt cache survives idle.

stabilize

bool

false

Keep each request’s cacheable prefix the same call to call, on every provider: tools in one order and format, the system prompt’s whitespace fixed, its per-call lines (a date, a time, an id) moved to its end. Per request: X-Lockpin-Stabilize: on|off.

compact

bool

false

Trim old tool results when it pays: never the newest -compact-keep, nothing under -compact-min-tokens, and only when the saving repays the cache it breaks. Off by default. Changes what the model sees. Per request: X-Lockpin-Compact: on|off.

compact-keep

int

3

Most recent tool results never trimmed (0 keeps none).

compact-min-tokens

int

4000

Smallest worthwhile trim in tokens, so history is not trimmed a little every turn.

compact-exclude

string

none

Comma-separated tool names whose results are never trimmed.

compact-client-limit

int

0

Prompt size in tokens at which your agent summarises its own history (Codex, Claude Code); trimming stops there so the agent still does. 0 learns it.

dedup

bool

false

Replace an exact repeat of earlier tool output with a one-line pointer to the copy still in the history; in batches every 3 calls, never in the newest 3 turns. Needs -compact. Changes what the model sees.

stale-reads

bool

false

Replace an old read of a file that a later call edited with a one-line note; in batches every 3 calls, never in the newest 3 turns. Needs -compact. Changes what the model sees.

budget-note

bool

false

Add one line at the very end of each request of a task that has a budget, with the budget left and about how many more calls it pays for, so the agent can wrap up before the cap refuses it. Changes what the model sees. Per request: X-Lockpin-Budget-Note: on|off.

handoff

bool

false

When a conversation starts over in a task (a /clear, a compaction, a new session), add a note to it copied from the previous one. Changes what the model sees. Only for calls that name their task in X-Lockpin-Task. Per request: X-Lockpin-Handoff: off.

gap-tables

string

auto

The pause and calls-per-task tables Lockpin keeps from its ledger (lockpin gaps shows them): off, shadow (shown, deciding nothing) or auto (they decide only where lockpin gaps -check found them at least as good as the old rules, for 30 days after the check).

learned

string

auto

The learned pause model lockpin learn trains: off, shadow (shown, deciding nothing) or auto (it decides the -cache-economics 1-hour cache choice only where lockpin learn passed it and the gap tables decide).

ab

string

none

A/B experiments on the savings switches, such as "stabilize,compact=50%" (see lockpin ab in the Command reference).

Drift tracking#

Key

Type

Default

Meaning

drift

string

none

Project folder to snapshot on every model call, to catch recreated, reverted, repeated and lost work. Empty: off.

drift-goal

string

none

Goal file in the project to measure steps against, e.g. GOAL.md (default: GOAL.md or REQUIREMENTS.md if present, else the first request).

drift-plan

string

none

Checklist file in the project to follow, e.g. PLAN.md (default: PLAN.md, TODO.md or TASKS.md if present).

drift-brief

bool

false

Add project notes (earlier sessions, removed code, warnings, plan) to the model’s instructions. Changes what the model sees.

drift-session-gap

duration

30m0s

Idle time after which a task’s next call starts a new session.

drift-store

string

none

Where drift snapshots and the journal are kept (default: a folder in your user cache).

Team mode#

Key

Type

Default

Meaning

keys

string

none

Team mode: require a Lockpin key from this file on every call (see lockpin keys).

tags-locked

bool

false

Team mode: a call’s X-Lockpin-Tag-* headers cannot change its key’s tags.

keep-prompts

int

0

Team mode: keep the last prompt each person types, on this server only, for this many days (gzip, mode 0600; admins read them in the meter, members their own). Tell your team first. 0 keeps none.

prompts-dir

string

none

Folder -keep-prompts keeps them in (default: lockpin-prompts next to -ledger).

capabilities

string

none

Team mode: also accept spend capabilities (lpc_...) minted on this node, using the provider keys, root secret and node key in this sealed store (lockpin keys seal).

capabilities-issuer

string

none

With -capabilities: the admin listener (http://host:port) of the node that issues heartbeats and revocations. Empty makes this node its own issuer.

capabilities-issuer-key

string

none

With -capabilities-issuer: the issuer’s node key in hex, as its lockpin keys seal printed it.

capabilities-same-user

bool

false

With -capabilities: start even when this node runs as a user who signs in on this machine, where capabilities are bookkeeping only (the meter and the log say so).

managed-keys

bool

false

Accept keys made in the hosted dashboard (pushed as hashes; needs -report on and -keys).

managed-keys-ceiling

number

100

USD a month a dashboard-made key may spend on this machine, whatever the dashboard set.

Reporting and policy#

Key

Type

Default

Meaning

report

string

off

Optional reporting: off or on.

report-detail

string

tags

Maximum detail: totals, tags or tasks.

report-token

string

none

File containing JSON key_id and secret (or LOCKPIN_INGEST_TOKEN).

report-url

string

https://ingest.lockpin.dev

Ingest base URL.

policy-dir

string

none

Folder of the signed policy file and its pinned keys (default: %ProgramData%\Lockpin\policy, /Library/Application Support/Lockpin/policy or /etc/lockpin). The policy sets floors the other settings can only tighten.

policy-required

bool

false

While no signed machine policy is in force, refuse every metered call (503 policy_unavailable) and pass nothing through but the model list and token counts.

policy-user

string

none

The per-user signed policy file, verified against the same pinned keys (default: lockpin-policy.json in this user’s Lockpin data folder).

Recording#

Key

Type

Default

Meaning

record

string

none

Write every model call to cassettes in this folder, one file per task, known key and token patterns removed, for lockpin replay FOLDER.

record-for

duration

0s

With -record: stop recording this long after Lockpin starts (e.g. 2h). Calls go on, unrecorded, and the log says so once. 0 is no limit.

record-max-mb

int

0

With -record: stop writing new cassette entries once the folder’s cassettes (.jsonl) total more than this many MB, counting what was there at start. 0 is no cap.

Warning

Cassettes hold prompts and code, so keep the -record folder private (it gets a .gitignore). In team mode it records everyone’s prompts: tell your team first. Every entry holds the whole prompt, so a long session’s cassette grows quickly (tens to hundreds of MB). Turn -record on for the sessions you want to replay, not permanently, or cap it with -record-max-mb and -record-for.

Environment variables#

Variable

What it does

LOCKPIN_DATA_DIR

Changes the data folder where the service keeps its ledger (see Command reference).

LOCKPIN_CA_FILE

Extra root certificates (PEM) to trust, read when -ca-file is empty.

LOCKPIN_ALERT_SLACK

Slack incoming webhook URL for alerts.

LOCKPIN_ALERT_TEAMS

Microsoft Teams Workflows webhook URL for alerts.

LOCKPIN_ALERT_NTFY

ntfy topic URL for alerts.

LOCKPIN_ALERT_WEBHOOK

URL that gets every alert as JSON.

LOCKPIN_APPROVAL_WEBHOOK_URL

The approval webhook for held calls; setting it turns on -ask-headless.

LOCKPIN_INGEST_TOKEN

The reporting token, instead of a -report-token file.

AZURE_OPENAI_DEPLOYMENTS

Azure OpenAI deployment names mapped to the models they run; -azure-deployments is merged over it.

LOCKPIN_KEY_FILE

lockpin node run: the provider keys file.

LOCKPIN_NODE_DATA

lockpin node run: the node’s folder.

LOCKPIN_CAPABILITY

lockpin capabilities show and lockpin delegate: the capability to read.

ANTHROPIC_ADMIN_KEY, OPENAI_ADMIN_KEY, CURSOR_ADMIN_KEY

lockpin import: the providers’ admin keys. Never written down.

Provider API keys are read from each provider’s own key variable. lockpin providers lists which variable each provider uses and whether it is set.

Next steps#