Lamprey Config & Flags

SkillAI & models

Catalog of every Lamprey configuration axis — AppSettings keys with defaults and readers, inert retired keys, keychain/keys.json, custom models, loop and timeout knobs, environment variables, per-conversation runtime state — plus the exact checklist for adding a setting without breaking the parity-lock test. Load when reading/changing settings.json, adding a setting, or wondering what a flag does or whether anything still reads it.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Lamprey Config & Flags skill

What this skill tells your AI

The instructions your AI receives, as published by uss-parks/lamprey-harness in .claude/skills/lamprey-config-and-flags/SKILL.md and read by ahel’s review.

When to use / when not

  • Use when adding/changing a setting, auditing what a flag does, debugging settings/keys persistence, or checking a default.
  • Don't use for provider/model internals (see lamprey-provider-and-model-reference), the DB (see lamprey-database-and-persistence), or loop procedure (see lamprey-loop-reliability-campaign).

Where config lives

StorePathWriterNotes
App settings%APPDATA%\Lamprey\settings.jsonsettings:set IPC via writeJsonAtomicRead = {...DEFAULT_APP_SETTINGS, ...file} (mtime-cached); corrupt file preserved as settings.json.corrupt-<ts>
API keys%APPDATA%\Lamprey\keys.jsonkeychain service, atomic, mode 0o600Values safeStorage-encrypted (or plain:-prefixed after explicit consent when encryption unavailable)
MCP servers%APPDATA%\Lamprey\mcp-servers.jsonmcp-managerPlugin connectors overlay at runtime
Custom modelsinside settings.json (customModels[])model:addCustom IPCConsulted by resolveModel (mtime-cached)
Ship pipeline.bucket.json, .aws/credentials, .cf/token (repo root, gitignored)scripts/bucket-setup.ps1See lamprey-ship-and-release

AppSettings — full catalog (defaults verified against electron/services/default-app-settings.ts, 2026-07-02, v0.16.0)

KeyDefaultRead byUI tabStatus
theme'dark'renderer theme engineAppearanceera default
themePreset'arcgis-blue'theme loaderAppearanceera default
themeMode'dark'theme toggleAppearanceera default
fontSize14renderer CSS varsAppearanceera default
defaultModel'deepseek-v4-pro'chat init / model IPCModelsera default
sidebarCollapsedfalselayoutGeneralera default
artifactPanelWidth420artifact panelAppearanceera default
minimizeToTrayfalsewindow close handlerGeneralera default
autoCheckUpdatestrueupdate checkerGeneralera default
aiGeneratedTitlesfalsetitle generatorGeneralera default
modelConfig{}per-model temp/topP/maxTokens overridesModelsera default
customModels[]resolveModel, model:listModelsera default
toolSurface'full'chat tool dispatch ('lazy' enables HY2 surface)settings.json onlyera default; lazy = opt-in
agenticCodingModefalseturn router + skill auto-activationCoding Modeopt-in
agenticCodingSkills['plan','context','verify']skill activation gateCoding Modeera default
snipEnabledtrueshell-output filter layerSnipera default
snipVerbosefalsesnip activity logSnipopt-in
safeSeedLength8192fork/seed sizingSeed Budgetera default
includePastReasoningInContexttruechat history rehydratorReasoning Auditera default
loopsEnabledfalsemaster gate for all loop machineryLoopsopt-in power extension
loopMaxIterations25loop controllerLoops0 disables the ceiling
loopMaxWallclockMs1800000 (30 min)loop controller (counts active_ms, not calendar)Loops0 disables
loopTokenBudget500000loop controllerLoops0 disables
loopMaxConcurrent1loop controllerLoopsfloor-clamped to ≥ 1
loopMinIntervalSeconds30runaway floorLoopsfloor-clamped to ≥ 1
streamInactivityMsunset → 60000SSE watchdog (providers/registry.ts)Timeoutsmin clamp 5000; 0 disables
mcpCallTimeoutMsunset → 120000MCP manager per-call timeoutTimeoutsmin clamp 5000; 0 disables

Loop semantics precision (electron/services/loop-config.ts, verified): resolveLoopConfig accepts any finite number ≥ 0 (so 0 is a valid stored value); maxConcurrent and minIntervalSeconds are then clamped to ≥ 1 — meaning you cannot disable the concurrency limit or the runaway floor. The three ceilings (iterations/wallclock/token) treat 0 as "disabled" at the controller.

