Config

pinchtab config is the CLI entry point for creating, inspecting, validating, and editing PinchTab’s config file.

For security posture, token usage, sensitive endpoint policy, and IDPI guidance, see Security.

Commands

pinchtab config

Opens the interactive config overview/editor.

It currently exposes these high-signal settings directly:

  • multiInstance.strategy
  • multiInstance.allocationPolicy
  • instanceDefaults.stealthLevel
  • instanceDefaults.tabEvictionPolicy
  • instanceDefaults.tabPolicy.lifecycle

It also shows:

  • the active config file path
  • the dashboard URL when the server is running
  • the masked server token
  • a Copy token action
terminal
pinchtab config
pinchtab config

pinchtab config init

Creates a default config file at the current config path.

terminal
pinchtab config init
pinchtab config init

config init respects PINCHTAB_CONFIG. If that environment variable is set, the file is created there.

Generated config files include a $schema URL for IDE completion and validation.

pinchtab config schema

Prints the JSON Schema URL for this PinchTab build. Source builds, development builds, and versions without a published schema use the main schema URL. When a matching release schema is known, PinchTab uses that release tag; when a newer matching schema is known, PinchTab uses the closest newer tag.

terminal
pinchtab config schema
pinchtab config schema

Print the bundled schema JSON:

terminal
pinchtab config schema --print
pinchtab config schema --print

pinchtab config show

Shows the effective runtime configuration.

terminal
pinchtab config show
pinchtab config show

Secret values such as server.token remain masked in this output. The Security section also includes security.trustLoopbackProxy as Trust Loopback Proxy so proxy trust posture is explicit.

pinchtab config token

Copies the configured server.token to the system clipboard without printing it to stdout.

terminal
pinchtab config token
pinchtab config token

If clipboard access is unavailable, the command reports that safely and still does not print the token.

pinchtab config path

Prints the config file path PinchTab will read.

terminal
pinchtab config path
pinchtab config path

pinchtab config validate

Validates the current config file.

terminal
pinchtab config validate
pinchtab config validate

pinchtab config get

Reads a single dotted-path value from the file config.

terminal
pinchtab config get server.portpinchtab config get instanceDefaults.modepinchtab config get security.attach.allowHosts
pinchtab config get server.portpinchtab config get instanceDefaults.modepinchtab config get security.attach.allowHosts

pinchtab config set

Sets a single dotted-path value in the file config.

terminal
pinchtab config set server.port 8080pinchtab config set instanceDefaults.mode headedpinchtab config set multiInstance.strategy explicit
pinchtab config set server.port 8080pinchtab config set instanceDefaults.mode headedpinchtab config set multiInstance.strategy explicit

pinchtab config patch

Merges a JSON object into the config file.

terminal
pinchtab config patch '{"server":{"port":"8080"}}'pinchtab config patch '{"instanceDefaults":{"mode":"headed","maxTabs":50}}'pinchtab config patch '{"observability":{"activity":{"retentionDays":14}}}'
pinchtab config patch '{"server":{"port":"8080"}}'pinchtab config patch '{"instanceDefaults":{"mode":"headed","maxTabs":50}}'pinchtab config patch '{"observability":{"activity":{"retentionDays":14}}}'

Load Order

PinchTab applies configuration in this order:

  1. built-in defaults
  2. the config file selected by PINCHTAB_CONFIG or the default path
  3. PINCHTAB_TOKEN, if set, overriding server.token at runtime

Supported environment variables:

  • PINCHTAB_CONFIG: choose the config file path
  • PINCHTAB_TOKEN: override the API token at runtime
  • PINCHTAB_RATE_LIMIT_MAX: per-client request cap per 10-second window (default 3000, sized for agent-driven snapshot/action bursts). Lower it (e.g. to 300) when exposing the port beyond localhost. Child instances inherit it from the orchestrator’s environment.

For remote CLI targeting, use the root --server flag instead of config.

Config File Location

Default location by OS:

  • macOS: ~/.pinchtab/config.json
  • Linux: ~/.pinchtab/config.json
  • Windows: %APPDATA%\pinchtab\config.json

On macOS and Linux, PinchTab defaults to ~/.pinchtab so the CLI, npm-managed binary, and config file all use the same base directory.

If you are upgrading from an older macOS setup and still have a config at ~/Library/Application Support/pinchtab/config.json, treat that as a legacy location and move or merge it into ~/.pinchtab/config.json.

Override the config path with:

