From f8182e45149157477d9eb4c4e77a93509c304fa0 Mon Sep 17 00:00:00 2001 From: Dai Ha Date: Thu, 13 Aug 2026 10:44:21 +0200 Subject: [PATCH] =?UTF-8?q?Commit=20.autoenv=20=E2=80=94=20the=20loader=20?= =?UTF-8?q?that=20keeps=20Claude=20Code=20on=20one=20secret=20store?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This file has always been designed to be committed and says so in its own header; it simply never was, so every clone of this workspace has been reconstructing it by hand or duplicating tokens instead. It holds no secret. It reads `.secrets/` (gitignored, 0600) and exports three variables, because Claude Code expands `${VAR}` in `.mcp.json` from the *process* environment and cannot read a file — so without it, CONTEXT7_TOKEN and the gitea pair must be duplicated as literals in `.claude/settings.local.json`. opencode needs none of this: it reads `.secrets/` directly via `{file:...}`. Verified before committing that no value appears in it, only the three names and the paths they are read from. Safe in a worktree by construction: a worktree receives tracked files only, so `.secrets/` is absent there and the whole block is skipped rather than failing. Workers are fed by the launcher's env instead — which is where the name mismatch documented in wiki chapter 12 (GITEA_TOKEN vs GITEA_ACCESS_TOKEN) has to be reconciled. --- .autoenv | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .autoenv diff --git a/.autoenv b/.autoenv new file mode 100644 index 0000000..d957e20 --- /dev/null +++ b/.autoenv @@ -0,0 +1,27 @@ +# Workspace environment — loaded by autoenv on entering this directory. +# +# Single source of truth for credentials is .secrets/ (gitignored, 0600). +# NO secret value belongs in this file; it only reads them, so it is committed. +# +# Why it exists: Claude Code expands ${VAR} in .mcp.json from the *process +# environment* and has no way to read a file, so without this its tokens must be +# duplicated as literals in .claude/settings.local.json. opencode does not need +# this file — it reads .secrets/ directly via {file:.secrets/...} — which keeps +# opencode working even when launched outside a login shell. + +_cb_dir="${${AUTOENV_CUR_FILE:-${(%):-%N}}:A:h}" +_cb_secrets="$_cb_dir/.secrets" + +# A git worktree receives tracked files only, so .secrets/ is absent there. +# Workers are fed by the launcher's env instead — do nothing rather than fail. +if [[ -d "$_cb_secrets" ]]; then + _cb_load() { + [[ -r "$_cb_secrets/$2" ]] && export "$1"="$(<"$_cb_secrets/$2")" + } + _cb_load CONTEXT7_TOKEN context7-token + _cb_load GITEA_ACCESS_TOKEN gitea-token + _cb_load GITEA_HOST gitea-host + unset -f _cb_load +fi + +unset _cb_dir _cb_secrets