Imported from intelligenttools-ai/fritz-ai-local (
skills/brain-service-setup/SKILL.md). Install upstream withnpx skills add intelligenttools-ai/fritz-ai-local --skill brain-service-setup. Copyright stays with the author.
Brain Service Setup
Interactive provisioning runbook for the Fritz Local Brain Docker service. This skill collects all required answers, then delegates execution to the idempotent PROV1 engine — it never duplicates provisioning logic.
Trigger
Activate when the user asks to:
- Set up, provision, or reconfigure the Local Brain Docker service
- "Configure the brain service" or "start the brain Docker stack"
- Run
/brain-service-setup
Hard rules (read before proceeding)
- Do NOT write any file (
.env,registry.yaml, or any other config) before all questions in Phase 1 have been answered and the human has confirmed the summary in Phase 2. - Do NOT run any Docker command or call
local-brain-service.pybefore Phase 2 confirmation. - Do NOT implement provisioning logic yourself. Delegate every execution step to the PROV1 engine (see Phase 3).
- Ask questions one at a time. Wait for the answer before proceeding to the next question.
- If the human declines to answer a required question, explain why it is needed and ask again. Do not skip it silently.
- If the human asks to abort at any point before Phase 2 confirmation, stop immediately — write nothing.
Phase 1: Question set
Work through this ordered checklist. Show progress after each answer
(e.g., [3/10 answered]). Do not bundle questions.
Q1 — LLM protocol / source
"Which LLM backend will the service use?
a) OpenAI-compatible endpoint (self-hosted, Azure OpenAI, OpenRouter, etc.) b) Ollama running locally on this machine (will pull the model now) c) Official OpenAI API (api.openai.com)
Type a, b, or c."
- Record the answer as
llm_source. - If
b(Ollama), note you will ask for the model name and offer to pull it viaollama pull <model>after the full provision completes. - If
c, setllm_protocol=openai-compatible,llm_endpoint=https://api.openai.com/v1.
Q2 — LLM endpoint URL (skip if llm_source=b — the engine defaults to
http://host.docker.internal:11434/v1)
"What is the full base URL for the LLM API? (e.g.
http://host.docker.internal:11434/v1for a local Ollama,https://openrouter.ai/api/v1for OpenRouter)"
Validate that the URL starts with http:// or https:// and contains no
credentials, query strings, or fragments. Ask again if invalid.
Q3 — LLM model name
"Which model should the service use? (e.g.
llama3.2:latest,gpt-4o-mini,claude-3-5-haiku-20241022)"
Q4 — LLM API key
"Does this endpoint require an API key?
- Enter the key now (it will be stored in the repo-root
.envat mode 0600, never committed)- Or enter
none/ leave blank if no key is needed (local Ollama, etc.)"
Accept blank or none as equivalent to no key.
Q5 — Embeddings
"Do you want to enable embeddings? This indexes compiled knowledge articles for semantic search. Note: indexed text (article excerpts) is sent to the embedding provider you configure here — do not enable if your knowledge is sensitive and the provider is external.
yes / no"
If yes, ask two follow-up sub-questions (still one at a time):
Q5a — Embedding endpoint
"Embedding endpoint URL? (default: same as LLM endpoint,
http://host.docker.internal:11434/v1)"
Accept blank to reuse the LLM endpoint.
Q5b — Embedding model
"Embedding model name? (e.g.
nomic-embed-text:latest,text-embedding-3-small)"
Q6 — Scheduler
"Should the service run an automated background scheduler that periodically compiles and syncs?
yes / no"
If yes, ask two follow-up sub-questions:
Q6a — Interval
"How often should the scheduler run? Enter minutes (default: 30)"
Validate it is a positive integer.
Q6b — Scheduler mode
"Should the scheduler apply changes automatically (
apply) or only propose them for your review (propose/ dry-run)? (apply / propose)"
Record scheduler_dry_run = (answer == "propose").
Q7 — Autostart
"Should the service start automatically when you log in (OS-level autostart via launchd / systemd / Windows Task Scheduler)?
yes / no"
Q8 — Persistent scheduler approval token (optional)
"The scheduler uses an approval token to gate large-batch compiles. Should a persistent APPROVAL_TOKEN be written to
.envnow?
- Enter a token string to set it, OR
- Leave blank to skip (the scheduler will run without large-batch gating unless you edit
.envmanually later)enter a token string / leave blank"
Map a provided token to --approval-token <token>.
Important — persistent vs. one-time:
--approval-token <token>writesAPPROVAL_TOKENto.envpermanently. The running scheduler reads it on every large-batch compile decision.- This is completely separate from
--drain-approval-token, which is only forwarded in the single one-time backlog-drain POST and is never persisted.
Q9 — Reconciliation autonomy
"When new knowledge is reconciled against existing knowledge, should the reconciliation agent apply changes automatically or only propose them?
a) apply — changes are written automatically (default) b) propose — changes are proposed for your review (dry-run)
apply / propose"
Map to --reconciliation-autonomy <value>. Defaults to apply if left blank.
Q10 — Context injection level
"What context-injection level should hooks use when matching prompts to existing knowledge? I recommend
lightfor retrieval at the moment of need.off / light / full (default/recommended: light)"
Record context_injection as exactly one of off, light, or full. Map it
to --context-injection <value>.
Q11 — One-time backlog drain (optional)
"Do you want to trigger a one-time apply-mode compile immediately after provisioning, to drain any pending captures from the backlog?
yes / no (default: no)"
If yes, ask one follow-up sub-question:
Q11a — Drain approval token (only if Q11 = yes)
"If the backlog is large (above the service's batch threshold), the compile will require an approval token to proceed. Enter a token string now, or leave blank to let the compile proceed without one (it will be rejected with 403 if the batch is too large and no token is supplied).
enter a token string / leave blank"
Important — what this does and does not do:
--drain-backlogtriggers a single, one-time apply-mode compile POST at the end of the provision run. It is not a standing scheduler setting.--drain-approval-token <token>is included in that one POST request only. It is not written to.env, it is not persisted anywhere, and it has no effect if--drain-backlogis omitted.- The persistent
APPROVAL_TOKENis set via--approval-token(Q8), not here.
Q12 — API token
"The service exposes a local REST API protected by a Bearer token.
- Enter a token you want to use, OR
- Leave blank to auto-generate a cryptographically random token
(The token will be written to
.envand to~/.brain/registry.yaml)"
Q13 — Telemetry (usage dashboard)
"The service can record usage telemetry that powers the
/dashboardview.
- Enable usage telemetry? (yes / no, default: yes)
- Store the full query text in telemetry? (yes / no, default: yes — answer no for privacy; only counts/metadata are kept)
- Telemetry retention in days? (default: 90; 0 = keep forever)"
Records telemetry_enabled, telemetry_store_query_text,
telemetry_retention_days. Defaults: enabled, store query text, 90-day
retention.
After all thirteen questions (plus sub-questions) are answered, proceed to Phase 2.
Phase 2: Summary and confirmation
Print a structured summary of every answer collected in Phase 1. Use a format like:
Brain Service Setup — Proposed Configuration
=============================================
LLM
Protocol : openai-compatible
Endpoint : http://host.docker.internal:11434/v1
Model : llama3.2:latest
API key : (none)
Embeddings
Enabled : yes
Endpoint : http://host.docker.internal:11434/v1 (shared with LLM)
Model : nomic-embed-text:latest
Note : indexed text will be sent to this endpoint
Scheduler
Enabled : yes
Interval : 30 minutes
Mode : dry-run (propose only)
Autostart : no
Context injection : light
Reconciliation autonomy: apply
Drain backlog : no (skip one-time post-provision compile)
API token : (auto-generate)
Execution plan
1. Preflight: check docker, docker compose, python, port 8765
2. Write / merge repo-root .env (mode 0600)
3. Write / merge ~/.brain/registry.yaml
4. docker compose build + up -d
5. Poll /health until ready, then probe LLM reachability
6. (autostart skipped)
No files will be written until you confirm.
Then ask:
"Proceed with provisioning? (yes / no — or change any answer by naming the question number)"
If the human names a question number to change, re-ask that question (and any affected sub-questions), update the summary, and ask for confirmation again.
Do NOT proceed until the human explicitly confirms with yes.
Phase 3: Delegate to PROV1
Once the human confirms, invoke the PROV1 engine. Do NOT implement any provisioning logic yourself.
The engine entry point is:
python scripts/local-brain-service.py provision \
--llm-protocol <protocol> \
--llm-endpoint <endpoint> \
--llm-model <model> \
[--llm-api-key <key>] \
[--embedding-enabled] \
[--embedding-endpoint <endpoint>] \
[--embedding-model <model>] \
[--scheduler-enabled] \
[--scheduler-apply] \
--context-injection <off|light|full> \
--api-port 8765 \
[--install-autostart] \
[--api-token <token>] \
[--approval-token <token>] \
[--reconciliation-autonomy apply|propose] \
[--telemetry-enabled | --no-telemetry-enabled] \
[--telemetry-store-query-text | --no-telemetry-store-query-text] \
[--telemetry-retention-days <days>] \
[--drain-backlog [--drain-approval-token <token>]]
Run this from the fritz-ai-local repo root. The engine is idempotent — it is safe to re-run to reconfigure. Pass flags that match the confirmed answers:
| Answer | Flag(s) |
|---|---|
| embeddings yes | --embedding-enabled |
| scheduler yes + apply mode | --scheduler-enabled --scheduler-apply |
| scheduler yes + propose mode | --scheduler-enabled (dry-run is the default) |
| autostart yes | --install-autostart |
| context injection level | `--context-injection <off |
| API token provided | --api-token <token> (omit to auto-generate) |
| persistent approval token provided (Q8) | --approval-token <token> |
| reconciliation autonomy = propose (Q9) | --reconciliation-autonomy propose |
| reconciliation autonomy = apply (Q9) | --reconciliation-autonomy apply (default; may omit) |
| telemetry enabled (Q13) | --telemetry-enabled (default; may omit) |
| telemetry disabled (Q13) | --no-telemetry-enabled |
| store query text (Q13) | --telemetry-store-query-text (default; may omit) |
| do not store query text (Q13) | --no-telemetry-store-query-text |
| telemetry retention (Q13) | --telemetry-retention-days <days> (default 90; 0 = keep forever) |
| drain backlog yes | --drain-backlog |
| drain backlog yes + one-time approval token | --drain-backlog --drain-approval-token <token> |
Token flag semantics — keep these distinct:
--approval-token <token>writesAPPROVAL_TOKENpersistently to.env. The running scheduler reads it on every large-batch compile decision. This is the persistent setting that gates ongoing scheduler runs.--drain-approval-token <token>is forwarded in the single one-time backlog-drain POST only; it is not written to.envand has no effect outside that one request. Omitting--drain-backlogmakes this flag inert.- These two flags are independent and serve different purposes. Do not conflate them.
The provision sub-command is also aliased as setup, so
python scripts/local-brain-service.py setup … is equivalent.
Do not pass flags not supported by the engine. Do not invent provisioning
behavior the engine does not implement. Refer to scripts/provision_engine.py
(ProvisionConfig dataclass + provision(...) function) for the canonical
list of supported inputs.
Phase 4: Post-provision
After the engine returns, report the result to the human.
If the engine succeeds (overall: ok or overall: already_provisioned)
Print each step with its status marker:
Provision result: ok
✓ preflight : docker ok; docker compose ok; python ok; port 8765: free
✓ write_env : .env: merged 20 keys
✓ write_registry: ~/.brain/registry.yaml: wrote local_brain_service
✓ docker_start : build + up -d completed
✓ verify : service healthy; LLM reachable
– install_autostart: autostart not requested
Then show the operational state:
Service is running at http://127.0.0.1:8765
API token: <token> (also in .env as API_TOKEN and in ~/.brain/registry.yaml)
Other brain-* skills (brain-compile, brain-query, brain-sync) now route
through the service automatically when it is reachable.
Then register the Claude Code capture hooks. The binding is a directory-source
marketplace, so its skills load but its hooks do NOT auto-register — without
this step Claude records 0 captures. Run the installer (idempotent; merges into
~/.claude/settings.json, preserving other plugins' hooks):
python3 <REPO>/hooks/install_claude_hooks.py
If llm_source=b (Ollama) and the user agreed to pull the model, offer:
"Would you like me to run
ollama pull <model>now to ensure the model is available locally?"
If the engine returns overall: partial or overall: failed
Report each failed/warning step. Do not attempt to fix failures yourself — surface the error and tell the human how to re-run after resolving it:
Some steps failed. Fix the errors above, then re-run:
python scripts/local-brain-service.py provision [same flags]
The engine is idempotent — steps that already completed will be skipped.
Reconfigure / Rollback
Changing LLM backend, embeddings, or scheduler settings
To change any configuration (e.g. switch from Ollama to OpenAI, enable embeddings, change the scheduler interval):
-
Check for drift first (optional but informative):
python scripts/local-brain-service.py reconfigure \ --llm-model gpt-4o-mini \ --llm-endpoint https://api.openai.com/v1 \ --llm-api-key sk-... \ [other flags] \ --forceThe
reconfiguresub-command (alias:re-provision) detects which keys in the running container differ from the desired config (drift detection), then re-applies provisioning via the PROV1 engine. It never duplicates provisioning logic — it delegates toprovision()internally.- Drift detected → re-provision runs automatically (build + up + verify).
- No drift + no
--force→ returnsno_drift; nothing runs. --force→ re-provision always runs regardless of drift state.
-
Or run provision directly (equivalent, and always idempotent):
python scripts/local-brain-service.py provision \ --llm-model gpt-4o-mini \ --llm-endpoint https://api.openai.com/v1 \ --llm-api-key sk-...The engine merges new values into the existing
.envwithout destroying unrelated keys, then rebuilds and restarts the container. Steps that are already correct are skipped.
Both paths handle container restart (via docker compose build + up -d) and
verify reachability after the change.
Rolling back to local-only mode (no data loss)
To disable the Docker service and fall back to local slash-skill brain workflows without losing any capture or knowledge data:
python scripts/local-brain-service.py rollback
What rollback does:
- Sets
settings.local_brain_service.desired: localandsettings.local_brain_service.enabled: falsein~/.brain/registry.yaml, preserving all other keys (vaults, external targets, other settings, the API token, etc.). - Runs
docker compose downto stop the container (pass--no-stopto leave it running while only updating the registry). - Does NOT delete
~/.brain/capture/or~/.brain/knowledge/— all data is preserved on the host volume. - Does NOT modify
.env.
After rollback:
get_local_brain_service_desired()returns"local"— agents no longer inject the forcing instruction.local_brain_service_enabled()returnsFalse— service routing is off.- Brain operations fall back to local slash-skill workflows automatically.
To re-enable the service after a rollback, re-run provision (or this skill)
with your desired configuration. The --api-token flag accepts the token
previously stored in ~/.brain/registry.yaml; if omitted, the existing token
in .env is preserved automatically.
Important
- This skill collects answers and confirms them before delegating to PROV1. It never implements or duplicates provisioning steps.
- The PROV1 engine handles
.envwrites, registry updates, Docker build/start, health polling, and autostart installation. Trust it. - The engine is idempotent: steps that are already correct are skipped without side effects.
- If
settings.local_brain_serviceis already configured in~/.brain/registry.yaml, note this at the start of Phase 1:"The service is already configured. I will ask the same questions so you can change any setting. Unchanged values can be confirmed as-is."
- Do not invent extra provisioning steps beyond what the engine supports. Check
scripts/provision_engine.py(ProvisionConfig) for the authoritative list.