terminal
export PINCHTAB_CONFIG=/path/to/config.json
export PINCHTAB_CONFIG=/path/to/config.json

Config Shape

Current nested file-config shape:

{
  "$schema": "https://raw.githubusercontent.com/pinchtab/pinchtab/main/schema/config.json",
  "configVersion": "0.8.0",
  "server": {
    "port": "9867",
    "bind": "127.0.0.1",
    "token": "your-secret-token",
    "stateDir": "/path/to/state",
    "networkBufferSize": 100,
    "retainNetworkBodies": false,
    "retainNetworkBodyMaxBytes": 262144,
    "trustProxyHeaders": false,
    "cookieSecure": null
  },
  "browser": {
    "version": "144.0.7559.133",
    "binary": "/path/to/chrome",
    "remoteDebuggingPort": null,
    "extraFlags": "--disable-gpu",
    "cloak": {
      "fingerprintSeed": "42069",
      "platform": "windows",
      "locale": "en-GB",
      "timezone": "Europe/London",
      "webrtcIP": "auto",
      "fontsDir": "/path/to/fonts",
      "storageQuotaMB": 2048,
      "disableDefaultStealthArgs": true
    },
    "extensionPaths": ["/path/to/pinchtab/extensions"]
  },
  "instanceDefaults": {
    "mode": "headless",
    "noRestore": false,
    "timezone": "Europe/Rome",
    "blockImages": false,
    "blockMedia": false,
    "blockAds": false,
    "maxTabs": 20,
    "maxParallelTabs": 0,
    "userAgent": "",
    "noAnimations": false,
    "humanize": false,
    "stealthLevel": "light",
    "tabEvictionPolicy": "close_lru",
    "tabPolicy": {
      "lifecycle": "keep",
      "closeDelaySec": 300,
      "restore": false
    },
    "dialogAutoAccept": false
  },
  "security": {
    "allowEvaluate": false,
    "allowMacro": false,
    "allowScreencast": false,
    "allowDownload": false,
    "allowCookies": false,
    "allowFileScheme": false,
    "allowedDomains": ["127.0.0.1", "localhost", "::1"],
    "downloadAllowedDomains": [],
    "downloadMaxBytes": 20971520,
    "allowUpload": false,
    "allowClipboard": false,
    "uploadMaxRequestBytes": 10485760,
    "uploadMaxFiles": 8,
    "uploadMaxFileBytes": 5242880,
    "uploadMaxTotalBytes": 10485760,
    "maxRedirects": -1,
    "trustedProxyCIDRs": [],
    "trustedResolveCIDRs": [],
    "attach": {
      "enabled": false,
      "allowHosts": ["127.0.0.1", "localhost", "::1"],
      "allowSchemes": ["ws", "wss", "http", "https"],
      "forwardProxyAuth": false
    },
    "idpi": {
      "enabled": true,
      "strictMode": true,
      "scanContent": true,
      "wrapContent": true,
      "customPatterns": [],
      "scanTimeoutSec": 5,
      "shieldThreshold": 30
    }
  },
  "profiles": {
    "baseDir": "/path/to/profiles",
    "defaultProfile": "default"
  },
  "multiInstance": {
    "strategy": "always-on",
    "allocationPolicy": "fcfs",
    "instancePortStart": 9868,
    "instancePortEnd": 9968,
    "restart": {
      "maxRestarts": 20,
      "initBackoffSec": 2,
      "maxBackoffSec": 60,
      "stableAfterSec": 300
    }
  },
  "timeouts": {
    "actionSec": 30,
    "navigateSec": 60,
    "shutdownSec": 10,
    "waitNavMs": 1000
  },
  "autoSolver": {
    "enabled": false,
    "autoTrigger": true,
    "triggerOnNavigate": true,
    "triggerOnAction": true,
    "maxAttempts": 8,
    "solverTimeoutSec": 30,
    "retryBaseDelayMs": 500,
    "retryMaxDelayMs": 10000,
    "solvers": ["cloudflare", "semantic"],
    "llmProvider": "",
    "llmFallback": false,
    "external": {
      "capsolverKey": "",
      "twoCaptchaKey": ""
    }
  },
  "scheduler": {
    "enabled": false,
    "strategy": "fair-fifo",
    "maxQueueSize": 1000,
    "maxPerAgent": 100,
    "maxInflight": 20,
    "maxPerAgentInflight": 10,
    "resultTTLSec": 300,
    "workerCount": 4
  },
  "observability": {
    "activity": {
      "enabled": true,
      "sessionIdleSec": 1800,
      "retentionDays": 1,
      "events": {
        "dashboard": false,
        "server": false,
        "bridge": false,
        "orchestrator": false,
        "scheduler": false,
        "mcp": false,
        "other": false
      }
    }
  }
}

