1
0
forked from jason/echo

ver 1.4.0 - baked in values

This commit is contained in:
Jason Stedwell
2026-06-25 17:54:03 -05:00
parent b4605a52f2
commit a1f2f02d3a
23 changed files with 254 additions and 37 deletions
@@ -17,12 +17,21 @@ committed, and is never written into a vault note. To create it, run
it, or `python3 echo.py config set --owner ... --endpoint ... --key ...`.
Per-field resolution (first hit wins):
owner env ECHO_OWNER -> config "owner"
endpoint env ECHO_BASE -> config "endpoint"
key env ECHO_KEY -> config "key"
owner env ECHO_OWNER -> config "owner" -> baked DEFAULT_OWNER
endpoint env ECHO_BASE -> config "endpoint" -> baked DEFAULT_BASE
key env ECHO_KEY -> config "key" -> baked DEFAULT_KEY
The config directory honors $CLAUDE_CONFIG_DIR (defaults to ~/.claude); the config
file path itself can be overridden with $ECHO_CONFIG. Pure stdlib only.
BAKED FALLBACK (the lowest tier): the DEFAULT_* constants below are EMPTY in source
— the committed plugin ships zero credentials. `build.py --bake-key` substitutes a
specific user's owner/endpoint/key into them at package time, producing a per-user
artifact that needs no config file. This is how the plugin works in the CoWork
sandbox, where the user's ~/.claude is not bridged: the plugin itself (mounted
read-only every session) carries the values. A baked artifact is secret-bearing —
deliver it directly to that one user, NEVER commit or publish it. On a normal host
the empty defaults mean behaviour is unchanged (env/config file still win).
"""
from __future__ import annotations
@@ -30,6 +39,12 @@ import json
import os
from pathlib import Path
# Build-time injection targets — MUST stay empty string literals in source so the
# committed tree ships no secret. `build.py --bake-key` rewrites these lines.
DEFAULT_OWNER = ""
DEFAULT_BASE = ""
DEFAULT_KEY = ""
TEMPLATE = {
"owner": "Full Name — how the agent should refer to the vault owner (third person)",
"endpoint": "https://your-obsidian-rest-endpoint.example.com",
@@ -68,11 +83,11 @@ def load() -> dict:
which raise a helpful error. This keeps `--help`, `config`, and `doctor` usable
even when nothing is configured yet."""
f = _from_file()
endpoint = (os.environ.get("ECHO_BASE") or f.get("endpoint") or "").rstrip("/")
endpoint = (os.environ.get("ECHO_BASE") or f.get("endpoint") or DEFAULT_BASE or "").rstrip("/")
return {
"owner": os.environ.get("ECHO_OWNER") or f.get("owner") or "",
"owner": os.environ.get("ECHO_OWNER") or f.get("owner") or DEFAULT_OWNER or "",
"endpoint": endpoint,
"key": os.environ.get("ECHO_KEY") or f.get("key") or "",
"key": os.environ.get("ECHO_KEY") or f.get("key") or DEFAULT_KEY or "",
}
@@ -123,6 +138,9 @@ def source(field: str) -> str:
return f"{env} env"
if config_path().exists() and _from_file().get(field):
return "config file"
baked = {"owner": DEFAULT_OWNER, "endpoint": DEFAULT_BASE, "key": DEFAULT_KEY}[field]
if baked:
return "baked-in default"
return "unset"