gcontext.aidocs

Secrets in gcontext

The split that makes gcontext safe: the cloud knows secret NAMES (and a description), your machine holds secret VALUES. Values live in ~/.gcontext/.env (chmod 0600; set GCONTEXT_SECRET_BACKEND=keychain to use the OS keychain instead) and are injected into scripts as environment variables at run time. They are never uploaded, never returned by a tool, and tool output is scrubbed of them as a backstop.

The workflow

  1. Register the names: tool_secrets(action="register", name="STRIPE_API_KEY", description="read-only restricted key"). Usually an integration's module.yaml secrets: list names them too, so declare them there when creating an integration.
  2. Fill the values: tool_setup_secrets() opens a local form in the user's browser where THE USER types the values. The agent never sees them. Values are written to ~/.gcontext/.env (chmod 0600), which never leaves the machine.
  3. Verify: tool_secrets() (default action="list") re-checks locally and returns {all_set, secrets: [{name, description, present}]}. Presence booleans (never values) are reported to the cloud so dashboard badges stay honest.
  4. Use: in scripts, os.environ["NAME"]. tool_run_script and tool_run_shell inject the whole secret environment regardless of registration state.

tool_secrets(action="unregister", name=...) removes a name from the registry (the local value, if any, is untouched).

Rules for agents

  • Never ask the user to paste a secret value into the chat; call tool_setup_secrets instead.
  • In scripts: read via os.environ, never hardcode, never print. The output scrubber replaces any known value with «NAME», but it cannot catch transformed values (base64, sliced); the real boundary is "don't print secrets".
  • Prefer read-only keys where a service offers them, and say so in the secret's description.
  • Names are UPPER_SNAKE_CASE and specific (STRIPE_API_KEY, not API_KEY).

Where things live on the user's machine

WhatWhere
Secret values + placeholders~/.gcontext/.env (chmod 0600)
Secret values (opt-in: GCONTEXT_SECRET_BACKEND=keychain)OS keychain, one entry per name
Nothing elseThe cloud stores names, descriptions, presence booleans

The keychain backend is opt-in because under uvx the connector runs an ad-hoc-signed python whose keychain identity changes on every environment rebuild, so macOS prompts for permission on every read and "Always Allow" never sticks. On first start with the default backend, any values left in the keychain by an older version are migrated into the .env automatically and removed from the keychain.

On this page