From 737bc067273a6550ee2931e3028df03f386e467e Mon Sep 17 00:00:00 2001 From: Lorem Dev Date: Sat, 23 May 2026 10:00:27 +0200 Subject: [PATCH 1/6] test(initflow): require MCP fallback block in every agent template --- internal/initflow/agents_test.go | 40 ++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/internal/initflow/agents_test.go b/internal/initflow/agents_test.go index a3d6d81..bf67791 100644 --- a/internal/initflow/agents_test.go +++ b/internal/initflow/agents_test.go @@ -492,3 +492,43 @@ func TestTemplates_NoCrossAgentMentions(t *testing.T) { } } } + +func TestTemplates_AllHaveMCPFallback(t *testing.T) { + cases := []struct { + name string + loader func(string) ([]byte, error) + files []string + }{ + { + "claude", claudefiles.ReadTemplateForTest, + []string{"templates/claude_md.md.tmpl", "templates/claude_skill.md.tmpl"}, + }, + {"codex", codexfiles.ReadTemplateForTest, []string{"templates/codex_agents.md.tmpl"}}, + {"gemini", geminifiles.ReadTemplateForTest, []string{"templates/gemini_md.md.tmpl"}}, + {"opencode", opencodefiles.ReadTemplateForTest, []string{"templates/instructions.md.tmpl"}}, + {"generic", genericfiles.ReadTemplateForTest, []string{"templates/instructions.md.tmpl"}}, + } + needles := []string{ + "Locksmith Commands (runtime whitelist)", + "MCP Servers and Locksmith", + "Fallback for locksmith-wrapped MCP servers", + "{key:", + "{vault:", + "locksmith get --key", + "locksmith get --vault", + "locksmith session ensure --quiet", + } + for _, c := range cases { + for _, f := range c.files { + data, err := c.loader(f) + if err != nil { + t.Fatalf("%s %s: %v", c.name, f, err) + } + for _, n := range needles { + if !bytes.Contains(data, []byte(n)) { + t.Errorf("%s/%s missing %q", c.name, f, n) + } + } + } + } +} From a4437c39a35687473b8013f8b059891a4c7461a5 Mon Sep 17 00:00:00 2001 From: Lorem Dev Date: Sat, 23 May 2026 10:03:54 +0200 Subject: [PATCH 2/6] feat(initflow): document MCP wrapper fallback in agent templates --- CHANGES.md | 1 + .../agents/claude/templates/claude_md.md.tmpl | 97 +++++++++++++++++++ .../claude/templates/claude_skill.md.tmpl | 96 ++++++++++++++++++ .../codex/templates/codex_agents.md.tmpl | 97 +++++++++++++++++++ .../agents/gemini/templates/gemini_md.md.tmpl | 97 +++++++++++++++++++ .../generic/templates/instructions.md.tmpl | 97 +++++++++++++++++++ .../opencode/templates/instructions.md.tmpl | 97 +++++++++++++++++++ 7 files changed, 582 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 5ec6418..d3cdba2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -63,6 +63,7 @@ use `export LOCKSMITH_SESSION=$(locksmith session ensure --quiet)`) and includes usage examples for all three shipped vault types (`gopass`, `keychain`, `1password`). +- Agent templates now document an MCP-wrapper fallback: when a locksmith-wrapped MCP server fails, the agent parses `--header` and `--env` templates from its own MCP config, resolves them via `locksmith get`, and runs the server directly. Templates also whitelist `session ensure`, `serve`, and `get` as the only runtime locksmith commands. ## Version v0.3.0 - 2026-05-15 diff --git a/internal/initflow/agents/claude/templates/claude_md.md.tmpl b/internal/initflow/agents/claude/templates/claude_md.md.tmpl index 00dbb70..5be22fd 100644 --- a/internal/initflow/agents/claude/templates/claude_md.md.tmpl +++ b/internal/initflow/agents/claude/templates/claude_md.md.tmpl @@ -16,6 +16,103 @@ Just call `locksmith get` directly. locksmith get --vault keychain --path "My API Token" locksmith get --vault op --path "op://Personal/GitHub/token" +## Locksmith Commands (runtime whitelist) + +Use ONLY these at runtime: + +- `locksmith session ensure --quiet` - obtain/refresh a session ID +- `locksmith serve` - start the daemon if it is not running + (rare; `session ensure` will spawn it automatically) +- `locksmith get --key ` or `--vault --path ` - + fetch a secret + +Do not call `init`, `vault`, `plugins`, `config`, `reload`, `mcp`, +or any other subcommand - they are for the human operator only. + +## MCP Servers and Locksmith + +The MCP server config lives in **the agent's own settings** +(e.g. `~/.claude.json`, `~/.codex/mcp.json`, `~/.gemini/...`), +NOT in locksmith's config file. Always read from there. + +- If an MCP entry's `command` is anything other than `"locksmith"` - + run it exactly as written. Do not wrap it in locksmith. Behave + as if locksmith does not exist for this server. +- If `command` is `"locksmith"` with `args` starting with + `["mcp", "run", ...]` - the server is locksmith-wrapped. If it + fails to start or returns an auth error, apply the fallback below. + +### Fallback for locksmith-wrapped MCP servers + +1. Parse these flags from the entry's `args` (after `mcp run`): + - `--header Name=