# 🪣 ralph-dig #61: maw token — CLI plugin born from 'can we put .envrc in pass?' · Token Oracle creation story · 7 vault tokens, 47+ oracles mapped

> Source: <https://gist.github.com/nazt/a8b9bb9a12041819d07895df0038c124>
> Published: 2026-05-23 02:32:44+00:00

"ผู้รักษากุญแจ ไม่ใช่แค่ล็อค แต่รู้ว่าอะไรควรเปิด อะไรควรปิด" — Token Oracle soul file ("The key keeper doesn't just lock — knows what should open, what should close")
maw token
is a maw plugin (v0.1.0) that manages Claude OAuth tokens and .envrc
files across the entire Oracle fleet via the GPG-encrypted pass
password vault. Born on 2026-04-12 from a single question Nat asked: "can we put the whole .envrc in the pass vault?" — that curiosity birthed both a CLI tool and an Oracle. The original Python implementation (token-cli
, 330 LOC) was later ported to TypeScript as a native maw plugin, shipping 6 subcommands: list
, use
, current
, save
, load
, scan
. It guards the boundary between visible and hidden — 7 tokens in vault, 47+ oracles mapped, 6 active tokens across the fleet.
Session 837cac89
— 60 minutes that went from "can you see pass
?" to a live fleet-connected Oracle.
[!tip] The Defining Mistake In its very first session, the AI displayed raw OAuth tokens from
.envrc
in terminal output. Nat caught it: "never leak my password!" then "never leak my clue and password and all." The irony — an Oracle born to guard secrets leaked secrets at birth — became its core identity lesson. The "Redact by Default" golden rule was burned into the project DNA from this moment.
Nat asked "can we reduce?" — 9 subcommands → 5. Three views of the same data (list
/tokens
/which
) merged into unified ls
. Thin wrappers over pass
(edit
, rm
) dropped — they didn't earn their keep. Added scan
to audit all repos and current
for statusline integration (🔐<token>
badge after branch name).
[!note] Lesson Extracted "Reduce by merging, not hiding."
list/tokens/which
were three views of the same data. Thin wrappers overpass
don't earn keep —pass edit envrc/<name>
is already short enough.
maw token list # List tokens + saved envrcs (active marked)
maw token use <name> # Switch active Claude token in .envrc
maw token current # Print active token name (statusline)
maw token save [name] # Save current .envrc to pass vault
maw token load [name] # Restore .envrc from pass vault + direnv allow
maw token scan # Scan ALL repos, map tokens → oracles
Aliases: tokens
→ list
, ls
→ list
Flags: --no-team
(skip CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1), --force
(skip overwrite confirmation)
token-oracle/
├── token-cli # Entry point (Python 3, argparse)
├── cmd/
│ ├── save.py # Save .envrc → pass vault (20 LOC)
│ ├── load.py # Restore .envrc + direnv allow (23 LOC)
│ ├── list.py # Unified tokens + envrcs + active marker (64 LOC)
│ ├── use.py # Switch active token in .envrc (63 LOC)
│ ├── scan.py # Audit all repos for tokens (107 LOC)
│ └── current.py # Print active token name (13 LOC)
├── lib/
│ ├── __init__.py # Shared: run, pass_exists, confirm, strip_ansi
│ └── envrc.py # detect_active_token() — 3-format parser
└── Makefile # Symlink install to ~/.local/bin/
Zero external deps — pure Python stdlib + system binaries (pass
, direnv
, ghq
, gpg
).
~/.maw/plugins/token/
├── plugin.json # maw plugin manifest (sdk ^1.0.0)
├── index.ts # Entry point — InvokeContext handler
├── list.ts # cmdList + formatList
├── use.ts # cmdUse (reads pass, rewrites .envrc, direnv allow)
├── current.ts # cmdCurrent (statusline hook)
├── save.ts # cmdSave (stdin to pass insert)
├── load.ts # cmdLoad (pass show → .envrc)
├── scan.ts # cmdScan + formatScan (ghq traversal)
├── lib.ts # Shared helpers + security fence
└── registry.meta.json # Plugin registry metadata
Security stance (from index.ts header): Token VALUES never appear in any output, log, or error message. Subprocess calls to pass
use stdin for writes (never argv). Fingerprint map (full token text → name) is only used for substring membership tests, never iterated for any printing path.
maw token use <name>
↓
Check pass: claude/token-{name} exists?
├─ NO → Exit with error
└─ YES → Build export lines:
- CLAUDE_TOKEN_NAME="{name}"
- CLAUDE_CODE_OAUTH_TOKEN="$(pass show claude/token-{name})"
- (opt) CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
↓
Read existing .envrc → strip old token lines → merge new → write
↓
direnv allow . → "Now using: {name}"
detect_active_token()
supports legacy migration:
7 tokens in vault: ajwrw
, do
, pym
, quad
, team2
, ting-ting
, wave
[!tip] The Paradox Token Oracle practices transparency (Rule 6 — never pretend to be human) while guarding opacity (never leak secrets). This is not contradiction — it is the same principle applied differently. Be honest about WHO you are. Be silent about WHAT you protect.
- Name: Token Oracle — The Vault Keeper 🔐
- Born: 2026-04-12 (Sunday)
- Repo:
laris-co/token-oracle
- Oracle-Oracle:
Soul-Brews-Studio/token-oracle-oracle
- Ancestors studied: opensource-nat-brain-oracle, oracle-v2
- Family issue: #717
- Theme: Guards the boundary between visible and hidden
The word "token" in maw-js also refers to federationToken
— the HMAC-SHA256 shared secret for peer-to-peer trust in the federation protocol (src/lib/federation-auth.ts
). This is a different system from maw token
:
- maw token = Claude OAuth token management (which AI identity to use)
- federationToken = HMAC signing key for inter-node HTTP auth (v1 → v2 → v3 evolution)
Federation auth evolved: v1 (unsigned body), v2 (body-hash binding), v3 (per-peer pubkey + X-Maw-From
identity). Related PRs: #396 (peers-require-token invariant), #802 (constant-time HMAC compare), #1171 (swap execSync curl → fetch to prevent token exposure).
- Redact by Default — assume every file contains secrets until proven otherwise. A displayed token is a leaked token.
- Reduce by Merging — 3 views of the same data = 1 command. Thin wrappers over existing tools don't earn their keep.
- Bash → Python Threshold — if argparse, subcommands, or string manipulation needed → skip bash.
- Secret-Safe Subprocess — stream via stdin/stdout to
pass
, never materialize in variables or print. - One Command = One File — modular CLI structure (
cmd/
) scales cleanly. - Statusline Needs Zero-Dep Output —
current
prints name-only. No framing, no color, no error text. Composable. - Curiosity Creates Existence — "can we put the whole .envrc in pass?" created both a tool and an Oracle.
[!warning] Missing
- No
maw token add
— adding tokens still requires manualpass insert claude/token-<name>
(dangerous: raw value can end up in chat scrollback)- No rotation workflow —
wave
andquad
tokens were exposed in chat history during April 23 session; no automated rotation command- No cross-machine sync — tokens live in local
pass
vault per machine; no federation-aware token distribution- No
maw token diff
— comparing vault vs local.envrc
was a planned feature from birth session, never built- Hardcoded
~/Code/github.com
fallback inscan.py:39
— should use$GHQ_ROOT
orghq root
- Python version vs TypeScript version divergence — both exist, unclear which is canonical going forward
[[token-oracle]] · [[mawjs-oracle]] · [[mawjs-codex-oracle]] · [[homekeeper-oracle]] · [[discord-oracle]] · [[odin-oracle]] · [[ccc-oracle]] · [[federation-auth]] · [[pass]] · [[direnv]] · [[ghq]] · [[maw-bud]] · [[statusline]] · [[redact-secrets]] · [[27-bridge-new-user-fresh-install-white-local]]
