forked from bchanot/claude
feat(secrets): .env source-of-truth in ~/.claude + repo symlink
Move the real secret out of the git tree: the key lives in ~/.claude/.env (outside the repo), and link.sh symlinks repo/.env -> ~/.claude/.env so `source "$REPO/.env"` resolves transparently. The secret never enters git — not as content (it's a link) and not by accident (gitignored). link.sh: add link_env() — verify ~/.claude/.env exists + has MAGIC_API_KEY (warn, never create/copy the secret), then create repo/.env -> ~/.claude/.env. Defensive + idempotent: links only when repo/.env is absent or already the right symlink; a residual REAL repo/.env is left untouched with a migrate hint (never clobbered, so the secret can't be destroyed). .gitignore: harden .env -> .env + .env.* + !.env.example (covers .env.local, .env.bak, .env.save; keeps the template tracked). Messages point at ~/.claude/.env (the canonical edit location) instead of the ambiguous $REPO/.env: design-tool-gate.sh gate output, design-gate.md (branch 3 + IMPORTANT), toggle-external.sh, install-plugins.sh. Verified: shellcheck clean (link.sh, toggle-external.sh, design-tool-gate.sh); link.sh created the symlink (1 change, idempotent re-run); repo/.env absent from git status; magic-off path still exits 10 with the ~/.claude/.env hint. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
2e6725e8bb
commit
131d0bcb5d
@@ -106,6 +106,32 @@ for _ext in "${NPX_EXTERNAL_SKILLS[@]}"; do
|
||||
CHANGED=$((CHANGED + 1))
|
||||
done
|
||||
|
||||
# ── Local secrets: repo/.env -> ~/.claude/.env ──────────────
|
||||
# Real key lives in ~/.claude/.env (source of truth, outside the repo so the
|
||||
# secret never enters the git tree). The repo reaches it via a symlink that
|
||||
# `source "$REPO/.env"` follows transparently. Never creates/copies/prints it.
|
||||
link_env() {
|
||||
local home_env="$CLAUDE/.env" repo_env="$REPO/.env"
|
||||
if [ ! -f "$home_env" ]; then
|
||||
echo "⚠️ $home_env missing — create it (the repo never stores the secret):"
|
||||
echo " cp \"$REPO/.env.example\" \"$home_env\" && \"\${EDITOR:-nano}\" \"$home_env\""
|
||||
return
|
||||
fi
|
||||
grep -q '^MAGIC_API_KEY=' "$home_env" 2>/dev/null \
|
||||
|| echo "⚠️ $home_env has no MAGIC_API_KEY line — magic won't enable until added."
|
||||
if [ -L "$repo_env" ]; then
|
||||
[ "$(readlink "$repo_env")" = "$home_env" ] && return
|
||||
ln -sf "$home_env" "$repo_env"; CHANGED=$((CHANGED + 1))
|
||||
elif [ ! -e "$repo_env" ]; then
|
||||
ln -sf "$home_env" "$repo_env"; CHANGED=$((CHANGED + 1))
|
||||
else
|
||||
echo "⚠️ $repo_env is a real file, not a symlink."
|
||||
echo " If it holds your secret: mv \"$repo_env\" \"$home_env\" then re-run link.sh"
|
||||
echo " Otherwise remove it so link.sh can link to $home_env."
|
||||
fi
|
||||
}
|
||||
link_env
|
||||
|
||||
if [ "$CHANGED" -eq 0 ]; then
|
||||
echo "✅ All symlinks already up to date."
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user