Pullboard
A work board that lives in your git repo. Agents pick up the next task, another agent checks it, and you barely explain a thing. Local, open source, no account.
Watch your model learn: fine-tune LLMs on your Mac in a few clicks and see, layer by layer, what training changed.
Developer toolsPython · JavaScriptGitHub @Yiteng-CHENOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗Watch your model learn. Fine-tune an LLM on your Mac in a few clicks — and see, layer by layer, what training actually changed.
▶ Try the online demo (no install; replays a real recorded run) · English · 简体中文
Most fine-tuning tools stop at "training finished, loss = 1.23". Most interpretability tools show a model you cannot change. Neurolume puts both in one local app: you train the model, and you watch its insides while you do it.
Status: early alpha. Server, UI and tooling are unit-tested (110+ tests, no GPU needed). Everything below runs on one machine so far (MacBook Pro M5 Max, 128 GB). Verified there with Devstral Small 2 and Qwen3.6-27B: live layer probe, logit lens (live, and computed afterwards for answers generated without it), per-token confidence, guided LoRA training (Devstral: 36 steps, 15 GB peak, validation loss 4.45 → 1.06), before/after comparison, MLX export and training-data generation. Ollama export is not hardware-tested yet. Reports from other machines are very welcome.
Fine-tune without writing code
.jsonl, notes, code, or your ChatGPT / Claude / Claude Code chat history — or let the loaded model generate a dataset from your own files: Q&A pairs from documents, or "requests → your own code/writing" pairs that teach your style. You review and edit every item before training.See inside the model
Use it every day
/v1/chat/completions, streaming), one-click model library, knowledge base (import books/docs for retrieval), opt-in web search for local models (also as an MCP server), and an agent that reads a project folder and proposes edits you approve one by one (with undo).Everything labelled as the model's activity comes from the model; simulated data is labelled. Full definitions in docs/SIGNALS.md.
| Shown | Source |
|---|---|
| Layer count and types | Read from the loaded model |
| Weight values on hover | Exact strided sample of the dequantized weights |
| Per-layer activity | mean|out − in| / mean|in| of each block at the token being generated; raw value on hover |
| Logit lens | The model's own final norm + output head applied to intermediate layers |
| Per-token confidence and alternatives | The probabilities mlx-lm already computes while generating (no extra pass) |
| Brightness of the links between layers | Geometric mean of the two layers' activity; which matrix each thin line joins is illustrative |
| ΔW, per-layer change | Computed from the adapter (scale · B·A) |
| Validation loss before → after | mlx-lm's evaluation before the first update and at the end |
| Discharge paths on the sphere, colours, glow | Stylized (their frequency follows GPU/memory load and layer activity) |
The window is split in two: chat on the right, and on the left the brain on top, with the layer window and the answer replay below it.
| View | What you see |
|---|---|
| Inference | One column per layer, four matrices per layer: attention Q, attention output, MLP gate, MLP down-projection; each cell is a real weight from that matrix (evenly spaced sample). While generating, a layer is brighter the more it changes the token's representation. The bundle of links between two neighbouring layers is lit by the geometric mean of the two, so it is thick and bright only when both layers are busy, and faint if either is quiet. Hover a cell for the real weight and the layer's raw measurement. |
| Train | The adapter's real ΔW (green = weight increased, orange-red = decreased); the bars below are the total change per layer, and you can pick any trained adapter to review. LoRA trains only the last 16 layers by default, so unchanged early layers are expected. |
| Weights | The static weights: orange = positive, cyan = negative, intensity = |w| ÷ the matrix's std (capped at 3σ). |
| Logit lens | A table: one column per generated token, one row per layer showing what that layer would output “if the model stopped here”; darker = more confident. A green underline means the layer already agrees with the final output; the “Settled” row says from which layer on. ◇ is a byte fragment of a multi-byte character. Choose which layers to show: all / second half / last 16 / a custom range and step. If the view was closed while the answer was generated, switching to it computes the lens for that answer afterwards. |
Collect as you go: every answer in the chat has “Save as training sample” and “Edit, then save…”. Save good answers as they are; fix the others into what you wanted first, and the model learns the fixed version.
Import data (samples saved from chat, .jsonl, notes, code, conversations.json exported from ChatGPT or Claude, Claude Code session .jsonl files, or have the model generate pairs from your files; sources can be combined into one dataset) → automatic checks (secrets removed, duplicates dropped, train/validation split) → pick a preset and train (live loss, speed, memory) → results: validation loss before → after, per-layer ΔW, side-by-side comparison with the base model → export as an MLX model or to Ollama.
http://127.0.0.1:8765/v1/chat/completions, OpenAI-compatible, so other tools can use the local model.I clicked a token in the replay. Why are the links between some layers thick and bright and others faint? The layer map is frozen at the moment that token was generated. Each layer's brightness is how much it changed the token's internal representation, compared both with that layer's typical level in this answer and with the other layers for this token. The bundle between two layers takes the geometric mean, so a bright stretch means several consecutive layers were heavily rewriting this token, and a faint stretch means those layers mostly passed it along. It is a real measurement, but not “importance”: changing a lot does not mean contributing a lot to the answer. The overall pattern also tends to look similar from token to token (overall activity varied only about ±10 % on real hardware); what really separates tokens is the confidence in the replay bars. Which of the 16 thin lines in a bundle joins which two matrices, and how the dots move, is illustrative; the measurement is per layer.
Why are the early layers in the logit lens mostly English or gibberish? Early layers are still working out what each token is and where it sits; reading a next-token prediction off them is not meaningful yet. Most training text is English, so the intermediate “drafts” often surface in English. Later layers get closer to the final output.
Why did training only change the later layers? LoRA attaches adapters to the last 16 layers by default and leaves the rest untouched, on purpose: less memory and less risk of breaking the model.
Can fine-tuning make the model remember facts? It is better at style and habits (format, tone, a fixed way of answering). For reliable answers about your documents, use the knowledge base.
One line, no clone needed:
uvx --from "neurolume[mlx] @ git+https://github.com/Yiteng-CHEN/neurolume" neurolume serve --open
Or from a checkout (double-click Neurolume.command, or):
git clone https://github.com/Yiteng-CHEN/neurolume.git && cd neurolume
uv run --extra mlx neurolume serve --open # http://127.0.0.1:8765
Need uv (brew install uv). In the browser: Models → Download (Devstral Small 2 4-bit ≈ 15 GB) → Load → chat; Train opens the wizard. Without a Mac you can still open src/neurolume/web/index.html to see the UI in demo mode.
Data lives in ~/Library/Application Support/Neurolume; models download into the checkout's models/ folder (or the data folder when installed with uvx).
| Qwen3.6-27B (8-bit) | Devstral Small 2 (4-bit) | |
|---|---|---|
| Layers | 64 = 16 × (3 linear + 1 full attention) | 40, all full attention |
| LoRA, longest sequence that fit | 1024 (2048 ran out of memory, peak 115 GB) | ≥ 2048 |
| LoRA seconds / step | 10.1 | 4.4 |
| LoRA peak memory | 62 GB | 18 GB |
src/neurolume/web/ UI: index.html, css/, js/ (plain scripts, no build step)
src/neurolume/server/ local server: chat, library, training, data generation, export, knowledge base, agent
src/neurolume/telemetry/ per-layer probe and logit lens on MLX transformer blocks
src/neurolume/backends/ MLX backend, mocks, OpenAI-compatible client
src/neurolume/evals/ eval tooling: mine tasks from git history, sandboxed grading
docs/ SIGNALS.md, decisions, plan
The server binds to 127.0.0.1 only. Neurolume never reads Claude / Codex / Hugging Face credentials.
Issues and pull requests are welcome — hardware reports (chip, memory, model, what worked) are especially valuable. See CONTRIBUTING.md. Tests: PYTHONPATH=src python -m unittest discover -s tests -t .
M-Courtyard and MLX-LoRA-Studio (no-code MLX fine-tuning); llm-viz and Transformer Explainer (how transformers work); TransformerLens and llm-transparency-tool (research interpretability). Neurolume's focus is the overlap: a live, local model you train and inspect at the same time.
MIT. Neurolume was previously called Cortex; old links redirect.