Skip to content

Commit affa62f

Browse files
pdfinnclaude
andauthored
docs: add developer guide
Covers running InferNode from the terminal with full command breakdown, capturing logs, the ~/.infernode overlay directory, resetting tour/ secstore/full installation, debugging common issues, and environment variables. Fills documentation gaps identified during v0.1 release testing. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent eaf57c4 commit affa62f

1 file changed

Lines changed: 283 additions & 0 deletions

File tree

docs/DEVELOPER-GUIDE.md

Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
# Developer Guide: Running, Debugging, and Resetting InferNode
2+
3+
This guide covers running InferNode from the command line for development,
4+
debugging, and testing. For building from source, see QUICKSTART.md. For
5+
the testing framework, see the Testing System section in CLAUDE.md.
6+
7+
## Running from the Command Line
8+
9+
### Minimal Startup (Interpreter Only, No GUI)
10+
11+
```sh
12+
cd infernode
13+
./emu/MacOSX/o.emu -r. sh -l
14+
```
15+
16+
This starts the Inferno shell with your profile loaded (`-l`). You get a
17+
text console — no GUI, no agent, no LLM.
18+
19+
### Full GUI Startup
20+
21+
```sh
22+
cd infernode/emu/MacOSX
23+
./o.emu -c1 -pheap=1024m -pmain=1024m -pimage=1024m -r../.. \
24+
sh -l -c "wm/logon; \
25+
llmsrv &; sleep 1; \
26+
/dis/veltro/wallet9p.dis &; sleep 1; \
27+
luciuisrv; \
28+
echo activity create Main > /n/ui/ctl; sleep 1; \
29+
/dis/veltro/tools9p -v -m /tool \
30+
-b read,list,find,search,grep,write,edit,editor,exec,launch,spawn,diff,json,fractal,webfetch,git,say,memory,todo,plan,websearch,mail,keyring,present,gap \
31+
-p /dis/wm read list find present say hear task memory gap keyring editor shell; \
32+
lucibridge -a 0 -v -s &; sleep 1; \
33+
echo 'create id=tasks type=taskboard label=Tasks' > /n/ui/activity/0/presentation/ctl; \
34+
lucifer"
35+
```
36+
37+
This is equivalent to what the app bundle does via `lib/sh/profile` and
38+
`lib/lucifer/boot.sh`, but laid out explicitly so you can see and modify
39+
each step.
40+
41+
### Breaking Down the Command
42+
43+
**Emulator flags:**
44+
45+
| Flag | Purpose |
46+
|------|---------|
47+
| `-c1` | Enable JIT compilation (ARM64 or AMD64). Use `-c0` for interpreter only. |
48+
| `-pheap=1024m` | Heap pool size (memory for Limbo allocations) |
49+
| `-pmain=1024m` | Main pool size (memory for kernel data structures) |
50+
| `-pimage=1024m` | Image pool size (memory for draw images/GUI) |
51+
| `-r../..` | Inferno root directory. Points to the project checkout. The path is concatenated directly to `-r` with no space. |
52+
53+
**Boot sequence (inside `sh -l -c "..."`):**
54+
55+
The `-l` flag loads `lib/sh/profile` which sets up networking, the host
56+
filesystem mount (`trfs`), the `~/.infernode` writable overlay, secstored,
57+
and factotum. Then `-c` runs the quoted command string:
58+
59+
| Step | Command | Purpose |
60+
|------|---------|---------|
61+
| 1 | `wm/logon` | Login screen. Creates secstore account on first run, unlocks and loads keys on subsequent runs. Blocks until the user enters their password. |
62+
| 2 | `llmsrv &` | LLM 9P file server. Mounts at `/n/llm`. Reads config from `lib/ndb/llm` (via profile). The `&` backgrounds it. |
63+
| 3 | `wallet9p &` | Cryptocurrency wallet 9P server. Experimental. |
64+
| 4 | `luciuisrv` | UI 9P server. Creates the `/n/ui` namespace that lucifer, lucipres, luciconv, and lucibridge all communicate through. This is the hub. |
65+
| 5 | `echo activity create Main > /n/ui/ctl` | Creates the default "Main" activity (task/conversation). |
66+
| 6 | `tools9p -v -m /tool -b ... -p ...` | Veltro tool server. `-b` lists built-in tool modules. `-p` lists tools available to the agent as "passive" (invocable). Mounts at `/tool`. |
67+
| 7 | `lucibridge -a 0 -v -s &` | Agent bridge. Connects the conversation zone to the LLM. `-a 0` targets activity 0, `-v` verbose, `-s` enables speech. |
68+
| 8 | `echo 'create id=tasks ...' > /n/ui/...` | Creates the Tasks taskboard tab in the presentation zone. |
69+
| 9 | `lucifer` | Main GUI. Blocks until the user exits. When lucifer returns, emu shuts down. |
70+
71+
**Important:** Commands are separated by `;` not `&&`. The Inferno shell
72+
is rc-style and does not support `&&` or `||` operators.
73+
74+
### Capturing Logs
75+
76+
The app bundle suppresses stderr. To see diagnostic output:
77+
78+
```sh
79+
/path/to/InferNode.app/Contents/MacOS/InferNode 2>/tmp/infernode.log
80+
```
81+
82+
Or from a dev checkout:
83+
84+
```sh
85+
cd infernode/emu/MacOSX
86+
./o.emu -c1 -pheap=1024m -pmain=1024m -pimage=1024m -r../.. \
87+
sh -l /lib/lucifer/boot.sh 2>/tmp/infernode.log
88+
```
89+
90+
Key log messages to look for:
91+
92+
| Message | Meaning |
93+
|---------|---------|
94+
| `logon: loaded N keys from secstore` | Secstore unlocked successfully, N keys restored |
95+
| `logon: secstore has no factotum file` | No saved keys (first run or read failure) |
96+
| `factotum: secstore configured` | Save-back to secstore is active |
97+
| `lucibridge: ready` | Agent is connected and waiting for input |
98+
| `lucibridge: llm configured but not ready` | LLM service failed to start |
99+
| `tools9p: warning: cannot load tool X` | A tool's .dis file is missing (rebuild needed) |
100+
101+
### Running Without the Agent
102+
103+
To test the GUI without Veltro/LLM (useful for UI work):
104+
105+
```sh
106+
cd infernode/emu/MacOSX
107+
./o.emu -c1 -pheap=1024m -pmain=1024m -pimage=1024m -r../.. \
108+
sh -l -c "wm/logon; luciuisrv; echo activity create Main > /n/ui/ctl; sleep 1; lucifer"
109+
```
110+
111+
This starts logon, the UI server, and lucifer — but no llmsrv, no
112+
lucibridge, no tools9p. The conversation zone will be empty.
113+
114+
## The ~/.infernode Directory
115+
116+
InferNode stores all user data in `~/.infernode`, separate from the
117+
read-only emu root (whether that's an app bundle or a dev checkout).
118+
The profile creates this directory on first run and bind-mounts its
119+
subdirectories over the corresponding paths in the Inferno namespace.
120+
121+
### Directory Structure
122+
123+
```
124+
~/.infernode/
125+
usr/inferno/secstore/ # Encrypted key storage (PAK + factotum files)
126+
usr/inferno/tmp/ # Persistent temp files
127+
lib/ndb/ # LLM config (lib/ndb/llm)
128+
lib/lucifer/theme/ # GUI theme (current)
129+
lib/veltro/ # Agent state (welcome_shown, tour_offered, meta.txt)
130+
lib/veltro-agents/ # Task agent prompts
131+
lib/veltro-keys/ # Agent API keys
132+
tmp/ # Session temp files
133+
```
134+
135+
### How It Works
136+
137+
The profile (`lib/sh/profile`) uses `bind -bc` to overlay each
138+
`~/.infernode` subdirectory onto the corresponding Inferno path:
139+
140+
```
141+
bind -bc ~/.infernode/usr/inferno/secstore /usr/inferno/secstore
142+
bind -bc ~/.infernode/lib/ndb /lib/ndb
143+
bind -bc ~/.infernode/lib/veltro /lib/veltro
144+
...
145+
```
146+
147+
The `-bc` flags mean: **b**efore (overlay takes priority over the
148+
original) and **c**reate (new files go to the overlay, not the original).
149+
This means writes always go to `~/.infernode` while reads fall through
150+
to the emu root for defaults.
151+
152+
### Why It Exists
153+
154+
Without the overlay, user data would be written into the emu root.
155+
In an app bundle, the emu root is inside the signed `.app` — read-only.
156+
Even in a dev checkout, mixing user data with source code is messy.
157+
The overlay keeps the emu root clean and user state portable.
158+
159+
## Resetting
160+
161+
### Reset the Guided Tour
162+
163+
The tour is offered once per installation. To see it again:
164+
165+
```sh
166+
rm ~/.infernode/lib/veltro/tour_offered
167+
```
168+
169+
On next launch, Veltro will offer the guided tour again.
170+
171+
### Reset the Welcome Message
172+
173+
```sh
174+
rm ~/.infernode/lib/veltro/welcome_shown
175+
```
176+
177+
### Full Reset (Start Fresh)
178+
179+
**WARNING: This deletes your secstore password, all saved API keys,
180+
LLM configuration, theme, and agent state. You will need to set up
181+
everything from scratch on next launch.**
182+
183+
```sh
184+
rm -rf ~/.infernode
185+
```
186+
187+
On next launch, the profile detects the missing directory, recreates
188+
it, seeds defaults, and the login screen shows the first-run setup.
189+
190+
### Reset Only Secstore (Keep Config)
191+
192+
To clear saved keys without wiping everything:
193+
194+
```sh
195+
rm -rf ~/.infernode/usr/inferno/secstore
196+
```
197+
198+
On next launch, logon will show the first-run password setup.
199+
200+
## Debugging Common Issues
201+
202+
### "Launching..." Stuck on App Tab
203+
204+
The app's .dis file may be stale (compiled against an old module
205+
interface). Rebuild:
206+
207+
```sh
208+
export ROOT=$PWD PATH=$PWD/MacOSX/arm64/bin:$PATH
209+
cd appl/cmd && mk install # or the specific directory
210+
```
211+
212+
### Blank Conversation Zone / "LLM configured but not ready"
213+
214+
llmsrv failed to start. Common causes:
215+
216+
- **No API key:** Add one via Keyring, or set `ANTHROPIC_API_KEY` env var
217+
- **Wrong backend:** Check `~/.infernode/lib/ndb/llm``backend=openai`
218+
needs a URL like `http://127.0.0.1:11434/v1` (not `localhost`)
219+
- **Model doesn't support tools:** Use a tool-capable model (llama3.2,
220+
qwen2.5, mistral) — llama2 does not support tools and returns empty
221+
222+
### Login Asks for Password Setup Again
223+
224+
The secstore overlay may not have loaded. Check:
225+
226+
```sh
227+
ls ~/.infernode/usr/inferno/secstore/$(whoami)/PAK
228+
```
229+
230+
If PAK exists, it's a trfs timing issue (see boot.sh warmup). If it
231+
doesn't exist, secstore wasn't saved — you'll need to set up again.
232+
233+
### "link typecheck" Errors
234+
235+
A `.dis` file was compiled against an old `.m` interface. Rebuild
236+
the affected directory:
237+
238+
```sh
239+
export ROOT=$PWD PATH=$PWD/MacOSX/arm64/bin:$PATH
240+
cd appl/xenith && mk install # if xenith modules changed
241+
cd appl/cmd && mk install # if cmd modules changed
242+
```
243+
244+
See the "Stale bytecode problem" section in CLAUDE.md for details.
245+
246+
### Tests Fail With "cannot load testing module"
247+
248+
The testing framework .dis is missing or stale:
249+
250+
```sh
251+
export ROOT=$PWD PATH=$PWD/MacOSX/arm64/bin:$PATH
252+
cd appl/lib && mk testing.dis
253+
cd tests && mk install
254+
```
255+
256+
## Environment Variables
257+
258+
| Variable | Purpose |
259+
|----------|---------|
260+
| `ANTHROPIC_API_KEY` | API key fallback (used if not in secstore) |
261+
| `SECSTORE_PASSWORD` | Headless mode: auto-unlock secstore without login screen |
262+
| `OLLAMA_HOST` | Not used by InferNode — configure via Settings or `lib/ndb/llm` |
263+
264+
## Platform Notes
265+
266+
### macOS (Apple Silicon)
267+
268+
- Emulator binary: `emu/MacOSX/o.emu` (or `InferNode.app/Contents/MacOS/emu`)
269+
- Native tools: `MacOSX/arm64/bin/mk`, `MacOSX/arm64/bin/limbo`
270+
- JIT: ARM64 JIT with `-c1`
271+
272+
### Linux (AMD64)
273+
274+
- Build: `./build-linux-amd64.sh`
275+
- Emulator binary: `emu/Linux/o.emu`
276+
- Native tools: `Linux/amd64/bin/mk`, `Linux/amd64/bin/limbo`
277+
- JIT: AMD64 JIT with `-c1`
278+
279+
### Linux (ARM64, e.g. NVIDIA Jetson)
280+
281+
- Build: `./build-linux-arm64.sh`
282+
- Native tools: `Linux/arm64/bin/mk`, `Linux/arm64/bin/limbo`
283+
- JIT: ARM64 JIT with `-c1`

0 commit comments

Comments
 (0)