q-ring
About
Quantum-inspired keyring for AI coding agents. Secure secrets with superposition, entanglement, tunneling, and teleportation — CLI + 44 MCP tools.
Details
- Author
- I4cTime
- GitHub stars
- 3
- Downloads
- 2,108
- Categories
- Developer Tools, Other, Productivity, AI, Security
Jump to
- Superposition: Store one key with multiple states (dev/staging/prod) that collapse based on context
- Entanglement: Link keys across projects so rotating one automatically updates them all
- Tunneling: Create ephemeral, in-memory secrets that self-destruct after a set time or read count
- Teleportation: Securely pack and share AES-256-GCM encrypted secret bundles
- Tamper-evident auditing: Every event is hash-chained and HMAC-anchored in the OS keyring — qring audit:verify catches edits, truncation, and whole-file rewrites
- Policy governance: A .q-ring.json file controls which MCP tools, keys, and commands an agent may touch, enforced at both the server and keyring level
- Seamless AI integration: 44 built-in MCP tools for native use in Cursor, Kiro, and Claude Code
Setting up with Highlight
This MCP is not yet compatible with Highlight’s one-click setup. However, you can still use it with Highlight by following these steps:
- Download and install Highlight from highlightai.com/download
- Navigate to the plugins tab and select "Add Custom Plugin"
-
Configure the plugin with the settings below
Plugin Name
q-ringCommand (node, npx, python, etc.)Please refer to the README for specific instructions on how to obtain API keys or other required environment variables.
- Enable "Start Automatically" if you want the plugin to start when Highlight launches
From the repository
Install the CLI, then add the MCP server to your client:
npm install -g @i4ctime/q-ring # or: brew install i4ctime/tap/qring
{
"mcpServers": {
"q-ring": {
"command": "qring-mcp"
}
}
}
No global install? Use npx directly in the config:
{
"mcpServers": {
"q-ring": {
"command": "npx",
"args": ["-y", "--package=@i4ctime/q-ring", "qring-mcp"]
}
}
}
get_secret
[secrets] Read the plaintext value of a single secret from the q-ring keyring. Use when an agent needs the actual credential to call an external API or inject into a runtime; prefer `inspect_secret` to see metadata only, `has_secret` for presence-only checks, and `exec_with_secrets` to run a command without exposing the value to chat. Side effects: collapses superposition (selects the per-env state) and writes a 'read' event to the audit log (observer effect). Subject to project tool/key policy and may be denied with a 'Policy Denied' message. Returns JSON `{ ok, data: { key, value } }` on success or an error message if missing/blocked.
list_secrets
[secrets] List secret keys and quantum metadata in the requested scope, never the values. Use to discover what secrets exist before reading or writing; pair with `inspect_secret` for full metadata on one key, `analyze_secrets` for usage trends, or `health_check` for decay/anomaly summaries. Read-only; safe to call repeatedly. Returns JSON `{ ok, data: { entries: [...] } }` where each entry has scope, key, stateKeys (env names if superposed), expired, stale, lifetimePercent, timeRemaining, entangledCount, accessCount.
set_secret
[secrets] Create or overwrite a single secret value, optionally with TTL/decay, per-env superposition, description, tags, and rotation hints. Use to add or update one key at a time; prefer `import_dotenv` for bulk .env ingest, `generate_secret` (with saveAs) to generate-and-store in one step, and `entangle_secrets` instead of duplicating the same value under two keys. Mutates the keyring (overwrites any existing value at the same key/scope), writes a 'write' event to the audit log, and triggers any matching hooks. Subject to tool policy. Returns a short confirmation text like '[scope] KEY saved' (or '[scope] KEY set for env:NAME' when `env` is provided).
delete_secret
[secrets] Permanently remove a secret value (and all its env states) from the keyring for the given scope. Use when a credential is being retired or was created in error; prefer `disentangle_secrets` to break a sync link without erasing values, `remove_hook` to detach lifecycle callbacks, and `tunnel_destroy` for ephemeral tunnels. Destructive and not undoable from q-ring (no built-in trash). Writes a 'delete' event to the audit log and fires matching hooks. Returns 'Deleted "KEY"' on success or a not-found error if the key did not exist in the requested scope. Subject to tool policy.
has_secret
[secrets] Check whether a secret exists in the requested scope without reading the value. Use as a cheap precondition before reading or writing — for example, to skip prompting the user for a key that is already configured. Prefer `inspect_secret` when you also need metadata. Read-only; does not record a 'read' in the audit log. Decay-aware: returns 'false' for expired secrets even though the value is still in the store. Returns the literal text 'true' or 'false'.
export_secrets
[secrets] Render multiple secrets as a single .env or JSON document for piping into another tool or file. Use to materialize secrets for a one-off export or copy; prefer `env_generate` when you want output driven by the project's `.q-ring.json` manifest, and `teleport_pack` for an encrypted bundle to share between machines. Reads values (collapses superposition for the requested env) and writes one 'export' event per included secret to the audit log. Returns the rendered text directly (no JSON wrapper). Returns an error if no secrets matched the filters. Values are surfaced in plaintext — handle with care.
import_dotenv
[secrets] Parse standard dotenv-formatted text and store each key/value pair into the keyring in one batch. Use when migrating an existing `.env` file into q-ring or onboarding a new project; prefer `set_secret` for a single key, and `teleport_unpack` to import an encrypted bundle. Mutates the keyring (one write per parsed key) and emits a 'write' audit event for each. Supports comments, single/double quotes, and `\n` escapes. Returns a multiline summary listing imported keys and any skipped (existing) keys; in dryRun mode no writes happen and the same summary is produced for review.
inspect_secret
[secrets] Show full metadata for a single secret — env states, decay window, entanglement links, access counters — without ever revealing the value. Use when you need to understand the shape of a key before reading it or to debug 'why is this expired/stale'; prefer `get_secret` for the actual value, `list_secrets` for a many-key overview, and `audit_log` for the full access timeline. Read-only; does not write a 'read' event since the value is not exposed. Returns pretty-printed JSON with fields: key, scope, type ('superposition'|'collapsed'), created, updated, accessCount, lastAccessed, environments, defaultEnv, decay { expired, stale, lifetimePercent, timeRemaining }, entangled, description, tags. Errors with not-found if the key is absent.
generate_secret
[secrets] Generate a cryptographically random secret using Node's CSPRNG and optionally store it in the keyring in one step. Use to create new credentials that you control (signing keys, internal tokens, passwords); for issuer-issued credentials (Stripe/OpenAI etc.) use `rotate_secret` to ask the upstream provider for a fresh key, and use `set_secret` for values you already have in hand. If `saveAs` is provided this mutates the keyring (one 'write' event) and returns a summary like 'Generated and saved as "KEY" (FORMAT, ~N bits entropy)'. Without `saveAs` the call is read-only and returns JSON `{ ok, data: { value } }` containing the freshly generated string.
entangle_secrets
[secrets] Link two keys (across the same or different scopes) so future writes/rotations of either propagate the same value to the other. Use when one logical credential lives under multiple names (e.g. `STRIPE_SECRET_KEY` global and project) and should never drift; prefer `set_secret` for unrelated values, and reverse the link with `disentangle_secrets` (does not delete values). Mutates only the metadata of both envelopes — the values themselves are not changed by this call. Idempotent: re-running on an already-entangled pair is a no-op. Subject to tool policy. Returns a short confirmation: 'Entangled: SOURCE <-> TARGET'.
disentangle_secrets
[secrets] Break the sync link between two previously entangled keys so future rotations no longer propagate. Use when one of the keys is being retired or should diverge intentionally; pair with `delete_secret` if you also want to erase one of the values, and use `entangle_secrets` to recreate the link. Mutates only metadata; the current values remain untouched. Safe and idempotent — running on a pair that was never linked returns success without effect. Subject to tool policy. Returns 'Disentangled: SOURCE </> TARGET'.
check_project
[project] Compare the keys declared in the project's `.q-ring.json` manifest against what is actually present in the keyring. Use as the canonical 'is this project ready to run' gate before starting a dev server, deploying, or onboarding a teammate; prefer `health_check` for a scope-wide decay sweep (no manifest), and `agent_scan` for multi-project scans with optional auto-rotation. Read-only; does not mutate the keyring or audit log materially beyond a 'list' read. Returns JSON `{ total, present, missing, expired, stale, ready, secrets: [...] }` where `ready` is true only when nothing is missing or expired. Errors with 'No secrets manifest found in .q-ring.json' if the project has no manifest.
env_generate
[project] Render a complete `.env` file body from the project's `.q-ring.json` manifest, resolving each declared key from the keyring. Use when a build step or local runtime needs a real `.env` materialized on disk and you want exactly the keys the manifest declares; prefer `export_secrets` when you want every key in scope (manifest-agnostic) and `exec_with_secrets` to inject secrets into a child process without writing them to a file. Reads values (records 'read' audit events) and collapses superposition for the requested env. Returns the raw `.env` text, with `# MISSING (required): KEY` / `# EXPIRED: KEY` / `# STALE: KEY` warnings appended as comments. Missing keys appear as commented-out `# KEY=` placeholders so the file remains a valid drop-in.
detect_environment
[project] Resolve which environment slug (e.g. 'dev', 'staging', 'prod') the current invocation should collapse to. Use before reading secrets when you want to mirror the same env q-ring would auto-pick (e.g. to log it, or to pass through to another tool); prefer passing an explicit `env` to `get_secret`/`env_generate` when you already know which env you want. Read-only; checks the QRING_ENV env var, NODE_ENV, the project's `.q-ring.json`, and the current git branch in priority order. Returns JSON `{ env, source }` (e.g. `{ env: 'dev', source: 'NODE_ENV' }`), or a plain message indicating that no env could be detected.
get_project_context
[agent] Return a single redacted snapshot of everything an AI agent typically wants to know about this project: secrets present (keys + metadata only), detected env, manifest declarations, configured providers, registered hooks, and recent audit activity. Use this as the very first call in a session to orient the agent before it asks for any individual secret; prefer `list_secrets` for a flat key listing, `check_project` for manifest-vs-keyring drift, and `audit_log` for a deeper access trail. Read-only and value-safe — no plaintext secret values are ever included. Returns a single pretty-printed JSON document; shape is intentionally broad and may grow over time, so read defensively.
tunnel_create
[tunnel] Stash a one-shot or short-lived secret in the q-ring server's process memory and return an ID that can be used to read it back. Use for handing a one-time value to another tool/process without persisting it (npm OTP codes, magic-link tokens, copy/paste between machines via a relay); prefer `set_secret` with `ttlSeconds` when you actually want a tracked, auditable secret. Mutates only in-memory state — the value never touches disk and is lost on server restart. Subject to tool policy. Returns JSON `{ ok, data: { id } }` where `id` is an opaque string to pass to `tunnel_read`/`tunnel_destroy`.
tunnel_read
[tunnel] Fetch the value stashed by a prior `tunnel_create` call by its ID. Use exactly once per intended consumer; the value is destructive-by-design and may self-delete after this call. Increments the read counter and may auto-destroy the tunnel if `maxReads` was set. Returns JSON `{ ok, data: { id, value } }` on success, or an error 'Tunnel "..." not found or expired' if the tunnel has been destroyed, hit its TTL, or never existed.
tunnel_list
[tunnel] Enumerate all currently-active tunnels in the q-ring server with their remaining read budget and time-to-live. Use to audit what is still in memory or to look up an ID you forgot; values are never included in the output. Read-only. Returns one line per tunnel formatted as `id | reads:N | max:N | expires:Ns`, or the literal text 'No active tunnels' when the list is empty.
tunnel_destroy
[tunnel] Immediately remove a tunnel from memory, regardless of remaining reads or TTL. Use when a tunneled value should be cancelled before delivery (e.g. wrong recipient, secret already rotated); prefer letting `maxReads`/TTL handle cleanup for normal flows. Mutates in-memory state only. Returns 'Destroyed ID' on success or a not-found error if the ID is unknown or already gone.
teleport_pack
[teleport] Encrypt one or more secrets into a single AES-256-GCM bundle string that can be safely transferred between machines. Use to hand off a curated set of credentials to another developer or environment; prefer `export_secrets` for plaintext .env output (single machine, trusted) and `tunnel_create` for ephemeral one-shot delivery on the same machine. Reads each secret value (records 'export' audit events) and produces a base64-encoded ciphertext. The bundle is unreadable without the same passphrase via `teleport_unpack`. Returns the bundle string directly. Errors with 'No secrets to pack' if the filter matched zero secrets.
teleport_unpack
[teleport] Decrypt a bundle produced by `teleport_pack` and import each contained secret into the local keyring. Use on the receiving machine after a packer hands you the bundle and passphrase out-of-band; prefer `dryRun=true` first to preview what will be written. When dryRun is false this mutates the keyring (one 'write' event per imported secret) at the requested scope. Bad passphrase or tampered bundle returns JSON `{ ok: false, error: { message } }` with `isError: true`. On success returns 'Imported N secret(s) from teleport bundle'; in dryRun mode returns 'Would import N secrets:' followed by a `KEY [scope]` listing.
audit_log
[audit] Query the q-ring audit log — a tamper-evident record of every read/write/delete touching a secret. Use to investigate 'who accessed KEY recently?' or to feed an agent the access timeline for a specific credential; prefer `detect_anomalies` for automated unusual-pattern detection and `health_check` for decay-state-plus-anomalies in one call. Read-only. Returns one line per event in chronological order, formatted `timestamp | action | key | [scope] | env:NAME | detail`. Returns 'No audit events found' when the filter matches nothing.
detect_anomalies
[audit] Scan the audit history for suspicious access patterns — burst reads of the same key, off-hours access, and other heuristics. Use as a quick triage signal when investigating a single key or before letting an agent rotate credentials; prefer `health_check` for a scope-wide decay+anomaly summary, and `agent_scan` for multi-project JSON reports with optional auto-rotation. Read-only; never mutates secrets or the audit log. Returns one line per finding formatted `[type] description`, or 'No anomalies detected' when the log looks clean.
health_check
[health] Run a single read-only sweep over every secret in the requested scope and report counts of healthy/stale/expired secrets plus any current audit anomalies. Use as the default 'is everything OK?' command for an agent or operator; prefer `check_project` to validate manifest compliance specifically, `detect_anomalies` for audit-only triage, and `agent_scan` for multi-project JSON output or optional auto-rotation. Read-only — never writes. Returns a multi-line text summary: header counts (Total / Healthy / Stale / Expired / No decay / Anomalies), then per-secret `EXPIRED:` / `STALE:` issue lines, then per-anomaly `[type] description` lines.
verify_audit_chain
[audit] Recompute the SHA-256 hash chain over the audit log and confirm no event has been mutated, deleted, or reordered. Use periodically as a tamper-evidence check, or whenever you suspect the audit log has been touched outside q-ring; the result is informational — this tool does not repair the chain if it is broken. Read-only. Returns JSON `{ ok, valid, brokenAt? }` where `valid` is `true` for an intact chain and `brokenAt` (when present) names the first event whose hash did not match.
export_audit
[audit] Export the audit log as a portable text artifact suitable for archiving or feeding into another SIEM/analyzer. Use for compliance exports, after-the-fact investigations, or to hand the trail to a non-MCP consumer; prefer `audit_log` for an in-conversation tail and `verify_audit_chain` to confirm integrity before exporting. Read-only. Returns the rendered text directly (no JSON wrapper). 'jsonl' is one event per line; 'json' is a single array; 'csv' is a header row plus events. Time filters are applied to the event timestamps before formatting.
validate_secret
[validation] Test whether a stored secret is still accepted by its upstream service (OpenAI, Stripe, GitHub, AWS, generic HTTP, etc.) by making a minimal authenticated request. Use to confirm liveness before relying on a credential or as the verification step after `rotate_secret`; prefer `ci_validate_secrets` for a batch run across every key in scope. Side effects: makes one outbound network request per call (may incur tiny provider-side rate-limit cost). Records 'read' for the underlying secret value in the audit log; the value itself is never logged. Returns JSON `{ valid, provider, status?, message?, rateLimit?, ... }` (provider-specific shape).
list_providers
[validation] Enumerate the secret-validation providers q-ring knows how to call (OpenAI, Stripe, GitHub, …) along with their auto-detect prefixes. Use to discover what `provider` string to pass to `validate_secret`/`rotate_secret`, or to check whether your custom provider is registered. Read-only. Returns JSON array of `{ name, description, prefixes }` objects. `prefixes` are the literal key-value prefixes (e.g. 'sk-' for OpenAI) used for auto-detection.
rotate_secret
[validation] Ask the upstream provider to issue a fresh credential for this secret and store the new value back into the keyring. Use when a secret is expiring, leaked, or part of a scheduled rotation; prefer `generate_secret` for self-managed values you fully control, and `agent_scan --autoRotate` for sweep-style rotation across multiple expired keys. Mutates the keyring with the newly-issued value if rotation succeeds (one 'write' audit event), and makes outbound network requests against the provider's rotation API. Returns JSON `{ rotated, newValue?, message?, ... }`. If `rotated` is false, the existing value is left untouched.
ci_validate_secrets
[validation] Validate every accessible secret in the requested scope against its detected provider in a single batch and return a structured pass/fail report. Use as a CI gate ('do all our credentials still work before deploy?') or as a pre-rotation health pass; prefer `validate_secret` for a single key. Side effects: one outbound request per validatable secret (cost scales with N). Reads each secret value (records 'read' audit events). Returns JSON `{ total, valid, invalid, results: [...] }` listing per-key status, provider, and error messages where applicable. Returns 'No secrets to validate' if nothing in scope has a provider mapping.
register_hook
[hooks] Register a side-effect (shell command, HTTP webhook, or process signal) that fires automatically when a matching secret is written, deleted, or rotated. Use to keep external systems in sync (restart a service after rotation, post to Slack on delete, kick a build); prefer `agent_remember` for storing facts an agent should recall later, and `register_hook` is not the right tool for time-based scheduled rotation (use `agent_scan` for that). Mutates the hook registry on disk. At least one match criterion (`key`, `keyPattern`, or `tag`) is required — calls without any return an error. Returns JSON of the registered hook entry including its assigned `id` (use that `id` with `remove_hook`).
list_hooks
[hooks] Enumerate every registered lifecycle hook with its match criteria, delivery type, enabled flag, and description. Use to find a hook's `id` before calling `remove_hook`, audit what side effects are wired up, or diagnose why a hook did not fire. Read-only. Returns pretty-printed JSON array of hook entries, or 'No hooks registered' when the registry is empty.
remove_hook
[hooks] Detach a single lifecycle hook by its registry id so it stops firing. Use to retire a specific webhook/command without touching any secrets; prefer `delete_secret` to remove a credential and `tunnel_destroy` for ephemeral tunnels. Mutates the hook registry only — does not touch secret values, audit log, or env states. Idempotent in spirit: removing an already-absent id returns a not-found error rather than partial work. Returns 'Removed hook ID' on success.
exec_with_secrets
[exec] Run a child shell command with project secrets injected as environment variables and any leaked secret values redacted from captured stdout/stderr before they return to the agent. Use to let an agent run a script that needs credentials (`npm run db:migrate`, `terraform plan`, `vercel deploy`) without ever putting plaintext values in the chat; prefer `env_generate` if you need to write a `.env` file to disk and `validate_secret` for upstream liveness checks. Spawns a real child process — has whatever side effects the command itself causes (writes, network, exec). Subject to BOTH tool policy and exec policy (allowlist/denylist). Returns a text body with `Exit code: N` then `STDOUT:` and `STDERR:` blocks; both streams are scrubbed against the secret values that were injected.
scan_codebase_for_secrets
[scan] Walk a directory tree and flag plausible hardcoded secrets using regex heuristics plus Shannon-entropy scoring on string literals. Use as a one-shot 'is anything leaking in this repo?' audit before commit/release; prefer `lint_files` when you already know the specific files to check (and want optional auto-fix). Read-only — never modifies source files. Honors `.gitignore`. Returns JSON array of `{ file, line, key, value, kind }` findings, or 'No hardcoded secrets found in the specified directory.' when clean. False positives are possible — review before treating as ground truth.
lint_files
[scan] Inspect a specific list of files for hardcoded secrets and, when `fix` is true, replace each finding with `process.env.KEY` while storing the extracted value into the keyring. Use to migrate a known set of files (e.g. just-changed files in a pre-commit hook) into q-ring; prefer `scan_codebase_for_secrets` for a whole-tree audit and `import_dotenv` to ingest an existing .env. With `fix: false` this is read-only. With `fix: true` this MUTATES the listed source files in place (review with git diff!) and writes one new secret per finding to the keyring. Returns a JSON array of `{ file, line, key, value, kind }` findings, or 'No hardcoded secrets found in the specified files.'.
analyze_secrets
[agent] Cross-reference the secrets in scope with recent audit events to produce a usage profile and rotation/retirement suggestions. Use as a quarterly hygiene check or as input to a planner that decides what to rotate or delete; prefer `health_check` for decay-only triage and `audit_log` to inspect access timelines for one key. Read-only; uses the most recent ~500 audit events. Returns JSON `{ total, expired, stale, neverAccessed: [...], noRotationFormat: [...], mostAccessed: [{ key, reads }] }`. `neverAccessed` and `noRotationFormat` are good candidates for cleanup or for adding rotation hints.
status_dashboard
[dashboard] Start a local web dashboard (`http://127.0.0.1:PORT`) that streams live KPIs, secret tables, manifest gaps, hooks, audit events, and anomalies via Server-Sent Events. Use when an operator (or an agent on behalf of one) wants a richer visual surface than chat output; prefer `health_check` / `analyze_secrets` for one-shot text summaries inside the conversation. Side effect: binds an HTTP server on the requested port (one process-wide instance — re-running returns the existing URL instead of starting a second server). Never exposes secret values. Returns the URL string to open in a browser.
agent_scan
[agent] Run a multi-project health pass that gathers decay status, audit anomalies, and `.q-ring.json` manifest gaps across one or more project paths and (optionally) auto-rotates expired secrets with freshly generated values. Use as the canonical 'agent maintenance loop' across a portfolio of repos; prefer `health_check` for a single read-only scope, `detect_anomalies` for audit-only triage, and `check_project` for a single-project manifest check. With `autoRotate=false` (default) this is read-only. With `autoRotate=true` it OVERWRITES expired secret values in the keyring with generated replacements — credential changes that may break upstream integrations until they are propagated. Subject to tool policy. Returns a JSON report of per-project findings and any rotations performed.
agent_remember
[agent] Persist a non-secret key/value note in encrypted, on-disk agent memory that survives across MCP sessions. Use to record stable agent context — last rotation date for a key, the user's deployment preferences, decisions taken in earlier sessions; do NOT use this to store secrets (use `set_secret` instead) and prefer chat scratchpad for purely transient state. Mutates the encrypted memory store. Idempotent: rewriting the same key with a new value simply overwrites. Returns 'Remembered "KEY"' on success.
agent_recall
[agent] Read a value from encrypted agent memory, or list every stored key when no specific key is supplied. Use at the start of an agent loop to rehydrate prior context, or to look up a single remembered fact; prefer `get_project_context` for a redacted overview of secrets and `get_secret` for actual credential values. Read-only. With a `key` argument: returns JSON `{ ok, data: { key, value } }` or a not-found error. Without `key`: returns a JSON listing of every stored key (no values), or 'Agent memory is empty'.
agent_forget
[agent] Permanently delete a single key from encrypted agent memory. Use to retract obsolete or misremembered context; prefer overwriting via `agent_remember` when you just want to update the value, and use `delete_secret` for actual credentials (which never live in agent memory). Destructive: there is no recycle bin. Returns 'Forgot "KEY"' on success or a not-found error if the key was already absent.
check_policy
[policy] Ask whether a single intended action would be allowed by the project's `.q-ring.json` policy without actually performing it. Use as a dry-run before calling a potentially-blocked tool, attempting to read a sensitive key, or invoking `exec_with_secrets` with a non-trivial command; prefer `get_policy_summary` for a one-shot overview of the entire policy. Read-only. Returns JSON `{ allowed, reason?, policySource }` describing the decision. Returns an error 'Missing required parameter for the selected action type' if the matching argument for the chosen `action` is not supplied.
get_policy_summary
[policy] Return a high-level summary of the project's `.q-ring.json` governance policy — counts of allow/deny rules for tools, key reads, exec commands, plus approval and rotation requirements. Use to orient an agent (or the user) on what guardrails are active before attempting policy-restricted actions; prefer `check_policy` for a precise per-action verdict. Read-only. Returns pretty-printed JSON; missing policy file returns an empty/default summary rather than an error so callers can branch on the counts.
Claude Desktop / Cursor
Paste into your MCP client config file to install this server.
{
"mcpServers": {
"q-ring": {
"q-ring": {
"command": "npx",
"args": [
"-y",
"--package=@i4ctime/q-ring",
"qring-mcp"
]
}
}
}
}
McpServers
{
"q-ring": {
"command": "npx",
"args": [
"-y",
"--package=@i4ctime/q-ring",
"qring-mcp"
]
}
}
OS keychain secrets for AI coding agents, over MCP.
Stop pasting API keys into plain-text.envfiles or wrestling with clunky secret managers.q-ringsecurely anchors your credentials to your OS's native vault (macOS Keychain, Linux Secret Service, Windows Credential Vault) and supercharges them with mechanics from quantum physics.
📖View the Official Documentationfor a complete CLI reference, MCP prompt cookbooks, and architecture details.
- Superposition:Store one key with multiple states (dev/staging/prod) that collapse based on context.
- Entanglement:Link keys across projects so rotating one automatically updates them all.
- Tunneling:Create ephemeral, in-memory secrets that self-destruct after a set time or read count.
- Teleportation:Securely pack and share AES-256-GCM encrypted secret bundles.
- Seamless AI Integration:44 built-in MCP tools for native use inCursor,Kiro, andClaude Code.
q-ring is designed to be installed globally so it's available anywhere in your terminal. Pick your favorite package manager:
# pnpm (recommended) pnpm add -g @i4ctime/q-ring # npm npm install -g @i4ctime/q-ring # yarn yarn global add @i4ctime/q-ring # Homebrew (macOS / Linux) brew install i4ctime/tap/qring
The repo ships aDockerfilethat builds the MCP server and exposes it throughmcp-proxy— useful for hosted MCP deployments (e.g. Glama) or keeping the server off the host entirely:
git clone https://github.com/I4cTime/q-ring.git cd q-ring docker build -t qring-mcp . docker run --rm -p 8080:8080 qring-mcp
Note: inside a container there is no OS keychain (GNOME Keyring / macOS Keychain), so this path is for the MCP protocol surface, ephemeral use, and CI experiments — not for durable local secret storage. For day-to-day use install the CLI natively via one of the package managers above.
# 1️⃣ Store a secret (prompts securely if value is omitted) qring set OPENAI_API_KEY sk-... # 2️⃣ Retrieve it anytime qring get OPENAI_API_KEY # 3️⃣ List all keys (values are never shown) qring list # 4️⃣ Generate a cryptographic secret and save it qring generate --format api-key --prefix "sk-" --save MY_KEY # 5️⃣ Run a full health scan qring health # Something not working? Diagnose the install (keyring, audit, MCP wiring) qring doctor # Tab completion for your shell qring completion zsh > ~/.zsh/completions/_qring # also: bash, fish
Superposition — One Key, Multiple Environments
A single secret can hold different values for dev, staging, and prod simultaneously. The correct value resolves based on your current context.
# Set environment-specific values qring set API_KEY "sk-dev-123" --env dev qring set API_KEY "sk-stg-456" --env staging qring set API_KEY "sk-prod-789" --env prod # Value resolves based on context QRING_ENV=prod qring get API_KEY # → sk-prod-789 QRING_ENV=dev qring get API_KEY # → sk-dev-123 # Inspect the quantum state qring inspect API_KEY
Wavefunction Collapse — Smart Environment Detection
q-ring auto-detects your environment without explicit flags. Resolution order:
- --envflag
- QRING_ENVenvironment variable
- NODE_ENVenvironment variable
- Git branch heuristics (main/master→ prod,develop→ dev)
- .q-ring.jsonproject config
- Default environment from the secret
# See what environment q-ring detects qring env # Project config (.q-ring.json) echo '{"env": "staging", "branchMap": {"release/": "staging"}}' > .q-ring.json
Secrets can have a time-to-live. Expired secrets are blocked from reads. Stale secrets (75%+ lifetime) trigger warnings.
# Set a secret that expires in 1 hour qring set SESSION_TOKEN "tok-..." --ttl 3600 # Set with explicit expiry qring set CERT_KEY "..." --expires "2026-06-01T00:00:00Z" # Health check shows decay status qring health
Every secret read, write, and delete is logged with a tamper-evident hash chain. Access patterns are tracked for anomaly detection.
# View audit log qring audit qring audit --key OPENAI_KEY --limit 50 # Detect anomalies (burst access, unusual hours, chain tampering) qring audit --anomalies # Verify audit chain integrity qring audit:verify # Export audit log qring audit:export --format json --since 2026-03-01 qring audit:export --format csv --output audit-report.csv
Generate cryptographically strong secrets in common formats.
qring generate # API key (default) qring generate --format password -l 32 # Strong password qring generate --format uuid # UUID v4 qring generate --format token # Base64url token qring generate --format hex -l 64 # 64-byte hex qring generate --format api-key --prefix "sk-live-" --save STRIPE_KEY
Link secrets across projects. When you rotate one, all entangled copies update automatically.
# Entangle two secrets qring entangle API_KEY API_KEY_BACKUP # Now updating API_KEY also updates API_KEY_BACKUP qring set API_KEY "new-value" # Unlink entangled secrets qring disentangle API_KEY API_KEY_BACKUP
Create secrets that exist only in memory. They never touch disk. Optional TTL and max-read self-destruction.
# Create an ephemeral secret (returns tunnel ID) qring tunnel create "temporary-token-xyz" --ttl 300 --max-reads 1 # Read it (self-destructs after this read) qring tunnel read tun_abc123 # List active tunnels qring tunnel list
Pack secrets into AES-256-GCM encrypted bundles for secure transfer between machines. Keys are derived with PBKDF2-HMAC-SHA512 (210 000 iterations) from your passphrase; each bundle records its iteration count, so bundles produced by older versions still unpack.
# Pack secrets (prompts for passphrase) qring teleport pack --keys "API_KEY,DB_PASS" > bundle.txt # On another machine: unpack (prompts for passphrase) cat bundle.txt | qring teleport unpack # Preview without importing qring teleport unpack <bundle> --dry-run
Import secrets from.envfiles directly into q-ring. Supports standard dotenv syntax including comments, quoted values, and escape sequences. The CLI accepts either a file path or raw content; theimport_dotenvMCP tool only accepts raw content (it never reads files from disk) so an agent can't coerce it into reading arbitrary local files.
# Import all secrets from a .env file qring import .env # Import to project scope, skipping existing keys qring import .env --project --skip-existing # Preview what would be imported qring import .env --dry-run
Export only the secrets you need using key names or tag filters.
# Export specific keys qring export --keys "API_KEY,DB_PASS,REDIS_URL" # Export by tag qring export --tags "backend" # Combine with format qring export --keys "API_KEY,DB_PASS" --format json
Filterqring listoutput by tag, expiry state, or key pattern.
# Filter by tag qring list --tag backend # Show only expired secrets qring list --expired # Show only stale secrets (75%+ decay) qring list --stale # Glob pattern on key name qring list --filter "API_" # Script-friendly existence check (exit 0 if present, 1 if not; decay-aware) qring has OPENAI_API_KEY --quiet && echo "configured"
Declare required secrets in.q-ring.jsonand validate project readiness with a single command.
# Validate project secrets against the manifest qring check # See which secrets are present, missing, expired, or stale qring check --project-path /path/to/project
Generate a.envfile from the project manifest, resolving each key from q-ring with environment-aware superposition collapse.
# Generate to stdout qring env:generate # Write to a file qring env:generate --output .env # Force a specific environment qring env:generate --env staging --output .env.staging
Secret References & Least-Privilege Run
Aqring://reference is a committable pointer to a secret — it goes in your.envfile instead of the value.qring runresolves references and manifest keys at spawn time, injectingonly what the project declares(unlikeexec, which injects the whole scope). Output is auto-redacted.
# .env — safe to commit: these are references, not values DATABASE_URL=qring://project/DATABASE_URL OPENAI_API_KEY=qring://global/OPENAI_API_KEY STRIPE_KEY=qring:///STRIPE_KEY # auto scope: project, then global SESSION_TTL=3600 # plain values pass through # Run with declared secrets injected (manifest + .env refs) qring run -- pnpm dev # Preview what would be injected, without running qring run --dry-run -- pnpm dev # Pin an environment, use a specific env file, or skip the manifest qring run --env prod --env-file .env.prod --no-manifest -- ./deploy.sh
The key lives in thepath, never the host (qring://project/KEY, notqring://KEY) — URL hosts are case-insensitive, and env-var keys are not. Malformed references fail loudly instead of leaking a literalqring://…string into the child. A reference pinned to an environment:qring://project/DATABASE_URL?env=prod.
Wire the q-ring MCP server into an editor's MCP config with one command. Merges non-destructively — other servers are preserved, and an existing q-ring entry is only replaced with--force.
qring setup cursor # .cursor/mcp.json (project) or --global for ~/.cursor qring setup kiro # .kiro/settings/mcp.json, with read-only autoApprove list qring setup claude # .mcp.json (project scope) # Preview without writing qring setup cursor --dry-run
Push manifest secrets to GitHub Actions, Vercel, or Cloudflare Workers through each platform'sown authenticated CLI(gh/vercel/wrangler) — q-ring never holds platform tokens, and values travel over stdin, never argv. Every push is recorded in the audit chain.
# Push the .q-ring.json manifest keys to GitHub Actions secrets qring push github --repo you/your-app # Push to Vercel environments qring push vercel --vercel-env production,preview # Push to Cloudflare Workers secrets qring push cloudflare # Explicit keys, preview first qring push github --keys DATABASE_URL,API_KEY --dry-run
Test if a secret is actually valid with its target service. q-ring auto-detects the provider from key prefixes (sk-→ OpenAI,ghp_→ GitHub, etc.) or accepts an explicit provider name.
# Validate a single secret qring validate OPENAI_API_KEY # Force a specific provider qring validate SOME_KEY --provider stripe # Validate all secrets with detectable providers qring validate --all # Only validate manifest-declared secrets qring validate --all --manifest # List available providers qring validate --list-providers
Built-in providers:OpenAI, Anthropic, OpenRouter, Google AI (Gemini), Groq, Hugging Face, ElevenLabs, Vercel, Stripe, GitHub, AWS (format check), Generic HTTP. Keys are only ever sent in headers, never URLs. (no safe public prefix — select explicitly with--provideror the manifestproviderfield.)
✓ OPENAI_API_KEY valid (openai, 342ms) ✗ STRIPE_KEY invalid (stripe, 128ms) — API key has been revoked ⚠ AWS_ACCESS_KEY error (aws, 10002ms) — network timeout ○ DATABASE_URL unknown — no provider detected
Register webhooks, shell commands, or process signals that fire when secrets are created, updated, or deleted. Supports key matching, glob patterns, tag filtering, and scope constraints.
# Run a shell command when a secret changes qring hook add --key DB_PASS --exec "docker restart app" # POST to a webhook on any write/delete qring hook add --key API_KEY --url "https://hooks.example.com/rotate" # Trigger on all secrets tagged "backend" qring hook add --tag backend --exec "pm2 restart all" # Signal a process when DB secrets change qring hook add --key-pattern "DB_" --signal-target "node" # List all hooks qring hook list # Remove a hook qring hook remove <id> # Enable/disable qring hook enable <id> qring hook disable <id> # Dry-run test a hook qring hook test <id>
Hooks are fire-and-forget: a failing hook never blocks secret operations. The hook registry is stored at~/.config/q-ring/hooks.json.
SSRF protection:HTTP hook URLs targeting private/loopback IP ranges (127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,169.254.0.0/16,::1,fc00::/7) are blocked by default. DNS is checked up frontandre-validated at connect time, so a hostname can't pass the check then rebind to a private address before the socket opens. To allow hooks targeting local services (e.g. during development), set the environment variableQ_RING_ALLOW_PRIVATE_HOOKS=1.
Set a rotation format per secret so the agent auto-rotates with the correct value shape.
# Store a secret with rotation format metadata qring set STRIPE_KEY "sk-..." --rotation-format api-key --rotation-prefix "sk-" # Store a password with password rotation format qring set DB_PASS "..." --rotation-format password
Run commands with secrets securely injected into the environment. All known secret values are automatically redacted from stdout and stderr to prevent leaking into terminal logs or agent transcripts. Exec profiles restrict which commands may be run.
# Execute a deployment script with secrets injected qring exec -- npm run deploy # Inject only specific tags qring exec --tags backend -- node server.js # Run with a restricted profile (blocks network tools and interpreters/shells, 30s timeout) qring exec --profile restricted -- npm test
Migrating a legacy codebase? Quickly scan directories for hardcoded credentials using regex heuristics and Shannon entropy analysis.
✗ src/db/connection.js:12 Key: DB_PASSWORD Entropy: 4.23 Context: const DB_PASSWORD = "..."
Store complex connection strings that dynamically resolve other secrets. IfDB_PASSrotates,DB_URLis automatically correct without manual updates.
qring set DB_USER "admin" qring set DB_PASS "supersecret" qring set DB_URL "postgres://{{DB_USER}}:{{DB_PASS}}@localhost/mydb" # Resolves embedded templates automatically qring get DB_URL # Output: postgres://admin:supersecret@localhost/mydb
Protect sensitive production secrets from being read autonomously by the MCP server without explicit user approval. Each approval token is HMAC-verified, scoped, reasoned, and time-limited. The gate applies to bulk reads too —export_secretsandteleport_packover MCP skip approval-protected keys that lack a valid grant.
# Mark a secret as requiring approval qring set PROD_DB_URL "..." --requires-approval # Temporarily grant MCP access for 1 hour with a reason qring approve PROD_DB_URL --for 3600 --reason "deploying v2.0" # List all approvals with verification status qring approvals # Revoke an approval qring approve PROD_DB_URL --revoke
When an agent is blocked on an approval-protected key, q-ring raises a desktop notification (Linuxnotify-send, macOSosascript) naming the key and the exactqring approvecommand — throttled per key, disabled withQRING_NOTIFY=off.
Plant fake credentials that look and read exactly like real ones. Anything that touches one — a compromised MCP server, an over-curious agent, exfiltrated tooling sweeping the ring — gets the fake value back with no tell, while q-ring fires a desktop alert and writes acanaryevent into the tamper-evident audit chain.
# Plant a canary shaped like a real AWS access key qring canary plant AWS_SECRET_ACCESS_KEY --format aws # Other shapes: github, openai, anthropic, stripe, generic qring canary plant GHP_BACKUP_TOKEN --format github # See what's been tripped qring canary list qring audit --action canary
Values are CSPRNG noise in the provider's real token shape (anawscanary matchesAKIA[A-Z0-9]{16}) — plausible enough to be taken, never valid. Alerts are throttled to one per key per 30 seconds; the audit trail records every read.
Run a third-party MCP server behind q-ring. The airlock sits between your agent host and the wrapped server, spawns it with astripped environment(no inherited API keys — opt back in with--inherit-env), and records every tool call that crosses it as awrapevent in the audit chain, grouped per session and labeled with the calling client's identity. Tool arguments are never logged — they may contain secrets.
{ "mcpServers": { "some-server": { "command": "qring", "args": ["mcp", "wrap", "--", "npx", "-y", "some-mcp-server"] } } }
Tools-only proxy today:tools/listandtools/callpass through verbatim, so the wrapped server behaves identically — it just can't read your environment, and everything it's asked to do is on the record.
Instead of storing static credentials, configureq-ringto dynamically generate short-lived tokens on the fly when requested (e.g. AWS STS, generic HTTP endpoints).
# Store the STS role configuration qring set AWS_TEMP_KEYS '{"roleArn":"arn:aws:iam::123:role/AgentRole", "durationSeconds":3600}' --jit-provider aws-sts # Resolving the secret automatically assumes the role and caches the temporary token qring get AWS_TEMP_KEYS
A safe, redacted overview of the project's secrets, configuration, and state. Designed to be fed into an AI agent's system prompt without ever exposing secret values.
# Human-readable summary qring context # JSON output (for MCP / programmatic use) qring context --json
Scan specific files for hardcoded secrets with optional auto-fix. When--fixis used, detected secrets are replaced withprocess.env.KEYreferences and stored in q-ring.
# Lint files for hardcoded secrets qring lint src/config.ts src/db.ts # Auto-fix: replace hardcoded values and store in q-ring qring lint src/config.ts --fix # Scan entire directory with auto-fix qring scan . --fix
Encrypted, persistent key-value store that survives across AI agent sessions. Useful for remembering rotation history, project decisions, or context.
Sign in to leave a review
Use Google, GitHub, or an email account so ratings stay tied to real people.
No reviews posted yet.





