# insecur — complete documentation Every documentation page concatenated as markdown. Index: https://insecur.cloud/llms.txt. Each page begins with a divider naming its canonical source URL. insecur is experimental and prelaunch: no public sign-up yet, and not approved for valuable production secrets. Local Mode runs the development loop with no account. --- Source: https://insecur.cloud/docs/index.md # insecur documentation insecur is an experimental developer tool for keeping secrets out of plaintext project `.env` files. It stores development secrets encrypted and injects the variables you select into a child process when you run a command. The `insecur` CLI is the primary interface, for humans and for agents. Product output is metadata: names, versions, opaque ids, and audit references. Secret values travel through a one-use injection grant into the environment of the child process you asked it to run. A process controlled by an agent can inspect its own environment, so runtime injection reduces routine exposure and plaintext storage rather than making a secret unreadable to that agent. The hosted service and its production no-reveal design are still prelaunch and are not approved for valuable production secrets. Automatic provider rotation and one-button recovery after an exposure are goals, not available features today. There is no public sign-up yet; [Local Mode](/docs/local-mode) runs the development loop with no account. ## Start here 1. [Install the CLI](/docs/installation) 2. [Quickstart](/docs/quickstart): store a secret and run a command with it in about five minutes 3. [How insecur works](/docs/how-it-works): the custody model and its honest boundaries ## Reading these docs as an agent Start with the [agent implementation guide](/docs/agent-quickstart.md) to add insecur to an existing project. It includes credential import, command wiring, fresh-worktree verification, and the handoff for a missing or rejected key. Every page is served in two formats at the same path: rendered HTML at `/docs/` and raw markdown at `/docs/.md`. [llms.txt](/llms.txt) is the index of every page with its markdown URL. The [CLI reference](/docs/cli) is generated from the CLI source on every change, so it never disagrees with `--help`. Error responses carry RFC 9457 `type` URIs that resolve to the [error reference](/errors), and `--json` error output includes copy-pasteable remediation commands. ## Sections | Section | What it covers | | --------------- | ------------------------------------------------------------------ | | Getting started | Install, first secret, first injected run | | Concepts | The custody model, the domain vocabulary, the security boundaries | | Guides | Task-oriented walkthroughs: agents, CI, migration, scanning, audit | | Reference | Environment variables, API overview, exit codes, error codes | | CLI reference | Every command and flag, generated from source | --- Source: https://insecur.cloud/docs/quickstart.md # Quickstart This walkthrough takes you from nothing to a running process with a secret in its environment. insecur does not print the value or write it to a project file or audit log. The child process receives the plaintext value and can display it if the program chooses. insecur is experimental and prelaunch. Use this quickstart with development credentials, not valuable production secrets. There is no public sign-up yet: hosted sign-in works only for accounts that are already enabled. Everyone else can run the same loop in [Local Mode](/docs/local-mode) with no account; step 2 tells you how. ## 1. Install the CLI ```sh curl -fsSL https://insecur.cloud/install.sh | sh ``` On Windows, use PowerShell: `irm https://insecur.cloud/install.ps1 | iex`. The installer verifies the release binary against its published SHA-256 checksums before installing. See [Installation](/docs/installation) for details and offline options. ## 2. Log in, or skip this step for Local Mode If you have a hosted account: ```sh insecur login ``` This opens your browser for sign-in and mints a short-lived CLI credential. There is no long-lived token to copy anywhere. Headless machine? Use `insecur login --device`. If you do not have one, skip this step. Running `insecur init` without a session starts [Local Mode](/docs/local-mode), which runs this whole loop against an encrypted store on your machine. The remaining steps are the same. ## 3. Initialize your project From your project directory: ```sh insecur init ``` On a fresh hosted account this provisions sensible defaults for you: a personal organization, a first project, and a development environment. In Local Mode it creates the encrypted machine-local store instead. Either way it writes `.insecur.json` in your project, a small committed file containing only opaque resource ids. It is safe to check in; there is nothing secret in it. ## 4. Store a secret ```sh insecur secrets set DATABASE_URL --value-stdin < /dev/tty ``` Paste the value and press enter. The write is blind: the CLI sends the value in, and every response from here on is metadata only (variable key, version, who set it, when). Don't have a value yet? Let insecur generate and store one without printing it: ```sh insecur secrets set API_SIGNING_KEY --generate random --length 32 ``` ## 5. Run something with it ```sh insecur run --variable-key DATABASE_URL -- node server.js ``` The CLI requests a fresh one-use injection grant, the value is decrypted inside the private runtime service, or on your machine in Local Mode, and it lands in the environment of `node server.js`. When the process exits, the grant is spent. Run it again and a new grant is issued and audited. Code controlling the child process, including an agent that launched it, can read the injected value. Confirm what happened without revealing anything: ```sh insecur secrets list insecur audit tail --limit 5 ``` `audit tail` reads the hosted audit trail and needs a hosted session. Local Mode records metadata-only audit events in the local store but has no `audit tail` yet. ## Where to go next - [Using insecur with coding agents](/docs/agents): run commands with injected development secrets and understand what the agent can still read - [Migrating from .env files](/docs/migrate-dotenv): import your existing file, then delete it - [How insecur works](/docs/how-it-works): what is protected, and what the honest boundaries are --- Source: https://insecur.cloud/docs/installation.md # Installation The `insecur` CLI is the supported way to work with insecur from a terminal, a coding agent, or CI. Install it with a one-line script, verify the binary, then log in. ## Install on macOS or Linux ```sh curl -fsSL https://insecur.cloud/install.sh | sh ``` The script it runs is [install.sh](https://insecur.cloud/install.sh); open it in your browser to read exactly what it does before piping it to a shell. ## Install on Windows Run this in PowerShell: ```sh irm https://insecur.cloud/install.ps1 | iex ``` The script it runs is [install.ps1](https://insecur.cloud/install.ps1). ## What the installer does Install the [GitHub CLI](https://cli.github.com/) first. The insecur install scripts use `gh attestation verify` and refuse to install without it. The install scripts ([install.sh](https://insecur.cloud/install.sh), [install.ps1](https://insecur.cloud/install.ps1)) download the platform binary, `SHA256SUMS`, and signed provenance bundle from the published `cli-v*` GitHub Release. They verify the checksum and require a valid GitHub build attestation signed by this repository's CLI release workflow. A corrupted, substituted, or unattested binary never lands on your machine. The binary is placed in: | Platform | Install destination | | ------------ | ---------------------------- | | macOS, Linux | `~/.local/bin` | | Windows | `%LOCALAPPDATA%\insecur\bin` | Make sure the install destination is on your `PATH`. If `insecur --version` fails right after install, add the directory to `PATH` and open a new shell. ## Installer overrides Set these environment variables before running the script to change what gets installed and where. | Variable | Purpose | | -------------------------- | ---------------------------------------------------------------------------- | | `INSECUR_CLI_VERSION` | Pin a release tag, for example `cli-v0.2.0`. Defaults to the latest release. | | `INSECUR_INSTALL_DIR` | Override the install destination directory. | | `INSECUR_INSTALL_BASE_URL` | Override the base URL the binary and checksums are fetched from. | Example, pinning a version and directory: ```sh export INSECUR_CLI_VERSION=cli-v0.2.0 export INSECUR_INSTALL_DIR="$HOME/bin" curl -fsSL https://insecur.cloud/install.sh | sh ``` ## Verify the install Confirm the binary runs: ```sh insecur --version ``` After you log in, confirm your identity and scope: ```sh insecur whoami ``` `whoami` returns metadata only: your principal, memberships, and resolved scope. It never prints a secret value. ## Crash reporting Crash reporting is on by default for unexpected CLI failures. Reports are metadata-only: they never include your argv, environment, or any secret value. They exist to make real bugs fixable. Turn crash reporting off in any of these ways: ```sh insecur --no-crash-reports whoami ``` ```sh export INSECUR_CRASH_REPORTS=off ``` ```sh insecur config set crash-reports off ``` ## Next step With the CLI installed and verified, continue to the quickstart to log in, resolve your scope, and complete your first value loop. ## Related - [Quickstart](/docs/quickstart) - [Environment variables](/docs/reference/environment-variables) - [Exit codes](/docs/reference/exit-codes) --- Source: https://insecur.cloud/docs/agent-quickstart.md # Agent quickstart This page is written for you, the agent. It tells you how to use development secrets without reading them during the normal workflow. Runtime injection does not enforce unreadability: if you control the child process, you can inspect its environment. If you are a human wiring up an agent, copy the [AGENTS.md snippet](#tell-your-agents-about-insecur-agentsmd) at the bottom into your repo and your agent will find its way here. ## The rules 1. Never display, inspect, log, or ask the user to paste a secret value into the conversation. Let `insecur import` read an explicitly identified project dotenv file directly. 2. Use `--json` for product commands. Output is metadata only, by contract. `insecur guide` is the exception: it intentionally emits offline Markdown playbooks. 3. Secrets reach code through `insecur run`, which injects them into one child process. That is the only delivery path you need. 4. Branch on exit codes, not on message text. Messages change; codes and remediation commands do not. 5. If the intended credential is missing or rejected, stop. Do not search other projects, home-directory credentials, agent settings, history, or transcripts for a substitute. A matching variable name or token format does not establish the right account or permissions. 6. Never generate a replacement for a third-party API key. Random generation is only for application-owned secrets such as signing keys, when their creation or replacement is authorized. ## Implement in an existing project Follow this procedure when the user hands you this page to adopt insecur. Local Mode needs no account or hosted login. It stores encrypted values on this machine and supports one injected variable per run. Use macOS or Linux: Windows runtime injection currently fails closed because descendant-process containment is not implemented. ### Install and select the project Install the [GitHub CLI](https://cli.github.com/) with `gh attestation` support first. The insecur installer verifies the binary checksum and GitHub build attestation. See [Installation](/docs/installation) for platform details and installer trust requirements. ```sh curl -fsSL https://insecur.cloud/install.sh | sh insecur --version ``` Start at the intended checkout's root. Inspect existing non-secret `.insecur.json` and application configuration code, without reading dotenv contents. Check the resolved configuration: ```sh insecur config show --json ``` Preserve an existing binding. Check `projectConfigPath`, project, and environment against this checkout's config. Explicit flags and `INSECUR_*` scope variables can override project defaults; stop on an unexpected selection instead of silently repointing the project. If the project has no config, initialize Local Mode explicitly from its root: ```sh insecur init --host local --json ``` Do not replace an existing hosted config with a local one. Follow the established authentication and policy setup for a hosted project. ### Import the intended credential The examples use `OPENROUTER_API_KEY`; substitute the exact variable your application uses. Confirm the provider account, credential purpose, and source file with the user if unknown. For a dotenv file the user has identified as belonging to this project: ```sh insecur import .env --dry-run --json insecur import .env --json insecur secrets list --json ``` Review the metadata-only dry-run plan before importing. File arguments are relative to the invocation directory. An approved source in the primary checkout can be passed by its exact path while retaining this project's target config. Do not search for it, parse it with a shell pipeline, or execute it with `source`. Import is create-only. Preflight rejects conflicts before writes start; a later write failure can leave partial progress, reported in the error. Reconcile that progress before retrying. The source file is preserved. Without an approved source file, ask the human to supply the intended credential in their own terminal with `insecur secrets set OPENROUTER_API_KEY --value-stdin`. Do not receive the value. A listed key without a current version still needs a value on this machine. ### Wrap the normal command Prefix the project's existing application or evaluation command with `insecur run`. For example, if its `eval` script currently runs `node scripts/evaluate.mjs`, update that same script: ```json { "scripts": { "eval": "insecur run --variable-key OPENROUTER_API_KEY -- node scripts/evaluate.mjs" } } ``` Keep the project's real executable and arguments. Do not recursively invoke the wrapped script or give the provider key to the whole agent session. The application must require its selected environment variable. Remove any application fallback that overrides it from another credential file. Local Mode supports one variable per run. Multi-secret policy runs require hosted mode; nesting `insecur run` does not combine keys. Each child gets a small OS environment baseline, including `PATH` and `HOME`, plus the selected value. Other ambient variables, including non-secret settings, are excluded. Supply necessary non-secret settings through normal application arguments or config. The child retains filesystem access, so libraries that search `HOME` for credentials need explicit configuration too. ### Verify the application and a fresh worktree Plan the actual command first: ```sh insecur run --variable-key OPENROUTER_API_KEY --plan --json -- node scripts/evaluate.mjs ``` Inspect `data.plan.ready`, `variableKeys`, `projectId`, and `environmentId`. A plan returns exit `0` even when `ready` is false and issues no grant. Check `projectConfigPath` when provided; `insecur config show --json` also reports the selected path. Respect each next action's `actor`: `human` means hand off, not permission to obtain the value yourself. Run the normal project command and its smallest meaningful provider-backed check: ```sh npm run eval ``` Use the project's actual package manager and command. A ready plan proves a stored value exists, not that the provider accepts its account, permissions, model access, or credit balance. If the provider rejects it, ask the owner to correct this binding rather than trying another key. Commit `.insecur.json`, the command change, and the agent instructions below. The config contains references and secret names, not values. Never commit local stores, machine keys, or plaintext credential files. Create a fresh worktree from a branch containing that commit, then repeat `config show`, `secrets list`, the plan, and the real application check from its root. On the same machine and OS user, the committed config selects the same encrypted local value. Do not copy `.env` into the worktree or initialize a replacement project there. On another machine, `insecur init --host local --json` adopts committed metadata; the owner must supply the intended values on that machine. Current source builds discover config from subdirectories within the current Git checkout. For released CLIs without that behavior, run from the checkout root or pass `--config-dir` with its exact config directory. See [Local Mode](/docs/local-mode) for discovery boundaries. ### Verify failure and finish cleanup Choose a variable that `secrets list` confirms is absent. If `INSECUR_MISSING_PROOF` is absent: ```sh insecur run --variable-key INSECUR_MISSING_PROOF --json -- node -e "console.error('CHILD_STARTED'); process.exit(99)" ``` Expect a nonzero missing-secret error and no `CHILD_STARTED` output. Ambient credentials and same-named secrets in other projects must not satisfy this request. Do not delete a real value to test failure. After the real application check passes, follow [dotenv migration](/docs/migrate-dotenv) to remove only the approved plaintext source. Preserve needed non-secret settings, obtain authorization before deleting files, and do not create extra plaintext backups. Run `insecur scan --strict --json` after cleanup; a clean scan covers its configured paths and detectors, not every copy on the machine. ### Done Report the normal command, selected config path, successful application check from the fresh worktree, missing-key failure without child execution, and cleanup result. Identify any remaining human handoff. Never include values. A configuration-only check is not end-to-end verification. ## Orient yourself Check whether a session exists and what scope is resolved: ```sh insecur whoami --json ``` Exit `0` means the command resolved the context it could. In hosted mode, inspect the returned session and scope fields instead of assuming organization, project, and environment are all present. Local Mode has no hosted session and can also return `0`. Exit `3` in hosted mode means no session: stop and ask the human to run `insecur login`, or run `insecur login --device` in a headless environment where the human can approve the device code. See what secrets the environment expects: ```sh insecur secrets list --json ``` ## Use a secret Run any command with a secret injected into its environment: ```sh insecur run --variable-key DATABASE_URL -- pnpm dev ``` The `--` separator is required. The CLI does not print the value or include it in the audit log. The child process receives it, so do not inspect, print, or log that process's environment. Each run consumes a fresh one-use grant and writes an audit event attributing it to you. ## Create a secret For a new application-owned signing secret, generation avoids copying the value: ```sh insecur secrets set WEBHOOK_SIGNING_SECRET --generate random --length 32 --json ``` If the value must come from a human (a third-party API key), ask the human to run the write themselves with `--value-stdin`. Do not accept the value into your own context. ## Handle failures Every failure returns a stable error code, an RFC 9457 `type` URI you can fetch for details, and, when one exists, copy-pasteable remediation commands in the `--json` envelope. The short version: | Exit | Meaning | What you should do | | ---- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `3` | Auth required | Ask the human to log in, or use `insecur login --device` | | `4` | Forbidden | Stop; the session lacks scope. Report it, do not retry | | `7` | Action required | Read the error; something external needs fixing first | | `8` | Retryable | Back off and retry | | `10` | Human step-up required | Take the `operationId` from the error and poll: `insecur operations wait --json`. A human clears it in the web console. Do not try to work around the gate | The full tables are [exit codes](/docs/reference/exit-codes) and [error codes](/docs/reference/errors). ## Keep the project clean Before and after you touch a project, you can check for plaintext secret exposure without an account: ```sh insecur scan --json ``` `insecur scan --strict` exits `7` when it finds likely secrets, which makes it a usable gate in hooks and CI. `insecur guide hooks` prints ready-made hook recipes for Claude Code and Codex. ## Read the rest of these docs Every page here is available as raw markdown: append `.md` to any docs URL, or start from [llms.txt](/llms.txt) for the index and [llms-full.txt](/llms-full.txt) for the entire documentation in one file. ## Tell your agents about insecur (AGENTS.md) Humans: paste this into your repo's `AGENTS.md` (or `CLAUDE.md`), adjusted to taste. ```markdown ## Secrets This project uses insecur for secrets. There are no readable secret values in this repo and there should never be. A process launched with `insecur run` does receive the selected values, so do not inspect, print, or log its environment. - Never display `.env` contents or ask me to paste a secret value. Import only an explicitly identified project file with `insecur import`. - Use this checkout's committed `.insecur.json`. Inspect selection with `insecur config show --json`; do not repoint it to fix a missing key. - Never search other projects, home-directory credentials, agent settings, history, or transcripts for a substitute credential. - Run anything that needs secrets through `insecur run --variable-key -- `. - List available keys with `insecur secrets list --json`. - If an API key is missing or rejected, stop and ask its owner to supply or correct it using `insecur secrets set --value-stdin`. Never generate a substitute. - Local Mode needs no login and injects one selected variable per run. - On exit code 3, tell me to run `insecur login`. On exit code 10, poll `insecur operations wait --json` while I approve in the web console. - Full agent instructions: https://insecur.cloud/docs/agent-quickstart.md ``` ## Related - [Using insecur with coding agents](/docs/agents): the human-facing view, attribution tiers, `agent shell` - [Quickstart](/docs/quickstart): the human first-run loop - [CLI reference](/docs/cli): every command and flag --- Source: https://insecur.cloud/docs/how-it-works.md # How insecur works Coding agents can read repositories and `.env` files at machine speed. insecur is an experimental attempt to remove that routine source of exposure: store development secrets encrypted, then inject them only into the process that needs them. insecur does that with two moves, in order of ambition. ## Move one: diskless development secret use In development, secrets stop living in files. A secret enters custody once, through a blind write: ```sh insecur secrets set STRIPE_KEY --value-stdin < /dev/tty ``` The value is encrypted on arrival and only ciphertext and metadata are stored. Nothing echoes it back. From then on, using the secret looks like this: ```sh insecur run --variable-key STRIPE_KEY -- pnpm dev ``` Each run issues a fresh, single-use, audited injection grant for exactly the variables you named. The value is decrypted inside a private runtime service that holds the only decryption capability, delivered into the environment of the child process, and the grant is spent. No plaintext at rest, no standing credential in your shell profile, and an audit event for every use with the full principal chain, including which agent asked. Be clear about the boundary here: the injected value does reach a process on your machine, and a process the agent launched is a process the agent controls. An agent can read or print that value if it chooses. What you get in development is no plaintext project file to scrape, one short-lived grant per use instead of an ambient credential, and an audit trail that records what was delivered. The grant limits reuse of insecur delivery; it does not change the provider credential's scope or lifetime. Automatic provider rotation and one-button exposure recovery are future goals. They do not exist today. Replacing a value stored in insecur does not revoke the old credential at its provider; you must rotate or revoke it with that provider yourself. ## Move two: the prelaunch production design The intended design for protected environments (staging and production) has a stronger property: the readable value does not reach the machine an agent or a human session runs on. There is no read-back route, reveal command, or console view that returns a protected value. Delivery to protected environments requires a machine credential bound to that environment, living where the workload runs (CI, the deploy target). Changes to protected secrets go through draft versions, promotion, and human approval that no CLI or agent-reachable channel can clear. An agent can prepare everything and ask; only a person with fresh step-up evidence in the web console can say yes. See [Approvals and step-up](/docs/approvals). This production path is still prelaunch and is not launch-proven. Do not use insecur for valuable production secrets yet. ## What a write and a run actually do 1. `secrets set` sends the value once. The API validates shape and size, then hands it to the private runtime service, which encrypts it under a tenant-bound key hierarchy (AES-256-GCM envelope encryption, wrapped per-record data keys). The response is metadata: variable key, version id, actor, timestamp. 2. `run` asks for an injection grant naming exact secret bindings. Grants are exact by design; there is no wildcard, prefix, or "all secrets in this folder" selection. 3. The runtime service, the only deploy holding the root key binding and the only place decryption happens, consumes the grant and returns the values over a private channel for injection into the child process environment. 4. The grant is now consumed. Reusing it fails. Every step emitted a metadata-only audit event. The public API edge, the web console, and the CLI never hold decryption capability. This separation is structural, enforced as separate deploys with conformance gates in CI, not an access-control flag. ## Honest claims, stated plainly - The protected-environment design offers no product read path that returns a secret value. It is still prelaunch and not approved for valuable production secrets. We do not claim "zero knowledge" or that operator access is technically impossible. - Development-tier injection delivers real values to your machine on purpose. The current benefit is encrypted storage, scoped delivery, and evidence, not secrecy from the process you ran. - Audit exports are tamper-evident and independently verifiable against published signing keys. That is the ceiling of the claim. See [Audit and verification](/docs/audit). ## Related - [Core concepts](/docs/concepts): the vocabulary these docs use - [Security model](/docs/security-model): boundaries, threat model, and what is out of scope - [Quickstart](/docs/quickstart): do the loop instead of reading about it --- Source: https://insecur.cloud/docs/concepts.md # Core concepts These are the nouns the product, the CLI, and the API all share. Every id you will see is an opaque resource id; names are display metadata, never addresses. ## Tenancy **Organization.** The tenant boundary. It owns projects, memberships, machine identities, connections, audit history, and the tenant-bound encryption keys. Solo users get a personal organization created automatically on first `insecur init` or during web onboarding. **Membership and roles.** Access always flows from an explicit membership with a role (owner, admin, developer, metadata viewer, approval, read-only). Roles grant authorization scopes, and every route checks scopes. There is no actor-type special-casing: a human, an agent session, and a machine identity all pass through the same authorization. **Project.** Belongs to one organization. Holds environments. **Environment.** Belongs to one project. The load-bearing property is `isProtected`. Development environments are non-protected: writes go live immediately and injection works from your machine. Staging and production are protected: changes require promotion and approval, and delivery requires environment-bound machine credentials. Protection is a property, not a naming convention. The development workflow is experimental. The protected-environment delivery path describes the prelaunch production design and is not approved for valuable production secrets yet. ## Secrets **Secret and variable key.** A secret is identified within an environment by its variable key, the environment variable name it will be injected as, like `DATABASE_URL`. **Blind write.** `insecur secrets set` sends a value in and returns metadata. You can also generate and store a value without printing it. A child process receiving the injected value, or an agent controlling that process, can still read it. **Versions.** Writes append versions; metadata records who set what and when. Non-protected writes become current immediately. Protected writes create draft versions that wait for [promotion and approval](/docs/approvals). `insecur secrets versions ` lists version metadata. **Reveal does not exist for protected environments.** There is no command or console view that returns a protected value. This is intentional and permanent. ## Using secrets **Runtime injection.** The only delivery path for development use: a value is decrypted inside the private runtime service and placed into the environment of one child process via `insecur run`. **Injection grant.** Every run gets a fresh grant naming exact secret bindings. Lifecycle: issued, then consumed, expired, or revoked. One use, short-lived, always audited. **Run policy.** A saved, immutable description of a repeatable run: exact secret bindings, the command, optionally a command fingerprint. Create one with `insecur run-policies create` and run it by profile. Bindings are always exact; there is no wildcard or prefix selection anywhere in the product. **Machine identity.** An organization-owned actor for CI and deploy workloads. It exchanges workload auth (GitHub Actions OIDC, or an environment deploy key) for short-lived tokens. Protected-environment delivery is machine-only. **App connection.** An organization-owned link to a provider (GitHub app installation, Cloudflare scoped token) with encrypted credentials, used for provider setup and alpha secret sync. Status output is metadata; provider credentials are never returned. Automatic provider rotation and one-button exposure recovery are not available today. ## Accountability **Agent attribution.** Sessions carry who is acting: a human directly, a derived agent child session, a registered agent harness, or a tag-only attribution. `insecur whoami` shows the resolved tier; audit events carry the principal chain. See [Using insecur with coding agents](/docs/agents). **Operations.** Long-running or gated work returns an operation id. `insecur operations get`, `wait`, and `cancel` read and control it. When a step-up gate blocks an action, the operation id is your handle to poll while a human clears it. **Audit events.** Metadata-only, tenant-scoped, filterable, exportable with signed manifests. See [Audit and verification](/docs/audit). ## Where configuration lives `.insecur.json` in your project directory pins host, organization, project, environment, and profile by opaque id. It is committed and non-secret. Flags override environment variables, which override the project file, which overrides profile defaults; the [environment variables reference](/docs/reference/environment-variables) lists the variables. ## Related - [How insecur works](/docs/how-it-works) - [Security model](/docs/security-model) - [CLI reference](/docs/cli) --- Source: https://insecur.cloud/docs/security-model.md # Security model insecur is experimental and prelaunch. This page separates the development workflow available today from the protected-environment design that still needs launch proof. Do not use the hosted service for valuable production secrets yet. ## The guarantee differs by tier | | Development environments | Protected-environment design | | ----------------------------- | ---------------------------------------------- | ----------------------------------------- | | Plaintext at rest | Never | Never | | Value reaches your machine | Yes, injected into one child process per grant | No | | Read-back through the product | No response body contains a value | No read path | | Delivery requires | A logged-in session and a one-use grant | An environment-bound machine credential | | Change control | Writes go live immediately | Draft versions, promotion, human approval | | Readiness | Experimental development workflow | Prelaunch and not launch-proven | For development, an agent-launched process holding the injected value is a process the agent controls, so the agent can read or print that value. The development benefit is no plaintext project file to scrape, no standing credential in a shell profile, and one audited grant per use. For the protected-environment design, the readable value does not reach an agent-reachable machine, and no human session, CLI call, or agent channel can obtain a protected injection grant. That stronger path is not launch-proven. ## Structural isolation, not conditionals The system runs as capability-isolated deploys. The public API edge holds no decryption capability and no database binding. The private runtime service is the sole holder of the root key binding, the only place decryption happens, and serves zero public routes; it is reachable only over a private service binding. The web console and the public site hold neither. CI conformance gates fail the build if any deploy ever combines a public route with the root key, so the boundary cannot erode quietly in a refactor. ## Cryptography Secret values are protected with AES-256-GCM envelope encryption under a tenant-bound key hierarchy: an instance root key wraps organization and project data keys, which wrap per-record data keys. Ciphertext is bound to its identity, so moving ciphertext between records fails closed. Key custody and rotation procedures harden further before general availability; current state is always reflected on the [security page](/security). ## Input hygiene the CLI enforces - Secret values are never accepted as command-line arguments. Inputs are stdin (`--value-stdin`), masked prompts, service-side generation (`--generate`), or provider authorization. `--token` style flags are explicitly rejected. - All CLI and API output is metadata-only by contract, enforced by shape checks and a no-plaintext canary test suite in CI. - Crash reports and telemetry are sanitized metadata: never argv, environment, values, or transcripts. ## Accountability Every meaningful action writes a tenant-scoped audit event carrying the principal chain: the human, the agent session acting under them, or the machine identity. Exports are signed (Ed25519) and independently verifiable against [published keys](https://insecur.cloud/.well-known/insecur/audit-export-signing-keys.json). The claim ceiling is tamper-evident and independently verifiable, nothing stronger. ## What we do not claim - Not zero-knowledge. We do not claim the operator is technically incapable of accessing data. Operator access is constrained by controls and audit, and the trust model is published rather than hand-waved. - No secrecy from your own runtime. A workload that receives a secret can do anything a process can do. insecur controls delivery and evidence, not what your code does afterward. - [Local Mode](/docs/local-mode) is encrypted local custody, not no-reveal custody. The machine key lives on the same machine. - No secure-erasure claims. `insecur local-files rm` is an ordinary filesystem delete. - No automatic provider rotation or one-button exposure recovery today. Writing a replacement value to insecur does not revoke the old credential at its provider. ## Reporting Found a vulnerability? See the [security page](/security) for the current disclosure contact. Please do not test against other tenants' data. ## Related - [How insecur works](/docs/how-it-works) - [Audit and verification](/docs/audit) - [Approvals and step-up](/docs/approvals) --- Source: https://insecur.cloud/docs/agents.md # Using insecur with coding agents To have an agent add insecur to an existing project, give it [the agent quickstart](/docs/agent-quickstart.md). It covers accountless Local Mode, importing the intended credential, wrapping the normal command, and verifying a fresh Git worktree. The hosted session and attribution features below are optional and require hosted authentication. Coding agents read your repo and your `.env` files at machine speed. insecur lets you remove plaintext development secrets from project files and attribute each runtime injection to the session that requested it. With insecur, an agent does not need a static secret in its ambient environment. Every `insecur run` mints a fresh one-use audited injection grant, and every audit event carries the principal chain: which human, which agent, which command. This is development-secret custody, not unreadability. The injected value reaches the child process the agent runs, and an agent that controls that process can inspect or print it. The current benefit is no plaintext project `.env` file, a short-lived single-use grant per run, and an audit record. Automatic provider rotation after an exposure is not available yet. ## Launch an agent in a deny-by-default session For hosted projects, wrap your agent harness in `insecur agent shell`. The child starts with a derived agent session and a filtered environment. This is not a filesystem sandbox: the agent can still access files allowed by its OS user. Local Mode does not require this command. ```sh insecur agent shell -- claude ``` The `--` separator is required. Everything after it is the command to run. The agent inside sees an attributed session, not your ambient credentials. To run a different harness, swap the command: ```sh insecur agent shell -- codex ``` ## Attribution tiers Attribution shows up in `insecur whoami` and in every audit event. Higher tiers give tighter, more trustworthy provenance. | Tier | How it happens | What it means | | ---------- | ---------------------------------------------------------------------------- | --------------------------------------------------------------------- | | Derived | Child credential minted from a live human session (`agent shell`) | Strongest: the agent's actions chain back to a specific human session | | Registered | Tier-2 structural registration when a harness is detected (`agent register`) | Structural agent session recorded for audit | | Tag-only | `--agent ` or `INSECUR_AGENT_TAG` | A label with no cryptographic backing | | None | No attribution provided | Actions attribute to the raw principal only | Prefer derived attribution. Use `agent shell` so the agent's session descends from your live human session. ## Wire an agent launched separately If your harness launches outside `agent shell`, hand it a session two ways. Print metadata-only shell exports for the harness to source: ```sh insecur agent env ``` Register a structural agent session for audit attribution: ```sh insecur agent register ``` For a headless machine, use device-authorization login that mints an agent-marked session: ```sh insecur login --device --agent-session ``` ## Environment variables a harness may see An agent harness may observe these. None of them is a secret value your product reads back. | Variable | Purpose | | ------------------------------- | ---------------------------------------------- | | `INSECUR_SESSION_TOKEN` | Session credential, in the environment only | | `INSECUR_AGENT_CREDENTIAL_FILE` | Path to a sealed derived-agent credential file | | `INSECUR_AGENT_TAG` | Tag-only attribution label | ## Gate agents with a scan hook Print offline recipes for wiring a scan gate into Claude Code and Codex. No auth required. ```sh insecur guide hooks ``` The hook runs `insecur scan --strict` so a run stops when likely secrets or transcript exposures are found. See [Scanning for exposed secrets](/docs/scan) for what it catches. ## Related - [Running commands with secrets](/docs/run) - [Scanning for exposed secrets](/docs/scan) - [Migrating from .env files](/docs/migrate-dotenv) - [Local Mode](/docs/local-mode) --- Source: https://insecur.cloud/docs/run.md # Running commands with secrets `insecur run` starts a command with the selected secrets injected into the child process environment. The CLI does not print or log the value, and audit events do not contain it. Each run requests a fresh one-use grant instead of reading a standing secret from a project file. This is development-secret custody. The injected value reaches the child process, and an agent controlling that process can inspect or print it. What you gain is no plaintext project `.env` file, a single-use short-lived grant per run, and an audit record. Automatic provider rotation is not available today. ## Run with a single variable Inject one exact variable key and run your command. The `--` separator is required. ```sh insecur run --variable-key DATABASE_URL -- node server.js ``` The child process sees `DATABASE_URL` in its environment. The CLI does not display it, though the child process can. The child starts in the invocation directory with an OS environment baseline plus the selected value. Unrelated shell credentials and other ambient application settings are excluded. Supply required non-secret settings through application arguments or configuration. Libraries can still read files under `HOME`; this is not filesystem isolation. Check selection and availability without issuing a grant: ```sh insecur config show --json insecur run --variable-key DATABASE_URL --plan --json -- node server.js ``` Inspect `data.plan.ready`; exit `0` alone does not mean a plan is ready. Current source builds also include `data.projectConfigPath` when project config was loaded. A ready plan proves a value exists, not its provider permissions. Missing values must be supplied by their owner, never borrowed from another project. See the [agent implementation guide](/docs/agent-quickstart). ## Run from a profile policy This requires hosted mode. Local Mode supports only single-variable runs. A hosted profile's default Runtime Injection Policy binds an exact set of secrets to a command. Run it by naming the profile: ```sh insecur run my-profile -- node server.js ``` Override the profile's default policy for a single run: ```sh insecur run my-profile --policy-id pol_example -- node server.js ``` Restart the child on file changes during development: ```sh insecur run --variable-key DATABASE_URL --watch -- node server.js ``` `--watch` is for development environments only. ## How injection works 1. The CLI requests a fresh one-use Runtime Injection Grant for the exact secret bindings. 2. Hosted decryption happens inside the private Runtime service. Local Mode decrypts on this machine using its machine key. 3. The value is injected into the child process environment. Code controlling that process can read it. 4. Run completion is recorded as metadata. The grant lifecycle is: issued, then consumed. An unconsumed grant expires or can be revoked. At no point does the value appear in CLI output, `--json`, logs, or audit events. ## Set secrets first Secrets must exist before you inject them. Writes are blind: the value is never echoed back. ```sh insecur secrets set DATABASE_URL --value-stdin ``` For an application-owned secret, generate a value instead of supplying one. Never generate a substitute for a third-party API key: ```sh insecur secrets set SESSION_SIGNING_KEY --generate --length 32 ``` | Flag | Effect | | ------------------- | --------------------------------------------------- | | `--value-stdin` | Read the value from stdin | | `--generate [mode]` | Service-generates the value; default mode is random | | `--length ` | Generated length in bytes, default 32 | | `--allow-empty` | Permit an empty value | See [the quickstart](/docs/quickstart) for the full setup path. ## Runtime Injection Policies A policy pins exact secret bindings to a command. Bindings are exact only, never wildcards or prefixes. Create a policy: ```sh insecur run-policies create --policy-id pol_example --command "node server.js" --secret-ids sec_a,sec_b ``` Additional creation flags: `--env-id`, `--display-name-stdin`, `--command-fingerprint sha256:...`, `--operation`. Inspect and retire policies: ```sh insecur run-policies show pol_example insecur run-policies disable pol_example --comment "rotated out" ``` ## The `--` separator Use `--` when injecting with `--variable-key` and no profile, or whenever the child command could be mistaken for a profile slug. It marks the boundary between insecur flags and the command to run. ## Related - [Using insecur with coding agents](/docs/agents) - [Migrating from .env files](/docs/migrate-dotenv) - [Scanning for exposed secrets](/docs/scan) - [Exit codes](/docs/reference/exit-codes) --- Source: https://insecur.cloud/docs/migrate-dotenv.md # Migrating from .env files A `.env` file is a plaintext secret sitting in your working tree, one agent read or one stray commit away from exposure. This guide moves those values into a development environment under custody, verifies the move, and removes the plaintext file. The migration is create-only. Preflight checks every key before writes start. A later write failure can leave partial progress; the error reports completed keys so you can reconcile them before retrying. The source file stays untouched. ## Recommended order 1. Select the intended project with `insecur config show --json` and identify its approved source file. Scan the project for likely exposure without displaying values. See [Scanning for exposed secrets](/docs/scan). 2. Import with `--dry-run` to review the plan. 3. Import for real. 4. Verify with `insecur secrets list` and a real `insecur run`. 5. Remove only the approved plaintext file after obtaining authorization. 6. Run `insecur scan --strict --json` and resolve or report any remaining findings. For a guided offline playbook of the whole move: ```sh insecur guide migrate-env ``` ## Preview the import Run a dry run first. It returns a metadata-only Secret Import Plan and writes nothing. ```sh insecur import .env --dry-run ``` The plan lists the keys that will be created. Values never appear in the plan. ## Import for real ```sh insecur import .env ``` If any key would conflict during preflight, import stops before writes. Import targets non-protected development environments. Use the exact source identified for this project; do not search other projects or home-directory credentials for substitutes. Prefix imported keys when you need to namespace them: ```sh insecur import .env --variable-key-prefix STAGING_ ``` ## Verify Confirm the keys landed: ```sh insecur secrets list ``` Then confirm injection works end to end with a real run: ```sh insecur run --variable-key DATABASE_URL -- node -e "if (!process.env.DATABASE_URL) process.exit(1); console.log('injection present')" ``` This checks presence only. Also run the application's real database or provider operation before removing its source file. The value reaches the child process, which can read it. See [Running commands with secrets](/docs/run) and the [agent implementation guide](/docs/agent-quickstart). ## Remove the plaintext file Once the values are in custody and verified, delete only the approved source file. Obtain authorization before deletion: ```sh insecur local-files rm .env ``` This prompts for explicit confirmation. Skip the prompt when scripting: ```sh insecur local-files rm .env --yes ``` This is an ordinary filesystem delete. There is no secure-erasure claim: treat any value that lived in the file as worth rotating at its provider. insecur does not automate provider rotation today, and storing a replacement does not revoke the old credential. ## Check for remaining plaintext After removing the approved source, run a strict scan: ```sh insecur scan --strict --json ``` If the scan finds likely secrets, resolve findings within the approved scope or report what remains. Do not delete other files without authorization. A clean scan covers its configured paths and detectors, not every copy on the machine. ## Related - [Scanning for exposed secrets](/docs/scan) - [Running commands with secrets](/docs/run) - [Using insecur with coding agents](/docs/agents) - [Local Mode](/docs/local-mode) --- Source: https://insecur.cloud/docs/scan.md # Scanning for exposed secrets `insecur scan` produces a project-scoped exposure report: it finds likely plaintext secret files without printing their values. It runs offline and needs no account or auth, so it is safe to run anywhere, including as the first step of a migration or as a CI gate. The report is metadata only. It tells you where likely secrets live, not what they are. ## Run a scan ```sh insecur scan ``` The scan root defaults to the current project. Point it elsewhere with the global `--config-dir`: ```sh insecur scan --config-dir /path/to/project ``` Get machine-readable output: ```sh insecur scan --json ``` ## Use it as a gate `--strict` exits with code `7` when likely secrets or transcript exposures are found. Wire it into CI or a hook to block on exposure. ```sh insecur scan --strict ``` See [Exit codes](/docs/reference/exit-codes) for the full list. Exit `7` is the action-required code. ## Widen the scan By default the scan stays inside the project. These flags extend it. | Flag | What it adds | | --------------------- | ------------------------------------------------------------------------------------------------ | | `--machine` | Also scans well-known home-directory credential locations, read-only and opt-in | | `--agent-transcripts` | Scans local agent conversation logs and exports for likely secrets | | `--agent-projects` | Discovers project directories agents touched, then inventories readable `.env`-style files there | Agents are the reason `--agent-transcripts` and `--agent-projects` exist. A coding agent's conversation log or a directory it wandered into can hold a secret that was never in your repo. ```sh insecur scan --agent-transcripts --agent-projects ``` ## Target specific transcripts Point the scan at exact transcript files or globs. Both flags repeat. ```sh insecur scan --transcript-path ~/logs/session-1.json --transcript-path ~/logs/session-2.json ``` ```sh insecur scan --transcript-glob "~/logs/*.jsonl" ``` ## Wire scan into agent hooks Print offline recipes for wiring `insecur scan` into Claude Code and Codex hooks as a gate: ```sh insecur guide hooks ``` The recipe runs `insecur scan --strict` before the agent proceeds, so a run stops when likely secrets are found. ## Related - [Using insecur with coding agents](/docs/agents) - [Migrating from .env files](/docs/migrate-dotenv) - [Exit codes](/docs/reference/exit-codes) - [Running commands with secrets](/docs/run) --- Source: https://insecur.cloud/docs/local-mode.md # Local Mode Local Mode is the simplest way to try insecur's current development workflow. An unauthenticated `insecur init` creates a local project config and uses an encrypted machine-local store instead of the hosted API. You get encrypted storage and the core run loop with no login, organization, or network dependency. Be clear about the boundary: Local Mode is encrypted custody on your machine. It is not no-reveal. The machine key lives on the same machine as the encrypted store, so anyone who fully controls that machine can reach the values. A child process receiving an injected value can also read it. Local Mode buys you no plaintext project `.env` file and an auditable local run loop, not unreadability. ## Start Local Mode From the project root, select Local Mode explicitly. No login is needed: ```sh insecur init --host local ``` This writes a local project config `.insecur.json` with `"host": "local"`. From there the store is encrypted and machine-local. ## What Local Mode delivers - An encrypted SQLite store holding projects, environments, secret shapes, current wrapped versions, one-use injection grants, and metadata-only local audit events. - Machine root-key custody via the OS keystore: macOS Keychain, Windows DPAPI, or Linux `secret-tool`, with a documented `0600` fallback file where no keystore is available. - The core commands: `secrets set`, `secrets list`, `secrets versions`, and `run --variable-key`. - Local `.env` import with a dry-run plan. - The local plaintext file removal helper. A minimal local loop: ```sh insecur secrets set DATABASE_URL --value-stdin insecur secrets list insecur run --variable-key DATABASE_URL -- node server.js ``` ## The ceiling Local Mode is intentionally limited to projects and non-protected development environments. These features are hosted-only and do not exist locally: - Organizations, teams, and memberships - Protected environments - Machine access and app connections - Sync and production delivery - Profile-backed multi-secret injection policies; Local Mode runs one selected variable at a time Windows can store local secrets, but `run` currently fails closed there until descendant-process containment is implemented. Use macOS or Linux for runtime injection. Any hosted-only command fails fast with a clear `local.cloud_feature_unavailable` error. The failure is deliberate, not a bug: those capabilities require the hosted API. ## Projects and Git worktrees Commit the non-secret `.insecur.json` with the project's wrapped application command. A worktree on the same machine and OS user selects the same encrypted local value through the committed project and environment references. No dotenv copy is needed. The worktree's branch must contain that config; do not initialize a replacement project when it is missing. Current source builds find the nearest `.insecur.json` from the invocation directory up to the first `.git` file or directory. Discovery never follows a worktree's Git pointer to the primary checkout or crosses into a parent repository. Without a Git boundary, or without config inside it, the invocation directory remains the target. Invalid config fails instead of falling back. Reads and writes use that same selected config. Adding a secret from a subdirectory updates the project manifest, not a new shadow config. `scan`, development watch, and `agent setup` also use the discovered project directory. `init` is the exception: it targets the invocation directory unless `--config-dir` explicitly selects another directory. An explicit `--config-dir` always selects exactly that directory without ancestor discovery. It does not change the launched child's working directory or the meaning of relative import/file arguments. On released CLIs without discovery, run from the checkout root or use this explicit flag. Use `insecur config show --json` to inspect `projectConfigPath` and resolved scope. Explicit flags and scope environment variables can override the config, so verify them before using a key. Missing values stop execution before the child starts; insecur does not substitute an ambient key or search another project. This does not prevent the child itself from reading other files. On another machine, run `insecur init --host local` against the committed config to adopt its metadata. Values must be supplied there separately. The [agent quickstart](/docs/agent-quickstart) contains the complete adoption and verification procedure. ## Moving to hosted later When you are ready to try the hosted prelaunch service, log in and migrate the current Local Mode project. The migration verifies every hosted write before it removes the corresponding local value. If the hosted project already exists, the CLI adopts it and reports any values that still exist only on this machine. The hosted protected-environment path is not approved for valuable production secrets yet. ```sh insecur login insecur projects migrate ``` ## Related - [Migrating from .env files](/docs/migrate-dotenv) - [Running commands with secrets](/docs/run) - [Scanning for exposed secrets](/docs/scan) - [Using insecur with coding agents](/docs/agents) --- Source: https://insecur.cloud/docs/audit.md # Audit and verification Every meaningful action in insecur writes a tenant-scoped, metadata-only audit event: who acted, what resource, when, the event code, and the full principal chain including agent attribution. Audit events never contain secret values. You read the feed live with `insecur audit tail`, and you produce signed, independently verifiable bundles with `insecur audit export`. Anyone can check a bundle offline with `insecur audit verify`. ## Tail recent events ```sh insecur audit tail --limit 50 ``` `audit tail` prints recent events, newest activity first. All fields are metadata. | Flag | Purpose | | ---------------------------------- | ----------------------------------------- | | `--limit ` | Number of events to return. Default `25`. | | `--from ` | Only events at or after this time. | | `--to ` | Only events at or before this time. | | `--cursor ` | Continue from a previous page. | | `--actor-user-id ` | Filter to a human actor. | | `--actor-machine-identity-id ` | Filter to a machine identity. | | `--project-id ` | Filter to a project. | | `--env-id ` | Filter to an environment. | | `--event-code ` | Filter to a single event code. | Example, filtering to one environment and event code: ```sh insecur audit tail --env-id env_2b9 --event-code secret.version.promoted --json ``` A representative event, metadata only: ```json { "eventCode": "secret.version.promoted", "occurredAt": "2026-07-09T14:02:11Z", "resource": { "type": "secret_version", "id": "sv_7c1" }, "principalChain": [ { "type": "user", "id": "usr_18a" }, { "type": "agent", "tag": "release-bot" } ] } ``` ## Export a signed bundle ```sh insecur audit export --from 2026-07-01T00:00:00Z --to 2026-07-09T00:00:00Z ``` Both `--from` and `--to` are required. The export produces JSONL events plus a signed manifest. Signing uses Ed25519, and the signing keys are custodied server-side in the private Runtime deploy. The bundle is tamper-evident and independently verifiable. ## Verify a bundle offline ```sh insecur audit verify events.jsonl --manifest manifest.json ``` `audit verify` recomputes the bundle over the JSONL and checks it against the signed manifest, offline. You supply the verifying key material through one of these flags. | Flag | Purpose | | ------------------------------------- | ---------------------------------------------------- | | `--published-signing-keys ` | Path to the published signing-keys document. | | `--published-signing-keys-env ` | Env var holding the published signing-keys document. | | `--signing-public-key-env ` | Env var holding a single Ed25519 public key. | | `--hmac-secret-env ` | Env var holding the HMAC secret for the bundle. | ## Published signing keys Current and historical Ed25519 public keys are published at: ```sh https://insecur.cloud/.well-known/insecur/audit-export-signing-keys.json ``` This is a metadata-only document. It lets anyone verify a bundle without contacting the API, which is why the claim ceiling here is exactly this: exports are tamper-evident and independently verifiable. Fetch the published keys and verify in one flow: ```sh export INSECUR_AUDIT_EXPORT_PUBLISHED_SIGNING_KEYS="$(cat published-keys.json)" insecur audit verify events.jsonl \ --manifest manifest.json \ --published-signing-keys-env INSECUR_AUDIT_EXPORT_PUBLISHED_SIGNING_KEYS ``` ## The console audit view The web console has a filterable audit view at the org level. The CLI and the console read the same events, so what you filter in one you can reproduce in the other. ## Related - [Approvals and step-up](/docs/approvals) - [Environment variables](/docs/reference/environment-variables) - [API overview](/docs/reference/api) - [Exit codes](/docs/reference/exit-codes) --- Source: https://insecur.cloud/docs/approvals.md # Approvals and step-up Some actions are deliberately not completable from a CLI or an agent session. Protected changes require a human step-up, a High-Assurance Challenge, cleared by a person in the web console with fresh step-up evidence. Agents cannot clear protected gates by design. ## How the gate behaves When a protected action is attempted, the API returns the error code `auth.high_assurance_required` with an operation id, and the CLI exits with code `10` (human step-up required). The channel split is intentional: - The CLI or agent channel can plan, request, and poll. - Only a human in the web console can clear the gate, with fresh step-up evidence (passkey or MFA via WorkOS). So the agent-side flow is: trigger the action, get back an operation id, then poll that operation until a human clears it or it reaches another terminal state. ## Poll and read operations ```sh insecur operations wait op_4f2 --json --timeout 600 ``` `operations wait` polls until the operation reaches a terminal state. If it does not resolve within `--timeout `, the command exits `9` with `operation.wait_timeout`. ```sh insecur operations get op_4f2 --json ``` `operations get` reads operation state once, without waiting. ```sh insecur operations cancel op_4f2 ``` `operations cancel` cancels a cancelable operation. ## List approval requests ```sh insecur approvals list --env-id env_2b9 ``` `approvals list` returns metadata-only approval request status for an environment: which requests are pending, and their target resources. ## Approve or deny in the console Humans clear challenges in the web console approvals inbox at `app.insecur.cloud`. The inbox has: - A pending challenges list. - A detail view with metadata evidence: the actor chain, the target resources, and staleness of the request. - Approve, which requires a per-action step-up. - Deny, which is one click. The evidence in the detail view is metadata only. It never reveals a secret value. ## Common CLI actions that hit this gate Two secrets actions commonly flow into the step-up gate. Promote draft versions (a protected promotion request): ```sh insecur secrets promote sv_7c1 sv_7c2 --env-id env_2b9 --comment "release 0.4" ``` | Promote flag | Purpose | | ---------------------------------- | -------------------------------------------- | | `--env-id ` | Target environment. | | `--comment ` | Human-readable note attached to the request. | | `--impact-review-fingerprint ` | Bind the request to a reviewed impact set. | | `--operation ` | Continue or reference an existing operation. | Roll back to a prior version: ```sh insecur secrets rollback sec_09d --to-version-id sv_7b0 --comment "revert bad promote" ``` `secrets rollback` requires `--to-version-id `, and also accepts `--promote` and `--comment`. ## A full step-up loop ```sh insecur secrets promote sv_7c1 --env-id env_2b9 --json # exits 10, prints an operation id when a human step-up is required insecur operations wait op_4f2 --json --timeout 900 # blocks until a human approves or denies in the console ``` ## Related - [Audit and verification](/docs/audit) - [Exit codes](/docs/reference/exit-codes) - [Errors](/docs/reference/errors) - [API overview](/docs/reference/api) --- Source: https://insecur.cloud/docs/reference/environment-variables.md # Environment variables The `insecur` CLI reads these environment variables. They are grouped by what they affect. Where scope is concerned, precedence runs flags first, then environment, then project config (`.insecur.json`), then profile. ## Scope resolution These select which host, org, project, environment, and profile the CLI operates against. A matching command-line flag always overrides the environment value. | Variable | Purpose | | ----------------- | -------------------------------------------------- | | `INSECUR_HOST` | API base URL. Default `https://api.insecur.cloud`. | | `INSECUR_ORG` | Organization to operate in (opaque id). | | `INSECUR_PROJECT` | Project to operate in (opaque id). | | `INSECUR_ENV` | Environment to operate in (opaque id). | | `INSECUR_PROFILE` | Named profile to resolve scope and auth from. | ## Authentication These carry credentials for non-interactive use, such as CI or an agent session. | Variable | Purpose | | ------------------------------- | -------------------------------------------------------- | | `INSECUR_SESSION_TOKEN` | Session credential supplied directly in the environment. | | `INSECUR_AGENT_CREDENTIAL_FILE` | Path to a sealed derived-agent credential file. | | `INSECUR_AGENT_TAG` | Agent attribution tag recorded in the principal chain. | ## Config location These control where the CLI reads and writes its own configuration. The user config lives at `~/.insecur/config.json`. Project config lives at `.insecur.json`, which is committed, non-secret, and holds opaque ids only. | Variable | Purpose | | --------------------- | ---------------------------------------------------------------------- | | `INSECUR_CONFIG_HOME` | Base directory for user config. Falls back to `HOME` or `USERPROFILE`. | ## Crash reporting and output | Variable | Purpose | | -------------------------------- | ------------------------------------------------------------- | | `INSECUR_CRASH_REPORTS` | Set to `off` to disable crash reporting. | | `INSECUR_CLI_SENTRY_DSN` | Override the CLI crash-reporting Sentry DSN. | | `INSECUR_CLI_SENTRY_ENVIRONMENT` | Override the environment label attached to CLI crash reports. | | `INSECUR_ASCII` | Force ASCII glyphs in output. | ## Audit export verification These hold key material for `insecur audit verify`. You do not read them directly; you pass their names to the matching `--*-env` flags of `audit verify`. | Variable | Purpose | | --------------------------------------------- | --------------------------------------------------------------------------- | | `INSECUR_AUDIT_EXPORT_HMAC_SECRET` | HMAC secret, passed via `--hmac-secret-env`. | | `INSECUR_AUDIT_EXPORT_SIGNING_PUBLIC_KEY` | Single Ed25519 public key, passed via `--signing-public-key-env`. | | `INSECUR_AUDIT_EXPORT_PUBLISHED_SIGNING_KEYS` | Published signing-keys document, passed via `--published-signing-keys-env`. | ## Installer These are read by the install scripts, not by the CLI at runtime. | Variable | Purpose | | -------------------------- | ------------------------------------------------- | | `INSECUR_CLI_VERSION` | Release tag to install, for example `cli-v0.2.0`. | | `INSECUR_INSTALL_DIR` | Install destination directory. | | `INSECUR_INSTALL_BASE_URL` | Base URL for the binary and checksums. | ## Example Non-interactive scope plus a session token for CI: ```sh export INSECUR_HOST=https://api.insecur.cloud export INSECUR_ORG=org_1a2 export INSECUR_PROJECT=prj_3c4 export INSECUR_ENV=env_5d6 export INSECUR_SESSION_TOKEN=... # supplied by your CI secret store insecur whoami --json ``` Values shown are opaque ids. Secret values never appear in configuration or CLI output. ## Related - [Installation](/docs/installation) - [Audit and verification](/docs/audit) - [Exit codes](/docs/reference/exit-codes) - [API overview](/docs/reference/api) --- Source: https://insecur.cloud/docs/reference/api.md # API overview The public API base is `https://api.insecur.cloud`. All product routes live under `/v1`. The CLI is the supported client. This page documents the API surface for orientation, not as a stable public contract. It is pre-1.0 and may change. ## Conventions - Organization-scoped routes are `/v1/orgs/:organizationId/...`. - All ids are opaque resource ids, never names. - Responses are metadata-only envelopes. - Success looks like `{ "ok": true, "data": ..., "meta": ... }`. - Failures use RFC 9457-style bodies with a stable `code`, a `retryable` flag, a `type` URI of the form `https://insecur.dev/errors/`, and often machine-readable remediation. Stored customer Secret Values never appear in any response body. The one delivery path is grant consumption inside the private Runtime deploy. Short-lived CLI credentials are returned only in a response header, never a body. ## Authentication Most API routes use short-lived CLI session credentials sent in a request header. Runtime Injection also accepts verified short-lived Machine Access Tokens. Browser sessions live in the web console BFF, not on the public API. ## Success envelope ```json { "ok": true, "data": { "id": "prj_3c4", "environments": ["env_5d6"] }, "meta": { "requestId": "req_9f0" } } ``` ## Error body ```json { "type": "https://insecur.dev/errors/auth-high-assurance-required", "code": "auth.high_assurance_required", "retryable": false, "detail": "This action requires a human step-up.", "operationId": "op_4f2" } ``` ## Route groups Documented at the group level only. | Method(s) | Prefix | Purpose | | --------- | -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | | GET | `/healthz` | Liveness. | | Various | `/v1/auth` | CLI login flows: AuthKit PKCE authorize and exchange, device authorization. | | Various | `/v1/session` | whoami, agent derive and register, memberships, revoke. | | Various | `/v1/instance/bootstrap` | Instance bootstrap status and operator claim. | | POST | `/v1/onboarding` | Guided personal organization provisioning. | | POST | `/v1/orgs/:organizationId/organizations` | Create an organization in the current tenant context. | | Various | `/v1/orgs/:organizationId/projects` | Projects, environments, secrets metadata, blind writes, possession checks, protected promotion and rollback, machine identities, injection grants. | | Various | `/v1/orgs/:organizationId/projects/:projectId/environments/:environmentId/secret-syncs` | Alpha Secret Sync create, update, and run routes. | | POST | `/v1/orgs/:organizationId/runtime-injection` | Issue runtime injection grants. | | Various | `/v1/orgs/:organizationId/run-policies` | Runtime injection policies: create, show, disable. | | Various | `/v1/orgs/:organizationId/connections` | App connections: list, create, status, reauth, rotate, disconnect. | | Various | `/v1/orgs/:organizationId/approval-requests`, `/v1/orgs/:organizationId/high-assurance-challenges` | Approvals and human step-up. | | GET | `/v1/orgs/:organizationId/audit-events`, `/v1/orgs/:organizationId/audit-export` | Audit feed and signed export. | | Various | `/v1/orgs/:organizationId/operations` | Long-running operation state: get, wait, cancel. | | Various | `/v1/orgs/:organizationId/webhook-subscriptions` | Webhook subscription management. | | Various | `/v1/orgs/:organizationId/members`, `/v1/orgs/:organizationId/invitations` | Membership metadata. | | GET | `/v1/orgs/:organizationId/first-value-usage` | Onboarding usage counters. | | POST | `/v1/orgs/:organizationId/design-partner-feedback` | Metadata-only design-partner feedback tied to a request or operation. | ## Errors and exit codes The CLI maps API error codes to process exit codes. See the errors reference for the code catalog and the exit-codes reference for how those map to CLI exit status. ## Related - [Errors](/docs/reference/errors) - [Exit codes](/docs/reference/exit-codes) - [Environment variables](/docs/reference/environment-variables) - [Audit and verification](/docs/audit) --- Source: https://insecur.cloud/docs/reference/exit-codes.md # Exit codes Every `insecur` command exits with one of these codes. They are stable: scripts and agents can branch on them. The exit code is derived from the failure's stable error code; the [error reference](/docs/reference/errors) lists the exact mapping per code. | Exit code | Meaning | | --------- | ---------------------------------------------------------------------------------------- | | `0` | success | | `1` | unexpected failure | | `2` | invalid usage or validation error | | `3` | authentication required or expired | | `4` | authorization denied | | `5` | not found or intentionally indistinguishable forbidden/not found | | `6` | conflict or idempotency mismatch | | `7` | action required: provider error, or `scan --strict` findings | | `8` | rate limited or retryable upstream failure | | `9` | operation incomplete | | `10` | human step-up required (a High-Assurance Challenge the acting credential cannot satisfy) | Exit code `10` deserves special note for agents: it means a human step-up is required. The `--json` error body includes the operation id; poll it with `insecur operations wait --json` while a human clears the gate in the web console. See [Approvals and step-up](/docs/approvals). ## Related - [Error codes](/docs/reference/errors) - [CLI overview](/docs/cli) --- Source: https://insecur.cloud/docs/reference/errors.md # Error codes Failures carry a stable dotted error code (for example `auth.required`) that never changes with message wording. In HTTP responses the code also appears as an RFC 9457 `type` URI, `https://insecur.dev/errors/`, which resolves to a landing page for that error. CLI `--json` error envelopes include the code, a `retryable` flag, and remediation commands when one exists. HTTP status `n/a (client-side)` marks codes that never cross the network. | Error code | Exit | HTTP | Remediation | Notes | | ------------------------------------------------------------------------------------------------------------------ | ---- | ------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [`auth.required`](/errors/auth-required) | `3` | `401` | required | Session expired or absent. | | [`auth.config_invalid`](/errors/auth-config-invalid) | `1` | `503` | - | Auth Worker bindings are missing or invalid; names the configuration class only. | | [`auth.expired`](/errors/auth-expired) | `3` | `401` | required | Session expired. | | [`auth.invalid`](/errors/auth-invalid) | `3` | `401` | required | Session invalid. | | [`auth.reauth_required`](/errors/auth-reauth-required) | `3` | `401` | required | Fresh re-authentication required. | | [`auth.mfa_enrollment_required`](/errors/auth-mfa-enrollment-required) | `3` | `401` | - | No eligible MFA factor enrolled (ADR-0032). | | [`auth.insufficient_scope`](/errors/auth-insufficient-scope) | `4` | `403` | - | Missing Authorization Scope. | | [`auth.oidc_wrong_audience`](/errors/auth-oidc-wrong-audience) | `4` | `403` | - | GitHub Actions OIDC audience does not match configured trust. | | [`auth.oidc_wrong_repository`](/errors/auth-oidc-wrong-repository) | `4` | `403` | - | GitHub Actions OIDC repository claim does not match configured trust. | | [`auth.oidc_wrong_environment`](/errors/auth-oidc-wrong-environment) | `4` | `403` | - | GitHub Actions OIDC environment claim does not match configured trust. | | [`auth.oidc_untrusted_source`](/errors/auth-oidc-untrusted-source) | `3` | `401` | - | GitHub Actions OIDC token failed verification or issuer trust. | | [`auth.deploy_key_invalid`](/errors/auth-deploy-key-invalid) | `3` | `401` | - | Environment Deploy Key secret failed verification or runtime policy key is not allowlisted. | | [`auth.deploy_key_disabled`](/errors/auth-deploy-key-disabled) | `4` | `403` | - | Environment Deploy Key is disabled. | | [`auth.deploy_key_wrong_environment`](/errors/auth-deploy-key-wrong-environment) | `4` | `403` | - | Environment Deploy Key is not authorized for the requested project and environment. | | [`auth.deploy_key_overbroad_scope`](/errors/auth-deploy-key-overbroad-scope) | `4` | `403` | - | Environment Deploy Key credential scopes exceed the Runtime Injection bundle. | | [`auth.high_assurance_required`](/errors/auth-high-assurance-required) | `10` | `401` | required | Step-up handoff, not a failure (ADR-0032). | | [`auth.device_authorization_expired`](/errors/auth-device-authorization-expired) | `3` | `401` | required | Device-authorization user code expired before approval; re-run `insecur login --device` (ADR-0010). | | [`auth.device_authorization_denied`](/errors/auth-device-authorization-denied) | `4` | `403` | - | Device-authorization request was denied at the verification page (ADR-0010). | | [`validation.invalid_opaque_resource_id`](/errors/validation-invalid-opaque-resource-id) | `2` | `400` | required | Validation of an opaque resource ID (server-side, plus CLI-side argument parsing). CLI remediation carries a `suggestedFix` to copy the full id from `--json` or `--full` output instead of the truncated table cell. | | [`validation.invalid_variable_key`](/errors/validation-invalid-variable-key) | `2` | `400` | - | Server-side Variable Key format validation. | | [`validation.invalid_command_input`](/errors/validation-invalid-command-input) | `2` | `400` | - | CLI `run` missing or invalid command after `--`; API request-body validation (PKCE exchange, run-completed `childExitCode`). | | [`validation.request_body_too_large`](/errors/validation-request-body-too-large) | `2` | `413` | - | Public API request body exceeds the bounded JSON envelope limit and is rejected before analytics, abuse accounting, authentication, RPC, or persistence. | | [`validation.invalid_display_name`](/errors/validation-invalid-display-name) | `2` | `400` | - | Server-side Display Name validation. | | [`validation.display_name_empty`](/errors/validation-display-name-empty) | `2` | `400` | - | Server-side empty Display Name validation. | | [`validation.invalid_profile_slug`](/errors/validation-invalid-profile-slug) | `2` | `n/a (client-side)` | - | CLI Profile Slug must be lower-kebab. | | [`cli.profile_not_found`](/errors/cli-profile-not-found) | `5` | `n/a (client-side)` | - | CLI Profile slug or opaque ID does not exist in local user config. | | [`cli.profile_slug_in_use`](/errors/cli-profile-slug-in-use) | `6` | `n/a (client-side)` | - | CLI Profile Slug already exists in local user config. | | [`cli.display_name_not_found`](/errors/cli-display-name-not-found) | `5` | `n/a (client-side)` | - | Display Name Resolution found zero exact matches in the scoped list (ADR-0035). | | [`cli.display_name_ambiguous`](/errors/cli-display-name-ambiguous) | `2` | `n/a (client-side)` | - | Display Name Resolution found two or more exact matches in the scoped list (ADR-0035). | | [`cli.parent_scope_unresolved`](/errors/cli-parent-scope-unresolved) | `2` | `n/a (client-side)` | required | Parent Organization, Project, or Environment scope is not pinned before child Display Name Resolution. | | [`cli.destructive_id_required`](/errors/cli-destructive-id-required) | `2` | `n/a (client-side)` | - | Irreversible or destructive action requires an opaque ID for non-interactive callers (ADR-0035). | | [`cli.scoped_selector_not_found`](/errors/cli-scoped-selector-not-found) | `5` | `n/a (client-side)` | - | Configured or explicit opaque ID is absent from the refreshed Scoped List in the authorized scope. | | [`cli.validation_error`](/errors/cli-validation-error) | `2` | `n/a (client-side)` | required | CLI argument parsing failure: unknown command, unknown option, missing required option, or invalid option value. Remediation carries the corrected `usage` invocation and a `suggestedFix`. | | [`cli.unexpected_error`](/errors/cli-unexpected-error) | `1` | `n/a (client-side)` | required | Unexpected client-side CLI failure after argument parsing. Remediation carries a `suggestedFix` pointing at `--verbose` for full error detail. | | [`validation.invalid_feedback_kind`](/errors/validation-invalid-feedback-kind) | `2` | `400` | - | Design-partner feedback kind is not one of the supported metadata-only values. | | [`validation.invalid_feedback_note_code`](/errors/validation-invalid-feedback-note-code) | `2` | `400` | - | Design-partner feedback note must be one of the supported metadata-only note codes. | | [`validation.feedback_association_required`](/errors/validation-feedback-association-required) | `2` | `400` | - | Design-partner feedback must reference a grant, operation, or request ID. | | [`validation.feedback_association_not_found`](/errors/validation-feedback-association-not-found) | `2` | `404` | - | Design-partner feedback references an operation or request ID that does not exist in the Organization. | | [`secret.input_required`](/errors/secret-input-required) | `2` | `400` | required | Secret value input is required; remediation carries the `secrets set --value-stdin` usage and a `suggestedFix` (mentioning `--generate random` only for minting a new random secret). | | [`secret.invalid_encoding`](/errors/secret-invalid-encoding) | `2` | `400` | - | | | [`secret.invalid_input_mode`](/errors/secret-invalid-input-mode) | `2` | `400` | - | Mutually exclusive or unsupported Secret input mode options. | | [`secret.value_too_large`](/errors/secret-value-too-large) | `2` | `400` | - | | | [`secret.empty_value`](/errors/secret-empty-value) | `2` | `400` | - | | | [`secret.coordinate_invalid`](/errors/secret-coordinate-invalid) | `5` | `404` | - | Resource-shaped denial; URL environment not owned by URL project collapses with not-found into HTTP `404` so the write path is not an existence oracle. | | [`environment.invalid_lifecycle_stage`](/errors/environment-invalid-lifecycle-stage) | `2` | `400` | - | Environment lifecycle stage is not a supported posture tier. | | [`environment.protected_environment`](/errors/environment-protected-environment) | `4` | `403` | - | Non-protected secret writes are blocked for Protected Environments. | | [`environment.non_protected_environment`](/errors/environment-non-protected-environment) | `4` | `403` | - | Protected draft secret writes are blocked for non-Protected Environments. | | [`environment.lifecycle_immutable`](/errors/environment-lifecycle-immutable) | `2` | `400` | - | Lifecycle stage and protected posture cannot change after creation. | | [`environment.preview_opt_down_invalid`](/errors/environment-preview-opt-down-invalid) | `2` | `400` | - | Preview opt-down evidence is invalid or scoped to the wrong lifecycle stage. | | [`environment.not_found`](/errors/environment-not-found) | `5` | `404` | - | Environment not found for the tenant-qualified coordinate. | | [`onboarding.already_provisioned`](/errors/onboarding-already-provisioned) | `6` | `409` | - | Personal Organization already provisioned. | | [`onboarding.resource_conflict`](/errors/onboarding-resource-conflict) | `6` | `409` | - | Guided-provisioning resource conflict. | | [`onboarding.not_instance_operator`](/errors/onboarding-not-instance-operator) | `6` | `403` | - | Acting user is not the Instance Operator for the requested action. | | [`onboarding.invitation_invalid`](/errors/onboarding-invitation-invalid) | `6` | `400` | - | Invitation input or role preset is invalid. | | [`onboarding.invitation_not_pending`](/errors/onboarding-invitation-not-pending) | `6` | `409` | - | Invitation is not pending or lost a compare-and-set race. | | [`onboarding.invitation_invitee_mismatch`](/errors/onboarding-invitation-invitee-mismatch) | `6` | `403` | - | Accepting user does not match the invitation invitee. | | [`onboarding.membership_already_exists`](/errors/onboarding-membership-already-exists) | `6` | `409` | - | Invitee already holds membership for the invitation scope. | | [`bootstrap.already_bootstrapped`](/errors/bootstrap-already-bootstrapped) | `6` | `409` | - | Instance bootstrap already completed. | | [`bootstrap.not_bootstrapped`](/errors/bootstrap-not-bootstrapped) | `5` | `404` | - | Instance is not bootstrapped. | | [`bootstrap.claim_not_available`](/errors/bootstrap-claim-not-available) | `5` | `404` | - | No pending Bootstrap Operator Claim or default team is missing. | | [`bootstrap.already_claimed`](/errors/bootstrap-already-claimed) | `6` | `409` | - | Bootstrap Operator Claim is already consumed. | | [`bootstrap.invalid_secret`](/errors/bootstrap-invalid-secret) | `3` | `401` | - | Bootstrap Secret verification failed. | | [`bootstrap.authenticated_actor_required`](/errors/bootstrap-authenticated-actor-required) | `3` | `401` | - | Bootstrap claim requires a WorkOS-resolved human actor. | | [`store.runtime_config_missing`](/errors/store-runtime-config-missing) | `1` | `503` | - | Runtime configuration unavailable; control-plane state, not caller input. | | [`store.unavailable`](/errors/store-unavailable) | `8` | `503` | - | Transient database connection-layer failure (Hyperdrive pool exhaustion, server shutdown, connection loss); safe to retry after a short delay. | | [`storage.gate_blocked`](/errors/storage-gate-blocked) | `1` | `503` | - | Storage Security Gate blocked production delivery before decrypt or provider write. | | [`storage.gate_unknown`](/errors/storage-gate-unknown) | `1` | `503` | - | Storage Security Gate readiness evidence is missing or unreachable for production delivery. | | [`crypto.decrypt_failed`](/errors/crypto-decrypt-failed) | `1` | `500` | - | Opaque single failure; HTTP `500` must not differentiate by cause ([ADR-0062](https://github.com/zaks-io/insecur/blob/main/docs/adr/0062-package-seam-failures-are-errorbody-compatible.md) amendment). | | [`crypto.root_key_not_configured`](/errors/crypto-root-key-not-configured) | `1` | `503` | - | Instance root key material is not configured. | | [`crypto.tenant_data_key_not_ready`](/errors/crypto-tenant-data-key-not-ready) | `1` | `503` | - | Active tenant data keys are missing or not usable; control-plane readiness, not caller input. | | [`crypto.invalid_aad_field`](/errors/crypto-invalid-aad-field) | `2` | `400` | - | Additional authenticated data field failed charset validation. | | [`audit.event_invalid`](/errors/audit-event-invalid) | `2` | `400` | - | Audit event payload failed metadata validation. | | [`audit.export_entry_limit_exceeded`](/errors/audit-export-entry-limit-exceeded) | `2` | `400` | - | Audit export time range matches more entries than a single export bundle allows; narrow the range and retry. | | [`high_assurance.evidence_missing`](/errors/high-assurance-evidence-missing) | `10` | `401` | - | Cleared challenge evidence is absent; fail closed to fresh step-up (ADR-0032). | | [`high_assurance.evidence_expired`](/errors/high-assurance-evidence-expired) | `10` | `401` | - | Challenge evidence validity window elapsed; fresh step-up required (ADR-0032). | | [`high_assurance.operation_mismatch`](/errors/high-assurance-operation-mismatch) | `5` | `404` | - | Challenge evidence is not bound to the requested operation. | | [`high_assurance.actor_mismatch`](/errors/high-assurance-actor-mismatch) | `4` | `403` | - | Clearing user is not authorized for this bounded operation. | | [`high_assurance.already_consumed`](/errors/high-assurance-already-consumed) | `10` | `401` | - | Single-use challenge evidence was already consumed. | | [`high_assurance.clearing_denied`](/errors/high-assurance-clearing-denied) | `4` | `403` | - | Clearing user lacks scope or operation state rejects clearing. | | [`high_assurance.session_assurance_failed`](/errors/high-assurance-session-assurance-failed) | `3` | `401` | - | WorkOS session assurance did not satisfy fresh high-assurance factor posture (INS-49). | | [`high_assurance.invalid_risk_reason`](/errors/high-assurance-invalid-risk-reason) | `2` | `400` | - | Unknown or malformed high-assurance risk reason code. | | [`abuse.rate_limited`](/errors/abuse-rate-limited) | `8` | `429` | - | Public-edge abuse control; retry after the configured window. | | [`import.unsupported_environment`](/errors/import-unsupported-environment) | `2` | `n/a (client-side)` | - | | | [`import.existing_secret`](/errors/import-existing-secret) | `6` | `409` | - | Existing-secret conflict in the target Environment (preflight, create-only, or version-conditional write). | | [`import.parse_error`](/errors/import-parse-error) | `2` | `n/a (client-side)` | - | Dotenv line does not split into key=value. | | [`import.duplicate_variable_key`](/errors/import-duplicate-variable-key) | `2` | `n/a (client-side)` | - | Duplicate final Variable Key in the import source. | | [`backup_restore.not_armed`](/errors/backup-restore-not-armed) | `1` | `503` | - | Restore entrypoint called while the RESTORE_DB arming binding is absent (ADR-0084 fail-closed default). | | [`backup_restore.target_is_live`](/errors/backup-restore-target-is-live) | `1` | `503` | - | RESTORE_DB points at the normal database target; restore refuses before any statement runs (ADR-0084). | | [`backup_restore.target_not_fresh`](/errors/backup-restore-target-not-fresh) | `6` | `409` | - | Restore target failed the fresh-target proof (journal marker, instance identity, or organizations already present). Discard the target and retry on a fresh one. | | [`backup_restore.import_conflict`](/errors/backup-restore-import-conflict) | `6` | `409` | - | Another restore import holds the target's exclusion lock or journal marker (ADR-0084 at-most-one import per target). | | [`backup_restore.artifact_not_found`](/errors/backup-restore-artifact-not-found) | `5` | `404` | - | No sealed scheduled-export artifact exists at the named reference. | | [`backup_restore.artifact_invalid`](/errors/backup-restore-artifact-invalid) | `2` | `400` | - | Sealed artifact is malformed or failed authenticated decryption under the AAD-bound instance ID. | | [`backup_restore.header_mismatch`](/errors/backup-restore-header-mismatch) | `2` | `400` | - | Advisory header pre-check failed fast (format marker, instance, or root key version); trust still derives from the AEAD open. | | [`backup_restore.export_operation_mismatch`](/errors/backup-restore-export-operation-mismatch) | `6` | `409` | - | Export success evidence is missing, hash-mismatched, or does not link the artifact to its source export Operation. | | [`backup_restore.manifest_incomplete`](/errors/backup-restore-manifest-incomplete) | `2` | `400` | - | Payload rows and the header organization manifest disagree, or the recovery-canary sentinel organization is absent. | | [`backup_restore.unsupported_table`](/errors/backup-restore-unsupported-table) | `2` | `400` | - | Artifact names a table outside the export-table registry (unsupported newer export version); fails closed before any row import. | | [`backup_restore.schema_mismatch`](/errors/backup-restore-schema-mismatch) | `6` | `409` | - | Restore target is missing migrated export-registry tables or columns the exported rows require. | | [`backup_restore.export_failed`](/errors/backup-restore-export-failed) | `1` | `500` | - | Scheduled export failed before durable success evidence was recorded. | | [`backup_restore.import_failed`](/errors/backup-restore-import-failed) | `1` | `500` | - | Restore import failed mid-run; the run is terminal, the target is never repaired in place — discard it and retry on a fresh target. | | [`injection.grant_denied`](/errors/injection-grant-denied) | `4` | `404` | - | | | [`runtime_policy.not_found`](/errors/runtime-policy-not-found) | `5` | `404` | - | Runtime Injection Policy or version not found for the tenant-qualified coordinate. | | [`runtime_policy.display_name_in_use`](/errors/runtime-policy-display-name-in-use) | `6` | `409` | - | Policy Display Name already exists in the target Environment. | | [`runtime_policy.invalid_bindings`](/errors/runtime-policy-invalid-bindings) | `2` | `400` | - | Policy bindings are missing, duplicate, or not exact opaque IDs / Variable Keys. | | [`runtime_policy.pattern_binding_rejected`](/errors/runtime-policy-pattern-binding-rejected) | `2` | `400` | - | Wildcard, prefix, suffix, regex, tag, folder, or other broad secret selection is rejected. | | [`runtime_policy.secret_binding_not_found`](/errors/runtime-policy-secret-binding-not-found) | `5` | `404` | - | Bound secret ID does not exist in the policy's organization and project scope. | | [`runtime_policy.secret_binding_environment_mismatch`](/errors/runtime-policy-secret-binding-environment-mismatch) | `2` | `400` | - | Bound secret ID exists in the organization but belongs to a different Environment than the policy. `400` (not `404`) is a deliberate intra-tenant carve-out per ADR-0062: the configurer is already scope-authorized, so distinguishing wrong-env from not-found is not an existence oracle. | | [`runtime_policy.version_immutable`](/errors/runtime-policy-version-immutable) | `6` | `409` | - | Used Runtime Injection Policy Versions cannot be mutated. | | [`runtime_policy.protected_use_blocked`](/errors/runtime-policy-protected-use-blocked) | `4` | `403` | - | Protected Environment policy use blocked until machine custody and Storage Security Gate readiness are satisfied. | | [`runtime_policy.disabled`](/errors/runtime-policy-disabled) | `4` | `403` | - | Runtime Injection Policy is disabled. | | [`injection.command_fingerprint_mismatch`](/errors/injection-command-fingerprint-mismatch) | `2` | `n/a (client-side)` | - | | | [`injection.decrypt_failed`](/errors/injection-decrypt-failed) | `1` | `n/a (client-side)` | - | Integrity failure; never silently retried. | | [`injection.grant_expired`](/errors/injection-grant-expired) | `6` | `404` | - | Resource-shaped denial; HTTP `404` so it is not a resource-existence oracle, even though the exit differs. | | [`injection.unreachable`](/errors/injection-unreachable) | `8` | `n/a (client-side)` | - | Retryable. | | [`approval.review_stale`](/errors/approval-review-stale) | `6` | `n/a (client-side)` | - | Approval Request stays pending. | | [`approval.request_not_found`](/errors/approval-request-not-found) | `5` | `404` | - | Approval Request not found for the tenant-qualified ID. | | [`approval.request_not_pending`](/errors/approval-request-not-pending) | `6` | `409` | - | Approval Request is not pending or lost a compare-and-set race. | | [`approval.invalid_draft_selection`](/errors/approval-invalid-draft-selection) | `2` | `400` | - | Promote body lists Draft Version IDs that are missing, not draft, or not in the target Environment. | | [`approval.wildcard_selection_rejected`](/errors/approval-wildcard-selection-rejected) | `2` | `400` | - | Wildcard or all-staged draft selection tokens are rejected at the API edge. | | [`approval.promotion_change_set_immutable`](/errors/approval-promotion-change-set-immutable) | `6` | `409` | - | Promotion Change Set is immutable after the Approval Request is created. | | [`approval.rollback_target_not_eligible`](/errors/approval-rollback-target-not-eligible) | `2` | `400` | - | Rollback target version is not a retained published version eligible for copy. | | [`approval.draft_version_not_discardable`](/errors/approval-draft-version-not-discardable) | `2` | `400` | - | Draft Version Discard target is not found, or is not currently a draft (already promoted or discarded elsewhere). | | [`operation.not_found`](/errors/operation-not-found) | `5` | `404` | - | Operation not found for the tenant-qualified ID. | | [`operation.idempotency_mismatch`](/errors/operation-idempotency-mismatch) | `6` | `409` | - | Same idempotency key reused with a different intent code (ADR-0066). | | [`operation.invalid_intent`](/errors/operation-invalid-intent) | `2` | `400` | - | Unknown or malformed operation intent code. | | [`operation.invalid_metadata`](/errors/operation-invalid-metadata) | `2` | `400` | - | Metadata-only progress or lease input failed validation. | | [`operation.stale_transition`](/errors/operation-stale-transition) | `6` | `409` | - | Compare-and-set transition lost a concurrent state change. | | [`operation.invalid_transition`](/errors/operation-invalid-transition) | `2` | `400` | - | State transition is not allowed by the operation state machine. | | [`operation.terminal_state`](/errors/operation-terminal-state) | `6` | `409` | - | Operation is already in a terminal state. | | [`operation.not_cancelable`](/errors/operation-not-cancelable) | `6` | `409` | - | Operation in the current state cannot be canceled. | | [`operation.not_retryable`](/errors/operation-not-retryable) | `6` | `409` | - | Operation in the current state cannot be retried. | | [`operation.wait_timeout`](/errors/operation-wait-timeout) | `9` | `n/a (client-side)` | - | `operations wait --timeout` expired before the operation left a non-terminal state; remediation points back at the same wait command. | | [`operation.stale_fencing_token`](/errors/operation-stale-fencing-token) | `6` | `409` | - | Sync target lease fencing token is stale or does not match the operation binding. | | [`operation.lease_not_held`](/errors/operation-lease-not-held) | `6` | `409` | - | No active sync target lease exists for the requested target. | | [`operation.lease_required`](/errors/operation-lease-required) | `2` | `400` | - | Sync target lease fencing token is required for this operation transition. | | [`connection.not_found`](/errors/connection-not-found) | `5` | `404` | - | App Connection not found for the tenant-qualified ID. | | [`connection.resource_conflict`](/errors/connection-resource-conflict) | `6` | `409` | - | App Connection ID or unique setup constraint already exists. | | [`connection.disconnected`](/errors/connection-disconnected) | `7` | `n/a (client-side)` | - | App Connection is disconnected; sync execution fails closed until reconnected. | | [`connection.reauthorization_required`](/errors/connection-reauthorization-required) | `7` | `n/a (client-side)` | - | App Connection requires provider reauthorization before sync execution. | | [`connection.pending_setup`](/errors/connection-pending-setup) | `7` | `n/a (client-side)` | - | App Connection setup is incomplete; sync execution fails closed. | | [`connection.provider_registration_missing`](/errors/connection-provider-registration-missing) | `7` | `n/a (client-side)` | - | Required Provider App Registration is missing for the Instance and connection method. | | [`connection.credential_missing`](/errors/connection-credential-missing) | `7` | `n/a (client-side)` | - | Credential-backed App Connection lacks an active encrypted provider credential. | | [`connection.validation_failed`](/errors/connection-validation-failed) | `7` | `n/a (client-side)` | - | Cloudflare scoped-token validation failed; connection remains non-writeable until current evidence succeeds. | | [`connection.boundary_mismatch`](/errors/connection-boundary-mismatch) | `2` | `n/a (client-side)` | - | Cloudflare token scope does not match the pinned account or Worker script boundary. | | [`connection.invalid_connection_method`](/errors/connection-invalid-connection-method) | `2` | `400` | - | App Connection operation targets an unsupported provider or connection method. | | [`sync.not_found`](/errors/sync-not-found) | `5` | `404` | - | Secret Sync not found for the tenant-qualified ID. | | [`sync.disabled`](/errors/sync-disabled) | `4` | `403` | - | Secret Sync is disabled and cannot execute. | | [`sync.invalid_bindings`](/errors/sync-invalid-bindings) | `2` | `400` | - | Secret Sync binding set failed validation. | | [`sync.pattern_binding_rejected`](/errors/sync-pattern-binding-rejected) | `2` | `400` | - | Pattern, wildcard, or inventory-based bindings are rejected. | | [`sync.secret_binding_not_found`](/errors/sync-secret-binding-not-found) | `5` | `404` | - | Bound secret not found in the source Environment. | | [`sync.secret_binding_environment_mismatch`](/errors/sync-secret-binding-environment-mismatch) | `2` | `400` | - | Bound secret belongs to a different Environment. | | [`sync.invalid_destination`](/errors/sync-invalid-destination) | `2` | `400` | - | Provider destination or target configuration is invalid. | | [`sync.resource_conflict`](/errors/sync-resource-conflict) | `6` | `409` | - | Secret Sync ID or unique setup constraint already exists. | | [`sync.connection_not_eligible`](/errors/sync-connection-not-eligible) | `7` | `n/a (client-side)` | - | App Connection is not eligible for this Secret Sync. | | [`sync.display_name_in_use`](/errors/sync-display-name-in-use) | `6` | `409` | - | Display name already used by another Secret Sync in scope. | | [`notification.invalid_event_code`](/errors/notification-invalid-event-code) | `2` | `400` | - | Webhook subscription event type is missing or not selectable. | | [`notification.subscription_not_found`](/errors/notification-subscription-not-found) | `5` | `404` | - | Webhook subscription not found for the tenant-qualified ID. | | [`notification.delivery_failed`](/errors/notification-delivery-failed) | `1` | `500` | - | Event notification delivery failed for a subscribed webhook. | | [`notification.signing_secret_missing`](/errors/notification-signing-secret-missing) | `1` | `500` | - | Active webhook signing secret is missing for delivery or rotation. | | [`provider_app_registration.not_found`](/errors/provider-app-registration-not-found) | `5` | `404` | - | Provider App Registration not found for the Instance and connection method. | | [`provider_app_registration.not_configured`](/errors/provider-app-registration-not-configured) | `7` | `n/a (client-side)` | - | Provider App Registration exists but instance setup is incomplete. | | [`provider_app_registration.already_exists`](/errors/provider-app-registration-already-exists) | `6` | `409` | - | Provider App Registration already exists for the Instance and connection method. | | [`protected_change.not_found`](/errors/protected-change-not-found) | `5` | `404` | - | Protected Change not found for the tenant-qualified ID. | | [`protected_change.invalid_transition`](/errors/protected-change-invalid-transition) | `2` | `400` | - | State transition is not allowed by the Protected Change state machine. | | [`protected_change.terminal_state`](/errors/protected-change-terminal-state) | `6` | `409` | - | Protected Change is already in a terminal state. | | [`protected_change.active_change_exists`](/errors/protected-change-active-change-exists) | `6` | `409` | - | Another active Protected Change already exists for the Protected Environment. | | [`protected_change.missing_evidence`](/errors/protected-change-missing-evidence) | `2` | `400` | - | Required approval evidence metadata is missing. | | [`protected_change.requester_mismatch`](/errors/protected-change-requester-mismatch) | `4` | `403` | - | Acting credential is not the Protected Change requester. | | [`protected_change.non_protected_environment`](/errors/protected-change-non-protected-environment) | `4` | `403` | - | Protected Changes require a Protected Environment. | | [`protected_change.approval_not_authorized`](/errors/protected-change-approval-not-authorized) | `4` | `403` | - | Protected delivery execution has no current authorizing approval evidence (rejected, canceled, stale-closed, or not yet approved). | | [`protected_change.delivery_target_mismatch`](/errors/protected-change-delivery-target-mismatch) | `4` | `403` | - | Approval evidence was issued for a different tenant, project, Protected Environment, operation, or target than the requested protected delivery execution. | | [`provider.reauth_required`](/errors/provider-reauth-required) | `7` | `n/a (client-side)` | - | | | [`provider.unavailable`](/errors/provider-unavailable) | `7` | `n/a (client-side)` | - | | | [`provider.lookup_not_found`](/errors/provider-lookup-not-found) | `7` | `n/a (client-side)` | - | | | [`provider.permission_denied`](/errors/provider-permission-denied) | `7` | `n/a (client-side)` | - | | | [`provider.boundary_mismatch`](/errors/provider-boundary-mismatch) | `2` | `n/a (client-side)` | - | The requested target falls outside the pinned Connection Boundary; fix the configuration, not the provider. | | [`sync.provider_value_too_large`](/errors/sync-provider-value-too-large) | `2` | `n/a (client-side)` | - | Validation-side pre-write failure. | | [`sync.source_value_missing`](/errors/sync-source-value-missing) | `2` | `n/a (client-side)` | - | Validation-side pre-write failure. | | [`sync.provider_drift`](/errors/sync-provider-drift) | `7` | `n/a (client-side)` | - | Provider-side `action_required` failure; needs reauthorization or an approved configuration change. | | [`sync.target_busy`](/errors/sync-target-busy) | `8` | `n/a (client-side)` | - | Retryable lease contention. | | [`sync.stale_plan`](/errors/sync-stale-plan) | `7` | `n/a (client-side)` | - | Sync Execution Revalidation found the plan no longer matches current sync configuration, App Connection state, or Explicit Provider Lookup status; re-plan before execution. No provider write starts. | | [`sync.overwrite_status_unknown`](/errors/sync-overwrite-status-unknown) | `2` | `n/a (client-side)` | - | Warning code; exits `2` only when required operation-scoped confirmation is absent, otherwise the run proceeds. | | [`sync.provider_delete_incomplete`](/errors/sync-provider-delete-incomplete) | `0` | `n/a (client-side)` | - | Warning code on a `completed_with_warnings` operation; not a failure. | | [`local.cloud_feature_unavailable`](/errors/local-cloud-feature-unavailable) | `4` | `n/a (client-side)` | - | Hosted-only capability invoked in Local Mode; remediation carries exact upgrade commands. | | [`local_store.unavailable`](/errors/local-store-unavailable) | `7` | `n/a (client-side)` | required | No supported OS credential store is available. Local Mode fails closed instead of silently storing its root key beside ciphertext; remediation explains Linux Secret Service setup and the explicit development-only opt-in. | | [`local.value_missing_on_machine`](/errors/local-value-missing-on-machine) | `2` | `n/a (client-side)` | - | Second-machine auto-adopt reports Variable Keys without local values; remediation lists exact `secrets set` commands. | | [`migrate.remote_diverged`](/errors/migrate-remote-diverged) | `6` | `409` | - | Remote Secret exists but possession check failed during migrate reconcile; nothing written. | | [`delivery_policy.not_configured`](/errors/delivery-policy-not-configured) | `7` | `409` | - | No Delivery Risk Policy record exists for the Project; automation resolution fails closed until one is selected (ADR-0043). | | [`delivery_policy.preset_invalid`](/errors/delivery-policy-preset-invalid) | `2` | `400` | - | Preset is not one of `strict`, `balanced`, `automation_friendly`. | | [`delivery_policy.preset_version_unsupported`](/errors/delivery-policy-preset-version-unsupported) | `2` | `400` | - | Preset template version is missing or not supported by this build; automation fails closed. | | [`delivery_policy.actor_invalid`](/errors/delivery-policy-actor-invalid) | `4` | `403` | - | Delivery Risk Policy configuration requires an authenticated human actor; machine and missing actors are denied (ADR-0043). | | [`delivery_policy.scope_invalid`](/errors/delivery-policy-scope-invalid) | `2` | `400` | - | Tenant, project, or environment scope is missing or inconsistent for the delivery policy action. | | [`delivery_policy.preview_automation_opt_in_required`](/errors/delivery-policy-preview-automation-opt-in-required) | `4` | `403` | - | Balanced preset allows preview automation only after explicit Preview Automation Opt-In for the exact preview Environment. | | [`delivery_policy.preview_automation_not_allowed`](/errors/delivery-policy-preview-automation-not-allowed) | `4` | `403` | - | Strict preset requires human review for preview delivery; preview automation is denied regardless of opt-in records. | | [`delivery_policy.protected_approval_required`](/errors/delivery-policy-protected-approval-required) | `4` | `403` | - | Protected Environments always require protected delivery approval evidence; no preset grants automation there. | | [`delivery_policy.opt_in_environment_invalid`](/errors/delivery-policy-opt-in-environment-invalid) | `2` | `400` | - | Preview Automation Opt-In applies only to non-protected preview Environments. | | [`delivery_policy.opt_in_not_found`](/errors/delivery-policy-opt-in-not-found) | `5` | `404` | - | No active Preview Automation Opt-In exists for the Environment. | | [`secret.possession_mismatch`](/errors/secret-possession-mismatch) | `6` | `409` | - | Server-side possession check verdict: candidate value does not match stored Secret; metadata-only, no digests or similarity scores. | ## Related - [Exit codes](/docs/reference/exit-codes) - [API overview](/docs/reference/api) --- Source: https://insecur.cloud/docs/cli/index.md # CLI overview insecur CLI — metadata-only output, sealed local session auth Install with `curl -fsSL https://insecur.cloud/install.sh | sh` (see [Installation](/docs/installation)). Product commands support `--json` for metadata-only machine-readable output and exit with a [stable exit code](/docs/reference/exit-codes). Failures carry stable [error codes](/docs/reference/errors) with remediation commands in `--json` output. Secret values are never accepted as command-line arguments and never appear in any output. `insecur guide` is the intentional exception to JSON output: it emits offline Markdown playbooks. ## Commands | Command | Description | | ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------- | | [`insecur agent`](/docs/cli/agent) | Agent harness attribution and child sessions | | [`insecur approvals`](/docs/cli/approvals) | Metadata-only approval request status | | [`insecur audit`](/docs/cli/audit) | Audit event feed and export verification | | [`insecur config`](/docs/cli/config) | Local CLI configuration | | [`insecur connections`](/docs/cli/connections) | Manage org-scoped App Connections (metadata only) | | [`insecur describe`](/docs/cli/describe) | Describe the CLI command contract as metadata | | [`insecur envs`](/docs/cli/envs) | Environment navigation and creation | | [`insecur guide`](/docs/cli/guide) | Offline CLI guides (markdown playbooks, no auth required) | | [`insecur import`](/docs/cli/import) | Import secrets from a local dotenv file into a development environment (create-only; all-or-nothing preflight) | | [`insecur init`](/docs/cli/init) | Provision guided organization defaults and write .insecur.json | | [`insecur local-files`](/docs/cli/local-files) | Local plaintext secret file utilities (metadata-only; no secure erasure) | | [`insecur login`](/docs/cli/login) | Authenticate with WorkOS AuthKit PKCE and mint a short-lived CLI credential | | [`insecur logout`](/docs/cli/logout) | End the CLI session locally and revoke the server session | | [`insecur operations`](/docs/cli/operations) | Poll, wait on, and cancel long-running operations | | [`insecur orgs`](/docs/cli/orgs) | Organization navigation | | [`insecur projects`](/docs/cli/projects) | Project navigation and creation | | [`insecur run`](/docs/cli/run) | Run a command with runtime injection from a CLI profile policy or one exact variable key | | [`insecur run-policies`](/docs/cli/run-policies) | Manage Runtime Injection Policies (metadata only) | | [`insecur scan`](/docs/cli/scan) | Offline project-scoped secret exposure report (metadata only) | | [`insecur secrets`](/docs/cli/secrets) | Blind secret writes and metadata-only management | | [`insecur shell`](/docs/cli/shell) | Start a subshell with INSECUR_SESSION_TOKEN in the environment | | [`insecur whoami`](/docs/cli/whoami) | Report acting human, session validity, resolved context, and attribution tier | ## Global flags These flags are accepted globally. `--json` does not change `insecur guide`, which always emits offline Markdown. | Option | Description | | --------------------- | ----------------------------------------------------------------- | | `--host ` | insecur API host | | `--org-id ` | organization opaque id | | `--project-id ` | project opaque id | | `--env-id ` | environment opaque id | | `--profile ` | CLI profile slug | | `--profile-id ` | CLI profile opaque id | | `--config-dir ` | directory containing .insecur.json | | `--agent ` | agent attribution tag (Tier 3) | | `--json` | metadata-only JSON output | | `--quiet` | suppress non-essential human output | | `--verbose` | verbose logging | | `--color` | force colored human output | | `--no-color` | disable colored human output | | `--full` | show full opaque ids in tables instead of truncating | | `--no-crash-reports` | disable default-on sanitized CLI crash reporting for this command | | `-V, --version` | output the version number | ## Related - [Quickstart](/docs/quickstart) - [Environment variables](/docs/reference/environment-variables) --- Source: https://insecur.cloud/docs/cli/agent.md # insecur agent Agent harness attribution and child sessions ```sh insecur agent [options] [command] ``` ## `insecur agent status` Report agent readiness, resolved context, capabilities, and exact next actions ```sh insecur agent status [options] ``` ## `insecur agent setup` Install or verify project-local agent instructions and scan hooks ```sh insecur agent setup [options] ``` | Option | Description | | ------------------ | -------------------------------------------------------- | | `--harness ` | agent harness: codex or claude (required) | | `--mode ` | scan hook mode: advisory or strict (default: `advisory`) | | `--dry-run` | report the files that would change | | `--check` | exit 7 when managed agent setup has drifted | ## `insecur agent shell` Run a command in a deny-by-default child environment with a derived agent session ```sh insecur agent shell [options] ``` | Option | Description | | ------------------------ | ------------------------------------------------------------------------------------ | | `--allow ` | comma-separated task capabilities: secrets:list, secrets:set, run, operations:cancel | | `--ttl ` | derived session lifetime from 60 to 86400 seconds | ## `insecur agent env` Print metadata-only shell exports for a separately launched agent harness ```sh insecur agent env [options] ``` | Option | Description | | ------------------------ | ------------------------------------------------------------------------------------ | | `--allow ` | comma-separated task capabilities: secrets:list, secrets:set, run, operations:cancel | | `--ttl ` | derived session lifetime from 60 to 86400 seconds | ## `insecur agent register` Register a structural agent session for audit attribution ```sh insecur agent register [options] ``` ## Related - [CLI overview and global flags](/docs/cli) - [Exit codes](/docs/reference/exit-codes) - [Error codes](/docs/reference/errors) --- Source: https://insecur.cloud/docs/cli/approvals.md # insecur approvals Metadata-only approval request status ```sh insecur approvals [options] [command] ``` ## `insecur approvals list` List approval requests for an environment ```sh insecur approvals list [options] ``` | Option | Description | | --------------- | ---------------------------- | | `--env-id ` | target environment opaque id | ## Related - [CLI overview and global flags](/docs/cli) - [Exit codes](/docs/reference/exit-codes) - [Error codes](/docs/reference/errors) --- Source: https://insecur.cloud/docs/cli/audit.md # insecur audit Audit event feed and export verification ```sh insecur audit [options] [command] ``` ## `insecur audit tail` Show recent tenant-bounded audit events (metadata-only) ```sh insecur audit tail [options] ``` | Option | Description | | ---------------------------------- | ----------------------------------------- | | `--limit ` | maximum events to return (default 25) | | `--from ` | include events at or after this timestamp | | `--to ` | include events before this timestamp | | `--cursor ` | pagination cursor from a prior response | | `--actor-user-id ` | filter by actor user id | | `--actor-machine-identity-id ` | filter by actor machine identity id | | `--project-id ` | filter by project id | | `--env-id ` | filter by environment id | | `--event-code ` | filter by audit event code | ## `insecur audit export` Export tenant-bounded audit events as JSONL with a signed manifest ```sh insecur audit export [options] ``` | Option | Description | | ------------------ | ----------------------------------------------------- | | `--from ` | include events at or after this timestamp (required) | | `--to ` | include events at or before this timestamp (required) | ## `insecur audit verify` Verify a tamper-evident audit export JSONL bundle and manifest ```sh insecur audit verify [options] ``` | Argument | Description | | -------- | -------------------------- | | `jsonl` | path to audit export JSONL | | Option | Description | | ------------------------------------- | ------------------------------------------------------------------ | | `--manifest ` | path to audit export manifest JSON (required) | | `--hmac-secret-env ` | env var holding the audit export HMAC secret | | `--signing-public-key-env ` | env var holding the published audit export signing public key | | `--published-signing-keys ` | path or URL to the published audit export signing public keys JSON | | `--published-signing-keys-env ` | env var holding the path or URL to published signing public keys | ## Related - [CLI overview and global flags](/docs/cli) - [Exit codes](/docs/reference/exit-codes) - [Error codes](/docs/reference/errors) --- Source: https://insecur.cloud/docs/cli/config.md # insecur config Local CLI configuration ```sh insecur config [options] [command] ``` ## `insecur config show` Show resolved local CLI configuration (metadata-only) ```sh insecur config show [options] ``` ## `insecur config set` Write durable local CLI configuration ```sh insecur config set [options] ``` | Argument | Description | | -------- | ------------------------------------------------------------------ | | `key` | config key (default-env-id, branch-env., or crash-reports) | | `value` | config value | ## Related - [CLI overview and global flags](/docs/cli) - [Exit codes](/docs/reference/exit-codes) - [Error codes](/docs/reference/errors) --- Source: https://insecur.cloud/docs/cli/connections.md # insecur connections Manage org-scoped App Connections (metadata only) ```sh insecur connections [options] [command] ``` ## `insecur connections list` List App Connections for the selected organization ```sh insecur connections list [options] ``` ## `insecur connections create` Create an App Connection via provider authorization or scoped token input ```sh insecur connections create [options] ``` | Argument | Description | | ---------- | ------------------------------------------ | | `provider` | provider slug (github, cloudflare, vercel) | | Option | Description | | -------------------------------- | ---------------------------------------------------------------- | | `--connection-id ` | client-minted app connection opaque id (required) | | `--method ` | connection method (github-app, scoped-api-token, ...) (required) | | `--display-name-stdin` | read the Display Name from stdin | | `--value-stdin` | read provider token from stdin (credential-backed methods) | | `--token ` | REJECTED: provider tokens must not be passed on argv | | `--allow-account-id ` | Cloudflare allowed account id (boundary) | | `--allow-worker-script ` | Cloudflare allowed Worker script (boundary) | | `--installation-id ` | GitHub App installation id (boundary) | | `--owner ` | GitHub owner login (boundary) | | `--allowed-repositories ` | comma-separated GitHub repository names (boundary) | | `--operation ` | resume after High-Assurance Challenge clearance | ## `insecur connections status` Show metadata-only App Connection status ```sh insecur connections status [options] ``` | Argument | Description | | --------------- | ------------------------ | | `connection-id` | app connection opaque id | ## `insecur connections rotate` Rotate credential-backed App Connection provider credentials ```sh insecur connections rotate [options] ``` | Argument | Description | | --------------- | ------------------------ | | `connection-id` | app connection opaque id | | Option | Description | | ------------------ | ---------------------------------------------------- | | `--dry-run` | validate the active credential without replacing it | | `--value-stdin` | read replacement provider token from stdin | | `--token ` | REJECTED: provider tokens must not be passed on argv | | `--operation ` | resume after High-Assurance Challenge clearance | ## `insecur connections reauth` Reauthorize an App Connection with audit ```sh insecur connections reauth [options] ``` | Argument | Description | | --------------- | ------------------------ | | `connection-id` | app connection opaque id | | Option | Description | | -------------------------------- | -------------------------------------------------- | | `--installation-id ` | GitHub App installation id (boundary override) | | `--owner ` | GitHub owner login (boundary override) | | `--allowed-repositories ` | comma-separated GitHub repository names (boundary) | | `--operation ` | resume after High-Assurance Challenge clearance | ## `insecur connections disconnect` Disconnect an App Connection with audit ```sh insecur connections disconnect [options] ``` | Argument | Description | | --------------- | ------------------------ | | `connection-id` | app connection opaque id | ## Related - [CLI overview and global flags](/docs/cli) - [Exit codes](/docs/reference/exit-codes) - [Error codes](/docs/reference/errors) --- Source: https://insecur.cloud/docs/cli/describe.md # insecur describe Describe the CLI command contract as metadata ```sh insecur describe [options] [command-path...] ``` | Argument | Description | | -------------- | ---------------------------- | | `command-path` | space-separated command path | ## Related - [CLI overview and global flags](/docs/cli) - [Exit codes](/docs/reference/exit-codes) - [Error codes](/docs/reference/errors) --- Source: https://insecur.cloud/docs/cli/envs.md # insecur envs Environment navigation and creation ```sh insecur envs [options] [command] ``` ## `insecur envs list` List environments in the resolved project ```sh insecur envs list [options] ``` ## `insecur envs create` Create a non-protected development environment ```sh insecur envs create [options] ``` | Option | Description | | -------------------------------- | -------------------------------------------------------------------- | | `--env-id ` | client-minted environment opaque id | | `--display-name-stdin` | read the Display Name from stdin | | `--copy-shapes-from-env-id ` | copy Secret Shapes only from another environment in the same project | ## Related - [CLI overview and global flags](/docs/cli) - [Exit codes](/docs/reference/exit-codes) - [Error codes](/docs/reference/errors) --- Source: https://insecur.cloud/docs/cli/guide.md # insecur guide Offline CLI guides (markdown playbooks, no auth required) ```sh insecur guide [options] [topic] ``` | Argument | Description | | -------- | ------------------------------------ | | `topic` | guide topic id (omit to list topics) | ## Related - [CLI overview and global flags](/docs/cli) - [Exit codes](/docs/reference/exit-codes) - [Error codes](/docs/reference/errors) --- Source: https://insecur.cloud/docs/cli/import.md # insecur import Import secrets from a local dotenv file into a development environment (create-only; all-or-nothing preflight) ```sh insecur import [options] ``` | Argument | Description | | -------- | --------------------------- | | `file` | local dotenv file to import | | Option | Description | | -------------------------------- | ------------------------------------------------------------------ | | `--dry-run` | run Import Preflight and return a metadata-only Secret Import Plan | | `--variable-key-prefix ` | prepend this prefix to every parsed dotenv key before validation | ## Related - [CLI overview and global flags](/docs/cli) - [Exit codes](/docs/reference/exit-codes) - [Error codes](/docs/reference/errors) --- Source: https://insecur.cloud/docs/cli/init.md # insecur init Provision guided organization defaults and write .insecur.json ```sh insecur init [options] ``` | Option | Description | | ----------------------- | --------------------------------------------- | | `--profile-slug ` | local CLI profile slug (default: `local-dev`) | ## Related - [CLI overview and global flags](/docs/cli) - [Exit codes](/docs/reference/exit-codes) - [Error codes](/docs/reference/errors) --- Source: https://insecur.cloud/docs/cli/local-files.md # insecur local-files Local plaintext secret file utilities (metadata-only; no secure erasure) ```sh insecur local-files [options] [command] ``` ## `insecur local-files rm` Delete a local file after explicit confirmation (ordinary filesystem delete) ```sh insecur local-files rm [options] ``` | Argument | Description | | -------- | ------------------------- | | `path` | local file path to delete | | Option | Description | | ------- | ---------------------------------------- | | `--yes` | skip the interactive confirmation prompt | ## Related - [CLI overview and global flags](/docs/cli) - [Exit codes](/docs/reference/exit-codes) - [Error codes](/docs/reference/errors) --- Source: https://insecur.cloud/docs/cli/login.md # insecur login Authenticate with WorkOS AuthKit PKCE and mint a short-lived CLI credential ```sh insecur login [options] ``` | Option | Description | | ------------------------------ | --------------------------------------------------------------------------------------------------------- | | `--no-open` | print the WorkOS login URL instead of opening a browser | | `--callback-port ` | localhost callback port for PKCE login | | `--callback-timeout ` | seconds to wait for the loopback PKCE callback (default: 300) | | `--no-persist` | keep the session credential in process memory only instead of the sealed local session store | | `--shell` | start a managed interactive shell with the session credential in the child environment only | | `--device` | use the OAuth device-authorization flow for headless or remote shells that cannot open a loopback browser | | `--agent-session` | mint the session agent-marked (only valid with --device) | ## Related - [CLI overview and global flags](/docs/cli) - [Exit codes](/docs/reference/exit-codes) - [Error codes](/docs/reference/errors) --- Source: https://insecur.cloud/docs/cli/logout.md # insecur logout End the CLI session locally and revoke the server session ```sh insecur logout [options] ``` ## Related - [CLI overview and global flags](/docs/cli) - [Exit codes](/docs/reference/exit-codes) - [Error codes](/docs/reference/errors) --- Source: https://insecur.cloud/docs/cli/operations.md # insecur operations Poll, wait on, and cancel long-running operations ```sh insecur operations [options] [command] ``` ## `insecur operations get` Read metadata-only operation state ```sh insecur operations get [options] ``` | Argument | Description | | -------------- | ------------------- | | `operation-id` | operation opaque id | ## `insecur operations wait` Poll until the operation reaches a terminal state ```sh insecur operations wait [options] ``` | Argument | Description | | -------------- | ------------------- | | `operation-id` | operation opaque id | | Option | Description | | --------------------- | ---------------------------------------------- | | `--timeout ` | fail with operation.wait_timeout when exceeded | ## `insecur operations watch` Stream operation state changes until terminal or ready to resume ```sh insecur operations watch [options] ``` | Argument | Description | | -------------- | ------------------- | | `operation-id` | operation opaque id | | Option | Description | | --------------------- | ---------------------------------------------- | | `--timeout ` | exit with operation incomplete when exceeded | | `--jsonl` | emit one versioned JSON event per state change | ## `insecur operations cancel` Cancel a cancelable operation ```sh insecur operations cancel [options] ``` | Argument | Description | | -------------- | ------------------- | | `operation-id` | operation opaque id | ## Related - [CLI overview and global flags](/docs/cli) - [Exit codes](/docs/reference/exit-codes) - [Error codes](/docs/reference/errors) --- Source: https://insecur.cloud/docs/cli/orgs.md # insecur orgs Organization navigation ```sh insecur orgs [options] [command] ``` ## `insecur orgs list` List organizations for the authenticated session ```sh insecur orgs list [options] ``` ## Related - [CLI overview and global flags](/docs/cli) - [Exit codes](/docs/reference/exit-codes) - [Error codes](/docs/reference/errors) --- Source: https://insecur.cloud/docs/cli/projects.md # insecur projects Project navigation and creation ```sh insecur projects [options] [command] ``` ## `insecur projects list` List projects in the resolved organization ```sh insecur projects list [options] ``` ## `insecur projects create` Create a project with a client-minted opaque ID ```sh insecur projects create [options] ``` | Option | Description | | ---------------------- | -------------------------------- | | `--project-id ` | client-minted project opaque id | | `--display-name-stdin` | read the Display Name from stdin | ## `insecur projects migrate` Migrate this Local Mode project to a Hosted Instance (one-way, verified-then-clean) ```sh insecur projects migrate [options] ``` | Option | Description | | --------------------------- | ------------------------------------------------------------------------------ | | `--org-id ` | target organization opaque id | | `--confirm-migrate` | scoped confirmation: verify every value remotely, then delete local copies | | `--yes` | answers ordinary prompts only; it cannot confirm a migration | | `--skip-key ` | keep the remote value for a diverged Variable Key (repeatable) (default: `[]`) | ## Related - [CLI overview and global flags](/docs/cli) - [Exit codes](/docs/reference/exit-codes) - [Error codes](/docs/reference/errors) --- Source: https://insecur.cloud/docs/cli/run.md # insecur run Run a command with runtime injection from a CLI profile policy or one exact variable key ```sh insecur run [options] [profile] ``` | Argument | Description | | --------- | ------------------------------------------------ | | `profile` | CLI profile slug or id (uses defaultRunPolicyId) | | Option | Description | | ---------------------- | ------------------------------------------------------------------------------- | | `--variable-key ` | application variable key to inject (First Value path) | | `--policy-id ` | runtime injection policy id (overrides profile default) | | `--watch` | restart the child on file changes (development environment only) | | `--plan` | resolve targets and prerequisites without issuing a grant or starting the child | ## Related - [CLI overview and global flags](/docs/cli) - [Exit codes](/docs/reference/exit-codes) - [Error codes](/docs/reference/errors) --- Source: https://insecur.cloud/docs/cli/run-policies.md # insecur run-policies Manage Runtime Injection Policies (metadata only) ```sh insecur run-policies [options] [command] ``` ## `insecur run-policies create` Create an immutable Runtime Injection Policy Version and set the active pointer ```sh insecur run-policies create [options] ``` | Option | Description | | ------------------------------ | -------------------------------------------------- | | `--policy-id ` | client-minted runtime policy opaque id (required) | | `--env-id ` | target environment opaque id | | `--display-name-stdin` | read the Display Name from stdin | | `--command ` | approved command shape (required) | | `--command-fingerprint ` | command fingerprint (sha256:...) | | `--secret-ids ` | comma-separated exact secret opaque ids (required) | | `--operation ` | resume after High-Assurance Challenge clearance | ## `insecur run-policies show` Show runtime injection policy metadata ```sh insecur run-policies show [options] ``` | Argument | Description | | ----------- | ------------------------ | | `policy-id` | runtime policy opaque id | ## `insecur run-policies disable` Disable a runtime injection policy with audit ```sh insecur run-policies disable [options] ``` | Argument | Description | | ----------- | ------------------------ | | `policy-id` | runtime policy opaque id | | Option | Description | | ------------------ | ----------------------------------------------- | | `--env-id ` | environment opaque id | | `--comment ` | audit comment (required) | | `--operation ` | resume after High-Assurance Challenge clearance | ## Related - [CLI overview and global flags](/docs/cli) - [Exit codes](/docs/reference/exit-codes) - [Error codes](/docs/reference/errors) --- Source: https://insecur.cloud/docs/cli/scan.md # insecur scan Offline project-scoped secret exposure report (metadata only) ```sh insecur scan [options] ``` | Option | Description | | ----------------------------- | ------------------------------------------------------------------------------------------ | | `--strict` | exit with code 7 when likely secrets or transcript exposures are found | | `--machine` | also scan documented well-known home-directory credential locations (read-only, opt-in) | | `--agent-transcripts` | scan local agent conversation logs and transcript exports for secret exposure evidence | | `--agent-projects` | discover agent-touched code directories from local conversations, then scan those projects | | `--transcript-path ` | explicit transcript or log file to scan (repeatable) | | `--transcript-glob ` | glob pattern for exported transcript files (repeatable) | ## Related - [CLI overview and global flags](/docs/cli) - [Exit codes](/docs/reference/exit-codes) - [Error codes](/docs/reference/errors) --- Source: https://insecur.cloud/docs/cli/secrets.md # insecur secrets Blind secret writes and metadata-only management ```sh insecur secrets [options] [command] ``` ## `insecur secrets list` List Secret Shapes in the resolved environment (metadata only) ```sh insecur secrets list [options] ``` ## `insecur secrets versions` List version metadata for one Secret (metadata only) ```sh insecur secrets versions [options] ``` | Argument | Description | | ----------- | ---------------- | | `secret-id` | opaque Secret ID | ## `insecur secrets set` Create or update a non-protected secret by variable key ```sh insecur secrets set [options] ``` | Argument | Description | | -------------- | ----------- | | `variable-key` | | | Option | Description | | ------------------- | ------------------------------------------------------------------ | | `--generate [mode]` | service-generate a secret value (default mode: random) | | `--length ` | random byte length for --generate random (default: `32`) | | `--value-stdin` | read the secret value from stdin | | `--allow-empty` | allow an intentionally empty secret value | | `--dry-run` | plan the metadata-only write without collecting or sending a value | ## `insecur secrets promote` Request protected promotion for exact draft versions (metadata only) ```sh insecur secrets promote [options] ``` | Argument | Description | | ------------------ | ----------- | | `draft-version-id` | | | Option | Description | | ------------------------------------ | ----------------------------------------------- | | `--env-id ` | target environment opaque id | | `--comment ` | audit comment | | `--impact-review-fingerprint ` | resume fingerprint from prior review | | `--operation ` | resume after High-Assurance Challenge clearance | ## `insecur secrets rollback` Rollback a secret from a retained published version (metadata only) ```sh insecur secrets rollback [options] ``` | Argument | Description | | ----------- | ----------- | | `secret-id` | | | Option | Description | | ---------------------- | ------------------------------------------------------ | | `--env-id ` | target environment opaque id | | `--to-version-id ` | retained published secret version opaque id (required) | | `--promote` | create draft and request promotion approval | | `--comment ` | audit comment | | `--operation ` | resume after High-Assurance Challenge clearance | ## Related - [CLI overview and global flags](/docs/cli) - [Exit codes](/docs/reference/exit-codes) - [Error codes](/docs/reference/errors) --- Source: https://insecur.cloud/docs/cli/shell.md # insecur shell Start a subshell with INSECUR_SESSION_TOKEN in the environment ```sh insecur shell [options] ``` | Argument | Description | | --------- | ----------------------------- | | `profile` | CLI profile slug or opaque id | ## Related - [CLI overview and global flags](/docs/cli) - [Exit codes](/docs/reference/exit-codes) - [Error codes](/docs/reference/errors) --- Source: https://insecur.cloud/docs/cli/whoami.md # insecur whoami Report acting human, session validity, resolved context, and attribution tier ```sh insecur whoami [options] ``` ## Related - [CLI overview and global flags](/docs/cli) - [Exit codes](/docs/reference/exit-codes) - [Error codes](/docs/reference/errors)