autoSolver.external is config-file-only. Capsolver and 2Captcha credentials are stored there.

Semantic Flow Credentials

The semantic-first autosolver flow injects credential values into recognised login/signup/form fields. Configure them under autoSolver.credentials in the config file:

{
  "autoSolver": {
    "credentials": {
      "login":  { "user": "you@example.com", "password": "..." },
      "signup": { "name": "Jane Doe", "email": "you@example.com", "password": "..." },
      "form":   { "field1": "...", "field2": "...", "email": "you@example.com" }
    }
  }
}

Notes:

  • Edit credentials by writing the config file directly. The dashboard config API redacts them on read (GET returns blanks) and preserves on-disk values when a PUT comes in with empty fields, so secrets never round-trip through the UI.
  • The form solver step 2 falls back to form.email when form.field2 is empty.
  • Steps without a configured value fall through to a click-only flow (e.g. a login attempt with no password becomes a “click submit” attempt).

The dashboard Settings page exposes the non-secret AutoSolver settings and shows the active config file path. Provider keys remain managed directly in the config file.

Browser Selection

The CLI uses --browser <name> to select a browser. In the config file the equivalent field is browsers.default:

{
  "browsers": { "default": "cloak" }
}

browsers.default explicitly selects the local browser backend:

  • chrome uses the normal Chrome/Chromium launch path.
  • ghost-chrome serves static-friendly reads from a lightweight fetcher and escalates to Chrome when a page needs rendering.
  • cloak uses a discovered or configured local CloakBrowser Chromium binary.

When browsers.default is omitted, PinchTab prefers a discovered local CloakBrowser installation and otherwise falls back to Chrome. Newly generated config files make the same choice, while existing configs that explicitly set browsers.default to chrome continue to use Chrome.

browsers.available optionally restricts which browsers requests may select. For multiple named configurations of the same provider (different binaries, proxies, or fingerprints), use browser.targets with browser.defaultTarget and browser.fallbackOrder — see Terminology. The legacy browser.provider field is no longer supported and is rejected at validation time.

When the selected browser is cloak, PinchTab uses browser.binary when set or searches its normal local CloakBrowser paths. A named CloakBrowser target must set that target’s binary explicitly. PinchTab does not download, bundle, or redistribute the CloakBrowser binary.

