Guide

Step-by-step examples for common secret management tasks

Quick Start

From zero to automatic secret injection in 5 minutes

1

Install the CLI

Download from the Downloads page, or use curl:

macOS (Apple Silicon — includes Touch ID helper)

curl -fSkL https://localhost:8080/v1/downloads/darwin/arm64 -o sg \ && curl -fSkL https://localhost:8080/v1/downloads/darwin/universal -o sg-bio \ && chmod +x sg sg-bio \ && sudo mv sg sg-bio /usr/local/bin/
2

Initialize the CLI

If you have an invite code from your admin:

sg init --gateway https://localhost:8080 --tls-skip-verify --invite YOUR_INVITE_CODE

Or if you are the admin (server operator):

sg init --gateway https://localhost:8080 --tls-skip-verify

Your token is stored in the OS keychain (Touch ID on macOS) or printed as export SG_TOKEN=... on Linux. The config file at ~/.sg/config.json stores only the gateway URL — never the token.

3

Store the token in the keychain (macOS only)

sg unlock

Triggers a Touch ID or macOS login password prompt and stores your token in the Data Protection Keychain. On Linux, add the export SG_TOKEN="..." line printed by sg init to your shell profile instead.

4

Install the shell plugin

sg shell install

Then reload your shell (or open a new terminal):

source ~/.zshrc # zsh source ~/.bashrc # bash exec fish # fish

This installs an integration snippet that starts the sg agent daemon once per session (Touch ID fires once) and automatically resolves sg:// references — no sg exec prefix needed.

5

Store your first secret

# Create a vault sg vault create myapp # Create an item (logical grouping) sg item create <vault-id> database # Store a secret field sg field set <vault-id> <item-id> password "s3cret!"
6

Run commands — secrets resolve automatically

# With the shell plugin active, just run commands normally: aws s3 ls kubectl get pods npm start # Or verify the agent is running: sg agent status

No prefix needed. The shell plugin resolves sg:// references in .env, ~/.aws/credentials, ~/.kube/config, and other well-known files automatically on every directory change.

Shell Plugin

Automatic secret injection via sg agent — no sg exec prefix required

The shell plugin installs an integration snippet into your shell profile. It starts a background daemon (sg agent) once per session and automatically resolves sg:// references on every directory change.

Install / uninstall

sg shell install # appends snippet to ~/.zshrc / ~/.bashrc / fish sg shell uninstall # removes the snippet sg shell status # show which profile file is configured

Agent commands

sg agent start # start the daemon (done automatically by the shell plugin) sg agent stop # stop the daemon sg agent status # check whether the daemon is running sg agent flush # clear the in-memory secret cache (forces re-resolve)

The agent holds your bearer token in memory and caches resolved secrets (15-minute TTL). Touch ID is triggered once when the agent starts, not on every command.

How it works

1. Shell opens → agent starts → Touch ID prompt (once)

2. cd project/ → hook fires → eval "$(sg shell-env)"

3. shell-env asks agent to resolve sg:// refs in well-known files

4. Agent returns cached values (no Touch ID re-prompt)

5. Shell exports resolved paths as env vars

6. aws s3 ls → reads credentials from exported temp file

7. Shell closes → EXIT trap stops the agent

Without the shell plugin

Use sg exec to wrap individual commands:

sg exec -- aws s3 ls sg exec -- kubectl get pods sg exec -- node server.js

Vaults & Items

Organize secrets hierarchically: Vault → Item → Field

Hierarchy

📦 myapp (vault)

├── 📋 database (item)

│ ├── 🔑 host = db.example.com

│ ├── 🔑 port = 5432

│ ├── 🔑 username = app_user

│ └── 🔑 password = ••••••••

├── 📋 aws (item)

│ ├── 🔑 access_key = AKIA...

│ └── 🔑 secret_key = ••••••••

└── 📋 stripe (item)

└── 🔑 api_key = sk_live_...

Managing Vaults

# List all vaults sg vault list # Create a vault sg vault create production # Delete a vault (and all its items) sg vault delete <vault-id>

Managing Items

# List items in a vault sg item list <vault-id> # Create an item sg item create <vault-id> database # Delete an item sg item delete <vault-id> <item-id>

Storing Secrets

Add, update, and manage secret fields

CLI Commands

# Store a secret field sg field set <vault-id> <item-id> password "my-secret-value" # Store multiple fields sg field set <vid> <iid> DB_HOST "db.example.com" sg field set <vid> <iid> DB_PORT "5432" sg field set <vid> <iid> DB_USER "app_user" sg field set <vid> <iid> DB_PASSWORD "super-secret" # List fields in an item sg field list <vault-id> <item-id> # Delete a field sg field delete <vault-id> <item-id> <field-id>

