| name | wicked-brain-init |
| description | Initialize a new digital brain. Creates the directory structure, brain.json,
and config. Auto-triggered on first use of any brain skill when no config exists.
Use when: "set up a brain", "create a brain", "brain init", or when any brain
skill detects no config.
|
wicked-brain:init
Initializes a new digital brain on the filesystem and gets it fully operational.
Cross-Platform Notes
Commands in this skill work on macOS, Linux, and Windows. When a command has
platform differences, alternatives are shown. Your native tools (Read, Write,
Grep, Glob) work everywhere โ prefer them over shell commands when possible.
Per-project brains (important)
Each project gets its own brain under ~/.wicked-brain/projects/{project-name}/.
Do NOT initialize a single monolithic brain at ~/.wicked-brain/ โ that overwhelms
the index, mixes unrelated content across clients/codebases, and makes federated
search useless.
The structure is:
~/.wicked-brain/ # parent directory (not a brain)
projects/
my-app/ # one brain per project
brain.json
chunks/
_meta/
client-site/ # another project's brain
brain.json
...
Project name defaults to the basename of the current working directory
(lowercase, hyphens for spaces). A supervising "meta-brain" agent can watch
~/.wicked-brain/projects/* and federate across all of them via
brain.json links.
For the brain path default:
- macOS/Linux:
~/.wicked-brain/projects/{project_name}
- Windows:
%USERPROFILE%\.wicked-brain\projects\{project_name}
Resolving the brain config
Most consumer skills now invoke wicked-brain-call directly and don't
need to resolve the brain themselves โ see the section below for the
canonical resolution this skill performs at init time.
This section is the canonical resolution logic. Other skills point here โ
keep it authoritative. Never read a bare relative _meta/config.json: the
model will resolve it against the current working directory and brain files
will land in the project root.
To locate the brain config for the current session:
- Compute
{cwd_basename} โ the basename of the current working directory run
through the canonical slug rule (projectId() in
server/lib/project-id.mjs; the full rule โ NFKD fold, lowercase,
non-alphanumerics โ hyphens, empty-fold brain-<sha1> fallback โ is spelled
out under Step 1 below). For ordinary names this is just lowercase +
non-alphanumerics โ hyphens.
- Try
~/.wicked-brain/projects/{cwd_basename}/_meta/config.json first
(Windows: %USERPROFILE%\.wicked-brain\projects\{cwd_basename}\_meta\config.json).
- If that file doesn't exist, fall back to the legacy flat path
~/.wicked-brain/_meta/config.json (Windows:
%USERPROFILE%\.wicked-brain\_meta\config.json).
- If neither exists, trigger
wicked-brain:init.
- Read the resolved file. It contains
brain_path and server_port (and
optionally source_path). All subsequent operations use these values โ
never hardcode the port or path.
Any skill that needs to read, write, or reference _meta/config.json MUST use
this resolution. Never compute _meta/config.json against the project's cwd.
When to use
- User explicitly asks to create/initialize a brain
- Another brain skill detected no
_meta/config.json and redirected here
Process
Step 1: Ask the user
Ask in this exact order โ do not reverse the questions.
First, compute {cwd_basename}:
basename "$PWD"
Split-Path -Leaf (Get-Location)
This gives you the name of the project the user is currently working in โ the repo or
directory they are about to index. It has nothing to do with wicked-brain, the skill name,
or any installed tool. For example:
- User is in
/Users/alice/Projects/wicked-bus โ default name is wicked-bus
- User is in
/home/bob/work/my-api โ default name is my-api
- User is in
/Users/mike/Projects/wicked-brain โ default name is wicked-brain (only
correct if they are literally indexing the wicked-brain repo itself)
Apply the canonical slug rule below. It is byte-for-byte identical to
projectId() in server/lib/project-id.mjs โ that function is the single
source of truth; this text just mirrors it so an agent computing the slug by
hand lands on the same dir the CLI resolves. For an ordinary ASCII repo name it
reduces to "lowercase, non-alphanumerics โ hyphens", but the full rule is:
- Unicode-normalize with NFKD and strip combining marks, folding accents and
compatibility forms toward ASCII (
cafรฉ โ cafe, Zรผrich โ zurich,
๏ฌnance โ finance).
- Lowercase.
- Replace every run of non-
[a-z0-9] characters with a single hyphen.
- Trim leading and trailing hyphens.
- Fallback: if nothing survives (e.g. an all-CJK name folds to empty), use
brain- + the first 8 hex chars of sha1(original name), so two distinct
names never collapse to the same empty slug.
Canonical project id. This is the ONE canonical slug for a repo, produced
by projectId() in server/lib/project-id.mjs โ treat that function as
authoritative and do not re-derive a simpler rule. The id you pick here and the
dir wicked-brain-call auto-resolves therefore always match. Underscores and
spaces collapse to hyphens: command_iq and My Repo become command-iq and
my-repo. Do NOT keep the raw basename (e.g. command_iq) as the id โ a raw-basename brain dir
and a kebab brain dir for the same repo is the split-brain fragmentation from
wicked-brain#56, where one repo's memory ends up scattered across two stores
and lookups silently resolve to the empty one. If you find both a raw-basename
dir and a kebab dir under ~/.wicked-brain/projects/ for the same repo, run
wicked-brain:migrate to merge them into the canonical (kebab) id.
Then ask two questions, in order:
-
"What should this project's brain be called?"
- Default:
{cwd_basename} โ computed above from the actual current working directory
- Wait for the user's answer (or acceptance of default) before asking question 2.
-
"Where should it live?"
- Default:
- macOS/Linux:
~/.wicked-brain/projects/{project_name} (where {project_name} is the name from question 1)
- Windows:
%USERPROFILE%\.wicked-brain\projects\{project_name}
- The default path MUST include the
projects/ subdirectory and the project name.
Never default to just ~/.wicked-brain/ โ that is the parent container, not a brain.
If the user supplies a path that is exactly ~/.wicked-brain (the parent
directory, not a project subdirectory), push back: explain the per-project
convention and suggest ~/.wicked-brain/projects/{project_name} instead.
Only accept the flat path if the user explicitly insists.
The projects/ infix is mandatory โ do not invent alternate layouts
The ONLY valid brain path under the default container is
~/.wicked-brain/projects/{name}/. Common misreadings to avoid:
- โ
~/.wicked-brain/{name}/ โ missing the projects/ segment. Not valid.
- โ
~/.{name}-brain/ โ sibling directory. Not the convention.
- โ
~/.wicked-brain/projects/{name}/projects/{subname}/ โ nested brains. Not supported.
If the user asks "why not ~/.wicked-brain/{name}?" the answer is: the projects/
segment is a deliberate namespace. The parent ~/.wicked-brain/ is a container
that may hold other metadata (linked brain indexes, federation config, etc.),
and every brain lives under projects/ to keep that clean.
Do not improvise alternate layouts when you hit an obstacle. If the documented
path is occupied, invoke the migration flow (Step 2a) โ do not pick a sibling
directory or a nested path.
Step 2: Check for existing brains
2a: Detect a flat brain at the parent path
Check first, before anything else: does ~/.wicked-brain/brain.json exist?
(That is brain.json at the flat parent path, NOT inside projects/.) If yes,
this is a legacy flat brain from before v0.4.7 and you MUST STOP the init
flow and resolve it before continuing.
Read ~/.wicked-brain/brain.json to find the existing brain's name, then tell
the user exactly this (substituting the real name):
"Heads up โ there's already a legacy flat brain at ~/.wicked-brain/ named
{existing_name}. The current layout puts each project under
~/.wicked-brain/projects/{name}/, so I can't just create a new brain at the
parent path without clobbering it. You have two options:
- Migrate the existing
{existing_name} brain to
~/.wicked-brain/projects/{existing_name}/ first, then create the new
{project_name} brain alongside it. Recommended.
- Keep the flat
{existing_name} brain where it is and create the new
brain at ~/.wicked-brain/projects/{project_name}/. This works but leaves
the old brain in a legacy layout.
Which do you want?"
Do NOT propose any other options. Do NOT suggest a sibling directory like
~/.wicked-bus-brain. Do NOT suggest nesting inside the existing brain. Do NOT
proceed with overwriting ~/.wicked-brain/brain.json under any circumstances.
If the user picks option 1, invoke wicked-brain:migrate with
flat_path=~/.wicked-brain and wait for it to complete before continuing.
If the user picks option 2, proceed with the new brain at
~/.wicked-brain/projects/{project_name}/ โ the flat brain stays untouched.
2b: Check target path
If {brain_path}/_meta/config.json already exists at the chosen target, tell the user:
"A brain already exists at {brain_path}. Do you want to re-initialize it (keeps existing chunks) or pick a different path?"
Stop and wait for their answer before continuing.
Step 3: Create directory structure
Use the native Write tool to create these directories (write a .gitkeep placeholder in each):
{brain_path}/raw
{brain_path}/chunks/extracted
{brain_path}/chunks/inferred
{brain_path}/wiki/concepts
{brain_path}/wiki/topics
{brain_path}/memory
{brain_path}/_meta
Shell equivalents if needed:
mkdir -p {brain_path}/raw {brain_path}/chunks/extracted {brain_path}/chunks/inferred \
{brain_path}/wiki/concepts {brain_path}/wiki/topics {brain_path}/memory {brain_path}/_meta
# Windows PowerShell
New-Item -ItemType Directory -Force -Path "{brain_path}\raw","{brain_path}\chunks\extracted","{brain_path}\chunks\inferred","{brain_path}\wiki\concepts","{brain_path}\wiki\topics","{brain_path}\memory","{brain_path}\_meta"
Step 4: Write brain.json
Write to {brain_path}/brain.json:
{
"schema": 1,
"id": "{id}",
"name": "{name}",
"parents": [],
"links": []
}
Where {id} is the directory name (lowercase, hyphens for spaces) and {name} is what the user provided.
Step 5: Write config
Write to {brain_path}/_meta/config.json:
{
"brain_path": "{absolute_path}",
"server_port": 4242,
"installed_clis": []
}
server_port: 4242 is the preferred starting port, not the guaranteed port.
When the server starts in Step 7, it probes from this value upward until it
finds a free port, then writes the actual port back to this same file.
If multiple project brains run at once, each gets a distinct port (4242, 4243,
4244, ...). Always re-read _meta/config.json after the server starts to get
the real port โ never hardcode 4242 in downstream calls.
Step 6: Initialize the event log
Use the Write tool to create an empty file at {brain_path}/_meta/log.jsonl.
Step 7: Start the server
Use wicked-brain-call to start and verify the server in one step. It picks
a free port, writes it back to _meta/config.json, and waits for the server
to answer:
npx wicked-brain-call --start --brain {brain_path}
npx wicked-brain-call health --brain {brain_path}
Verify the health response includes "brain_id" matching this brain's id โ
this confirms you're talking to the right server (not an unrelated brain on
the same machine).
If you need the raw spawn (e.g. to pass extra flags), the server binary is
still available directly:
npx wicked-brain-server --brain {brain_path} &
Do NOT pass --port unless the user specifies one โ let the server pick a
free port.
Step 8: Ingest the project
Invoke wicked-brain:ingest with:
brain_path: {brain_path}
source: the current working directory
This indexes the project files so the brain is immediately queryable.
Step 9: Configure the CLI
Invoke wicked-brain:configure to write routing instructions into the active
CLI's agent config (CLAUDE.md, GEMINI.md, etc.). This is what makes the brain
the default for search and exploration โ do not skip this step.
Step 10: Emit bus event
If wicked-bus is available, emit an initialization event:
npx wicked-bus emit \
--type "wicked.brain.index.initialized" \
--domain "wicked-brain" \
--subdomain "brain" \
--payload '{"brain_id":"{id}","brain_path":"{brain_path}","name":"{name}"}' 2>/dev/null || true
This is fire-and-forget โ if the bus is not installed, the command silently fails.
Step 11: Confirm
Tell the user:
"Brain {name} is ready at {brain_path} โ {N} files ingested, {M} chunks indexed.
CLI configured to route search and explore requests through the brain.
Run wicked-brain:compile to synthesize wiki articles from the indexed content."