On macOS, prefer a dedicated automation browser over your daily Google Chrome. Launching /Applications/Google Chrome.app headless makes macOS treat Chrome as already running, so opening your normal Chrome from the Dock just activates the windowless automation process and no window appears (issue #583). PinchTab’s discovery now prefers Google Chrome for Testing, Chromium, then Chrome Canary, and only falls back to your primary Chrome as a last resort. If only your daily Chrome is installed, install Google Chrome for Testing or set browser.binary to a separate Chrome/Chromium build. pinchtab doctor browsers warns when automation would use your primary Chrome.

browser.cloak maps supported CloakBrowser fingerprint settings to native launch flags:

  • fingerprintSeed -> --fingerprint
  • platform -> --fingerprint-platform
  • locale -> --fingerprint-locale
  • timezone -> --fingerprint-timezone
  • webrtcIP -> --fingerprint-webrtc-ip
  • fontsDir -> --fingerprint-fonts-dir
  • storageQuotaMB -> --fingerprint-storage-quota

disableDefaultStealthArgs defaults to true for CloakBrowser targets. When set, PinchTab keeps its process, profile, tab, extension, and action-control behavior, but does not add its own JS stealth overlays or automation-hiding launch flags. Set it to false only when you intentionally want PinchTab’s legacy stealth layer on top of CloakBrowser’s native patches.

Advanced CloakBrowser flags can still go through browser.extraFlags when they are not PinchTab-owned lifecycle flags.

browser.proxy.geo is a CloakBrowser fingerprint-alignment hint. When a proxy server and geo block are configured for a CloakBrowser target, PinchTab maps the geo values into native CloakBrowser fingerprint flags unless the target already sets the corresponding browser.cloak field. The stock chrome browser does not derive --lang, TZ, or WebRTC launch settings from proxy geo data.

Browser Extra Flags

browser.extraFlags is validated and sanitized. It is only for user-safe Chrome flags that do not weaken browser security and do not override PinchTab-owned launch behavior.

Rejected examples include:

  • --no-sandbox
  • --disable-web-security
  • --ignore-certificate-errors
  • --user-agent=...
  • --enable-automation=...
  • --disable-blink-features=...

Use the dedicated config fields instead:

  • instanceDefaults.userAgent for UA overrides
  • instanceDefaults.mode for headed/headless
  • instanceDefaults.timezone for timezone
  • browser.extensionPaths for extension loading
  • browser.remoteDebuggingPort for the remote debugging port

For Linux container compatibility, use the runtime-managed path instead of browser.extraFlags. PinchTab enables --no-sandbox automatically when needed.

By default, PinchTab looks for unpacked Chrome extensions in <server.stateDir>/extensions. On a normal local install that means the OS-specific PinchTab config directory plus extensions/, for example:

  • macOS: ~/.pinchtab/extensions
  • Linux: ~/.pinchtab/extensions
  • Windows: %APPDATA%\\pinchtab\\extensions

You can change or clear that default with browser.extensionPaths.

Tab Policy

instanceDefaults.tabPolicy groups tab lifecycle behavior:

{
  "instanceDefaults": {
    "tabPolicy": {
      "eviction": "close_lru",
      "lifecycle": "keep",
      "closeDelaySec": 300,
      "restore": false
    }
  }
}
  • eviction controls what happens when maxTabs is reached: close_lru, close_oldest, or reject.
  • lifecycle controls idle lifecycle behavior: keep disables lifecycle auto-close and is the default; close_idle auto-closes a tab after it handles an authorized /text, /snapshot, or /action request.
  • closeDelaySec is the idle delay for close_idle. The default is 300 seconds when auto-close is enabled.
  • restore controls whether session tabs are restored on startup. The default is false.

instanceDefaults.tabEvictionPolicy is still accepted for compatibility. New configs should use instanceDefaults.tabPolicy.eviction.

Humanized Input

instanceDefaults.humanize controls whether click and typing actions use the slower humanized path by default. The default is false, which keeps automation fast and deterministic by using raw CDP input.

Callers can override the instance default per action with the JSON field humanize:

  • {"kind":"click","selector":"#submit","humanize":true} opts a single action into bezier mouse movement and human-like delays.
  • {"kind":"type","selector":"#name","text":"Ada","humanize":true} opts a single type action into the slower per-character path.

Rationale: humanized input is useful for compatibility with pages that react poorly to raw input, but it adds sleeps and multi-step pointer movement. Keeping it opt-in prevents accidental seconds of overhead in default E2E and agent runs.

Sections

SectionPurpose
serverHTTP server settings, engine selection, proxy trust, and network buffer defaults
browserChrome executable, version pin, extra flags, and extension paths
instanceDefaultsDefault behavior for managed instances
securitySensitive feature gates, transfer limits, attach policy, and IDPI
profilesProfile storage defaults
multiInstanceOrchestrator strategy, allocation, port range, and restart policy
timeoutsAction, navigation, shutdown, and navigation wait delays
schedulerOptional task queue
observabilityActivity logging, source selection, and retention

config get And config set Support

pinchtab config get and pinchtab config set only support these top-level sections:

  • server
  • browser
  • instanceDefaults
  • security
  • profiles
  • multiInstance
  • timeouts
  • observability

They do not expose every field in those sections, and they do not support scheduler.*.

Use pinchtab config patch or edit config.json directly for fields such as:

  • server.networkBufferSize
  • browser.extensionPaths
  • instanceDefaults.dialogAutoAccept
  • instanceDefaults.tabPolicy.*
  • security.allowClipboard
  • security.idpi.scanTimeoutSec
  • security.idpi.shieldThreshold
  • scheduler.*
  • observability.activity.events.*

Common Examples

Headed Mode

{
  "instanceDefaults": {
    "mode": "headed"
  }
}

Network Bind With Token

terminal
pinchtab config set server.bind 0.0.0.0pinchtab config set server.token secretpinchtab server
pinchtab config set server.bind 0.0.0.0pinchtab config set server.token secretpinchtab server

Changing server.bind away from loopback is a documented, non-default, security-reducing deployment change. Use it only when remote reachability is intentional, keep a token set, and review the outer network boundary explicitly.

If the dashboard is served over plain HTTP on a non-loopback bind, PinchTab shows an in-product warning because session cookies are no longer transport encrypted. Prefer HTTPS or localhost when possible.

server.cookieSecure controls whether the dashboard session cookie must use the Secure flag:

  • null / unset / auto: default behavior. Session cookies are Secure on HTTPS and non-Secure on plain HTTP.
  • true: always require Secure. Dashboard login works only over HTTPS.
  • false: always omit Secure, even on HTTPS. Use only for operator-managed edge cases.

Examples:

terminal
pinchtab config set server.cookieSecure truepinchtab config set server.cookieSecure falsepinchtab config set server.cookieSecure auto
pinchtab config set server.cookieSecure truepinchtab config set server.cookieSecure falsepinchtab config set server.cookieSecure auto

When server.cookieSecure = true, plain-HTTP dashboard login fails explicitly with an HTTPS-required error instead of appearing to succeed and looping.

If TLS terminates in front of PinchTab, also set server.trustProxyHeaders=true only when the proxy is trusted and rewrites Forwarded / X-Forwarded-* headers correctly.

Custom Instance Port Range

{
  "multiInstance": {
    "instancePortStart": 8100,
    "instancePortEnd": 8200
  }
}

Attach Policy

{
  "security": {
    "attach": {
      "enabled": true,
      "allowHosts": ["127.0.0.1", "localhost", "chrome.internal"],
      "allowSchemes": ["ws", "wss", "http", "https"],
      "forwardProxyAuth": false
    }
  }
}

security.attach.allowHosts is an allowlist. If you set it to ["*"], PinchTab accepts any reachable attach host with an allowed scheme. That is a documented, non-default, security-reducing override: it removes host allowlisting entirely and should only be used on isolated, operator-controlled networks.

security.attach.forwardProxyAuth controls whether PinchTab may send configured proxy authentication credentials over remote CDP attach. It defaults to false; enable it only when the attached browser process and CDP transport are trusted.

Activity Retention

{
  "observability": {
    "activity": {
      "retentionDays": 14,
      "sessionIdleSec": 1800
    }
  }
}

server.trustProxyHeaders should stay false unless PinchTab is behind a trusted reverse proxy that overwrites Forwarded and X-Forwarded-* headers. Do not enable it on direct-exposure deployments or behind proxies that pass client-supplied forwarding headers through unchanged.

Legacy Flat Format

Older flat config is still accepted for backward compatibility:

{
  "port": "9867",
  "headless": true,
  "maxTabs": 20,
  "allowEvaluate": false,
  "timeoutSec": 30,
  "navigateSec": 60
}

Use pinchtab config init to create the current nested format.

Validation

pinchtab config validate checks, among other things:

  • valid instanceDefaults.mode
  • valid instanceDefaults.stealthLevel
  • valid instanceDefaults.tabEvictionPolicy
  • valid instanceDefaults.tabPolicy.eviction
  • valid instanceDefaults.tabPolicy.lifecycle
  • non-negative instanceDefaults.tabPolicy.closeDelaySec
  • instanceDefaults.maxTabs >= 1
  • instanceDefaults.maxParallelTabs >= 0
  • valid multiInstance.strategy
  • valid multiInstance.allocationPolicy
  • valid multiInstance.restart.* values
  • valid security.attach.allowSchemes
  • multiInstance.instancePortStart <= multiInstance.instancePortEnd
  • multiInstance.restart.initBackoffSec <= multiInstance.restart.maxBackoffSec
  • non-negative timeout values
  • non-negative server.networkBufferSize
  • non-negative security.idpi.scanTimeoutSec
  • positive observability.activity.sessionIdleSec and retentionDays

Valid enum values:

FieldValues
instanceDefaults.modeheadless, headed
instanceDefaults.stealthLevellight, medium, full
instanceDefaults.tabEvictionPolicyreject, close_oldest, close_lru
instanceDefaults.tabPolicy.evictionreject, close_oldest, close_lru
instanceDefaults.tabPolicy.lifecyclekeep, close_idle
multiInstance.strategysimple, explicit, simple-autorestart, always-on, no-instance
multiInstance.allocationPolicyfcfs, round_robin, random
security.attach.allowSchemesws, wss, http, https
security.attach.forwardProxyAuthtrue, false

Notes

  • config show reports effective runtime values, not just raw file contents.
  • config get, set, and patch operate on the file config model, not transient runtime overrides.
  • the dashboard config API treats server.token as write-only; use the CLI or file editing to manage it.