REST API

REST API equivalent

# Create a field via API curl -sk -X POST https://localhost:8080/v1/vaults/<vid>/items/<iid>/fields \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{"name": "password", "value": "s3cret!", "field_type": "password"}' # Read a field value curl -sk https://localhost:8080/v1/vaults/<vid>/items/<iid>/fields/<fid> \ -H "Authorization: Bearer <token>"

Note: All field values are encrypted with AES-256-GCM using per-field derived keys (HKDF). They are decrypted only when explicitly read.

Reading Secrets

Resolve secrets using sg:// references

Single secret

# Read a single secret by reference sg read sg://myapp/database/password # Output: my-secret-value

Batch resolve (API)

# Batch resolve via API (up to 100 at once) curl -sk -X POST https://localhost:8080/v1/resolve \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "references": [ "sg://myapp/database/password", "sg://myapp/aws/access_key", "sg://myapp/stripe/api_key" ] }' # Response: # { # "values": { # "sg://myapp/database/password": "s3cret!", # "sg://myapp/aws/access_key": "AKIAIOSFODNN7EXAMPLE", # "sg://myapp/stripe/api_key": "sk_live_..." # } # }

You can also use the Resolve page in this webapp to test references interactively.

Environment Injection

Secrets resolved automatically — or via sg run / sg exec

Create a .env file with sg:// references instead of hardcoded values:

.env

# .env file — secret references, NOT plaintext values DB_HOST=sg://production/database/host DB_PORT=sg://production/database/port DB_USER=sg://production/database/username DB_PASSWORD=sg://production/database/password AWS_ACCESS_KEY_ID=sg://production/aws/access_key AWS_SECRET_ACCESS_KEY=sg://production/aws/secret_key

Option A — Shell plugin (recommended)

With sg shell install active, just run commands normally — no prefix needed:

With shell plugin active

node server.js python manage.py runserver docker compose up ./my-script.sh

Option B — sg run (per-command)

Without the shell plugin, wrap each command with sg run:

Without shell plugin

sg run --env-file .env -- node server.js sg run --env-file .env -- python manage.py runserver sg run --env-file .env -- docker compose up

Zero code changes needed. Your app reads standard $DB_PASSWORD env vars — it never needs to know about SecretsGateway. Secrets are never written to disk.

Template File Injection

Replace sg:// references in config files

Create a template file with sg:// references:

config.yml.tpl (template)

# config.yml.tpl database: host: sg://production/database/host port: sg://production/database/port username: sg://production/database/username password: sg://production/database/password redis: url: sg://production/redis/url api_keys: stripe: sg://production/stripe/api_key sendgrid: sg://production/sendgrid/api_key

Render it with resolved values:

Resolve template

# Write resolved config to stdout sg inject --in-file config.yml.tpl # Write to a file sg inject --in-file config.yml.tpl --out-file config.yml # Pipe to another command sg inject --in-file config.yml.tpl | kubectl apply -f -

Team Access

Onboard team members with scoped invite codes

For admins: Create an invite

Use the Invites page or the API:

# Via API (admin key required) curl -sk -X POST https://localhost:8080/v1/auth/invites \ -H "X-Admin-Key: <admin-key>" \ -H "Content-Type: application/json" \ -d '{ "name": "Alice - Backend Team", "vault_scopes": ["<production-vault-id>"], "read_only": true }'

For team members: Redeem the invite

sg init --gateway https://localhost:8080 --tls-skip-verify \ --invite <invite-code>

The invite code can only be used once. The team member gets a scoped token that is automatically stored in their OS keychain.

Access control

Full Access

Can create, read, update, and delete secrets within their scoped vaults.

Read-only

Can only read secrets. Cannot create, update, or delete.

Reference Format

The sg:// URI scheme for addressing secrets

sg://{vault}/{item}/{field}

sg://{vault}/{item}/{section}/{field}

Examples

sg://production/database/password

Vault "production", item "database", field "password"

sg://myapp/aws/access_key

Vault "myapp", item "aws", field "access_key"

sg://dev/api-keys/stripe/secret

With section: vault "dev", item "api-keys", section "stripe", field "secret"

Where references are used

sg shell install — automatic injection in every shell session (recommended)
sg exec -- <cmd> — auto-discover and resolve for a single command
sg read sg://... — read a single secret
sg run --env-file .env — resolve refs in env file
sg inject --in-file tpl — resolve refs in template
POST /v1/resolve — batch resolve via REST API