Inert retired keys (harmless if present in settings.json)

agentMode, agentRoster, proofGate, agenticCodingComposer (retired UB-7), stageBudgetMs, stageInactivityMs (retired UB-6). Nothing reads them; the merge semantics pass them through silently. Do not re-add readers — that's rebuilding deleted machinery (lamprey-failure-archaeology #8).

Keychain key ids

Providers: deepseek, google, dashscope, openrouter, zhipu (+ google-client-id/google-client-secret for OAuth). Search providers use the separate namespace web_search:<id> (web_search:tavily, web_search:brave, web_search:serpapi). IPC: settings:saveProviderKey / :testProviderKey / :deleteProviderKey / :listProviderKeys, and the settings:*SearchProviderKey variants. Key mutations emit audit events (action + provider + storage mode — never the key value).

Environment variables

VarWhenPurpose
ELECTRON_EXEC_PATHdevexplicit Electron binary path for electron-vite dev (required on the primary machine)
WIN_CSC_LINK / WIN_CSC_KEY_PASSWORDreleaseAuthenticode signing (auto-detected by electron-builder; unsigned without them)
LAMPREY_GITHUB_CLIENT_ID / LAMPREY_GITHUB_CLIENT_SECRETbuild timeinjected as literals into the main bundle for the GitHub OAuth flow; empty in forks → BYO credentials fallback
ALLOW_AI_ARTIFACTS=1commitdeliberate bypass of the staged-diff artifact scan
GIT_TERMINAL_PROMPT=0runtime git opssuppress interactive auth prompts

Only LAMPREY_-prefixed keys from .env are exposed to the main bundle (custom loader in electron.vite.config.ts).

Per-conversation runtime state that acts like config (not persisted)

In electron/services/tool-unlock-state.ts: lazy-surface active set, unlocked-tool sets, malformed-tool_search counters (downgrade at MALFORMED_SEARCH_DOWNGRADE_THRESHOLD = 3), downgrade set. Cleared on conversation delete; reset by app restart.

Checklist: adding a setting (the SP-1 parity lock makes half-measures fail)

  1. Add key + default to DEFAULT_APP_SETTINGS in electron/services/default-app-settings.ts.
  2. Mirror the default in the renderer literal in src/stores/settings-store.tsdefault-app-settings.test.ts locks the two byte-for-byte; touching only one side fails the suite. This is deliberate (the D1 drift incident: renderer said one default, main another, main silently won).
  3. Add the type to AppSettings in src/lib/types.ts.
  4. Implement the reader (service or renderer). A setting nobody reads is a lie — don't land it.
  5. Optional UI: add to the relevant tab component under src/components/settings/ (tab registry in SettingsDialog.tsx); settings.json-only is acceptable (precedent: toolSurface).
  6. Choose the era-faithful default (OFF for anything power-shaped — loopsEnabled is the template).
  7. Verify: both tsc configs + npx vitest run electron/services/default-app-settings.test.ts + affected tests.

Provenance and maintenance

Defaults table verified by direct read of electron/services/default-app-settings.ts and electron/services/loop-config.ts on 2026-07-02 (v0.16.0). Keychain/env/UI facts from electron/services/keychain.ts, electron/ipc/settings.ts, electron.vite.config.ts, src/components/settings/SettingsDialog.tsx.

Re-verify:

  • Defaults: sed -n '/DEFAULT_APP_SETTINGS/,/^}/p' electron/services/default-app-settings.ts
  • Parity lock: npx vitest run electron/services/default-app-settings.test.ts
  • Loop clamps: sed -n '/resolveLoopConfig/,/^}/p' electron/services/loop-config.ts
  • Settings tabs: grep -n "id: '" src/components/settings/SettingsDialog.tsx
  • Timeout defaults: grep -n "DEFAULT_STREAM_INACTIVITY_MS" electron/services/providers/registry.ts; grep -rn "120_000\|DEFAULT_MCP" electron/services/mcp-manager.ts | head -3

Signals

GitHub stars
62
Forks
2
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
lamprey-config-and-flags
Source
github.com/uss-parks/lamprey-harness