v0.6.1: install anywhere β Dockerfile, install matrix, #115/#116 patches#122
Conversation
EventLogTailer detected logrotate/copytruncate via inode change, then reopened the new file via _open_at_end() which seeks to EOF. Events written to the new file between rotation detection and the next poll were silently skipped β bursts during active rotation showed up truncated on the live activity feed. Split _open_at_end() / _open_at_start() and track whether the next reopen is the initial start (preserve no-history-replay semantics) or a post-rotation recovery (must catch any already-written lines). Codex review on PR #112: #112 (comment) https://claude.ai/code/session_01SH6iHNAqeMJHXdq7ubVcuJ
The existing /api/queries tests cover happy-path n=5, clamping at 0 and 99999, and the bad-input ValueError branch. They don't explicitly exercise the no-argument case where n must default to 20. Add a focused test so future query-string parsing changes can't drift the documented default. Copilot review on PR #105: #105 (comment) https://claude.ai/code/session_01SH6iHNAqeMJHXdq7ubVcuJ
Phase 1 of the "Install Anywhere" plan adds: - Multi-stage Dockerfile in repo root. Builder stage produces a wheel; runtime stage is a slim python:3.12-slim image with the package installed under a non-root user. Default command is `neuralmind --help`; documented patterns mount a host project read-only at /project and run either neuralmind-mcp or `neuralmind serve --host 0.0.0.0`. GHCR auto-publish is deferred to Phase 3 / v0.7.x; users build locally for now. - Eight new PyPI keywords matching v0.6.0 product copy: graph-view, code-graph, obsidian-style, synapse-layer, hebbian-learning, code-visualization, force-directed-graph, neuralmind-serve. The existing v0.5-era list missed every term we now lead with β discoverability bump for the v0.6.1 launch. https://claude.ai/code/session_01SH6iHNAqeMJHXdq7ubVcuJ
β¦118) - README Quick Start: replace the single `pip install` block with a five-row install matrix (pip / pipx / uv / Docker / source). Add a "Verify install" snippet that works for every path. - New docs/use-cases/install-paths.md walkthrough β each path with trade-offs (when pipx beats pip, when uv matters, what Docker costs you for persistence). - docs/wiki/Setup-Guide.md: insert the install matrix as the canonical landing for "how do I install this" before the existing 30-Second Setup section. - Add "Install methods" row to five comparison pages (vs Cursor, vs Copilot, vs Aider, vs Cody, vs Claude Projects) naming each competitor's install constraint alongside NeuralMind's five paths. https://claude.ai/code/session_01SH6iHNAqeMJHXdq7ubVcuJ
β¦M pack (#118) The first marketing moment of the post-v0.6.0 cycle β frame: "NeuralMind installs wherever you work." All drafts gated on maintainer approval before publication. - LINKEDIN-POST-DRAFT.md: new v0.6.1 launch drafts block above the v0.6.0 block. Two voices β feature-tour scannable (recommended) and short dev-honest. Same hashtag and tone discipline as v0.6.0. - SCREENCAST-v0.6.1.md: 60-second three-beat script β `pipx install` (beat 1), `docker run` (beat 2), both canvases pulsing side by side on the same node (beat 3, the money shot). Production notes match the v0.6.0 clip's conventions. - docs/notebooklm/v0.6.1/: three-document source pack for NotebookLM, same template as the v0.6.0 pack (origin-story / what-shipped / honest-take registers). https://claude.ai/code/session_01SH6iHNAqeMJHXdq7ubVcuJ
NeuralMind self-benchmarkStatus: Phase 1 β Reduction on committed fixture
Phase 2 β Learning uplift
Note: uplift numbers on a 500-line fixture are intentionally modest β the point is to Assumptions
Per-model token reduction
Rows marked measured use the provider's real tokenizer. Rows marked Automated by |
There was a problem hiding this comment.
Pull request overview
Phase 1 of the v0.6.1 "Install Anywhere" plan: ships a multi-stage Dockerfile, expands the install matrix to five paths across README/wiki/comparisons, bumps PyPI keywords, and lands two deferred review-feedback patches (a rotation race fix in the event-log tailer and a no-arg test for /api/queries). The bulk of the diff is documentation and marketing collateral.
Changes:
- Code:
EventLogTailernow reopens at offset 0 after rotation detection (#115); new server test locks in the/api/queriesdefault-n=20 path (#116). - Packaging: new repo-root
Dockerfile(multi-stage, non-root runtime) and 8 new PyPI keywords. - Docs/marketing: install matrix in README + wiki, new
docs/use-cases/install-paths.md, "Install methods" rows in 5 comparison pages, LinkedIn drafts, 60s screencast script, NotebookLM v0.6.1 pack.
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| neuralmind/event_log.py | Splits _open_at_end/_open_at_start; reopens after rotation at offset 0 to avoid event loss. |
| tests/test_event_log.py | New regression test for the rotation-race fix. |
| tests/test_server.py | New test asserting /api/queries defaults n to 20 when omitted. |
| Dockerfile | New multi-stage image: builder produces wheel, slim runtime, non-root user. |
| pyproject.toml | Adds 8 PyPI keywords for v0.6.0 product copy. |
| README.md | New five-path install matrix + verify snippet under Quick Start. |
| docs/wiki/Setup-Guide.md | Install matrix added as canonical landing; 30-second setup reordered. |
| docs/use-cases/install-paths.md | New walkthrough page with pros/cons of each install path. |
| docs/comparisons/vs-*.md | Adds an "Install methods" row to each of the 5 comparison pages. |
| docs/SCREENCAST-v0.6.1.md | New 60-second screencast script. |
| docs/notebooklm/v0.6.1/*.md | New 3-doc NotebookLM source pack. |
| docs/LINKEDIN-POST-DRAFT.md | Adds v0.6.1 launch drafts (feature-tour + dev-honest). |
Comments suppressed due to low confidence (1)
neuralmind/event_log.py:170
- The OSError branch (when
path.stat()fails because the file briefly doesn't exist) closesfhbut does not setreopen_at_start = True. If the tailer's poll fires in the gap betweenos.rename(events.jsonl, events.jsonl.1)and the creation/first write of the newevents.jsonl, this branch runs instead of the inode-change branch. The next iteration will then call_open_at_end()on the freshly-created file and skip exactly the prewritten lines this PR is intended to preserve. Settingreopen_at_start = Truehere as well (or infinallyafter any close that wasn't a clean stop) would close that race. The new regression test happens to land on the inode-change branch (because it writes before the next poll), so it doesn't currently exercise this window.
except OSError:
fh.close()
fh = None
continue
π‘ Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| | **pip** | `pip install neuralmind graphifyy` | Default. Drops it in your active env. | | ||
| | **pipx** | `pipx install neuralmind && pipx inject neuralmind graphifyy` | Global CLI, no env pollution. Recommended if you want `neuralmind` available everywhere. | | ||
| | **uv** | `uv pip install neuralmind graphifyy` | Modern, fast Python tooling. ~10Γ faster install than pip. | | ||
| | **Docker** | `docker run --rm -v "$PWD:/project:ro" ghcr.io/dfrostar/neuralmind neuralmind --help` | Containerized β no Python on the host. Image built from the `Dockerfile` in this repo; auto-published to GHCR in a later release. | |
| | **pip** | `pip install neuralmind graphifyy` | Default. Drops it in your active env. | | ||
| | **pipx** | `pipx install neuralmind && pipx inject neuralmind graphifyy` | Global CLI, no env pollution. | | ||
| | **uv** | `uv pip install neuralmind graphifyy` | Modern, fast Python tooling. | | ||
| | **Docker** | `docker run --rm -v "$PWD:/project:ro" ghcr.io/dfrostar/neuralmind neuralmind --help` | Containerized β no Python on the host. | |
| COPY --from=builder /wheels /wheels | ||
|
|
||
| RUN pip install --no-cache-dir /wheels/*.whl \ | ||
| && rm -rf /wheels |
|
|
||
| COPY --from=builder /wheels /wheels | ||
|
|
||
| RUN pip install --no-cache-dir /wheels/*.whl \ |
| # Install (includes the CLI, semantic indexing, and the MCP server | ||
| # for Claude Code, Cursor, Cline, Continue, and any MCP client) | ||
| # Use whichever install method above | ||
| pip install neuralmind graphifyy |
| **Verify install** (works for every path): | ||
|
|
||
| ```bash | ||
| python -c "import neuralmind; print(neuralmind.__version__)" |
There was a problem hiding this comment.
π‘ Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7cba04a77d
βΉοΈ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with π.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| fh, state = self._open_at_start() if reopen_at_start else self._open_at_end() | ||
| reopen_at_start = False | ||
| if fh is None: |
There was a problem hiding this comment.
Preserve reopen-at-start mode across failed reopen attempts
After rotation is detected, reopen_at_start is set to True, but it is immediately reset to False even when _open_at_start() fails (for example, during the common rename-then-create gap where events.jsonl is temporarily missing). On the next successful open, the tailer falls back to _open_at_end(), which skips lines already written to the new file and reintroduces silent event loss. The flag should only be cleared after a successful reopen so the post-rotation file is always reopened from offset 0.
Useful? React with πΒ / π.
Codex P1 review on #122: after rotation, ``reopen_at_start = True`` was cleared unconditionally on every reopen attempt. If the first attempt failed (commonly the rename-then-create gap where the new file briefly doesn't exist), the next successful reopen fell back to ``_open_at_end()`` β silently dropping any lines already in the new file. Same root cause applied to the ``except OSError`` branch in the rotation-detection block, which didn't set the flag at all. Two changes: - Move ``reopen_at_start = False`` past the open-failed early return so it only clears after a successful open. - Set ``reopen_at_start = True`` in the OSError branch (file vanished = same recovery semantics as inode-change). New regression test reproduces both windows: rename without a new file, sleep through one poll interval (first reopen fails), then create the new file with pre-existing lines and assert all are delivered. Review: #122 (comment) https://claude.ai/code/session_01SH6iHNAqeMJHXdq7ubVcuJ
Two issues from Copilot's review on #122: - ``graphifyy`` wasn't in the image, so ``neuralmind build`` inside the container would fail with "graphify command not found". The install-paths docs assume it's present. - The runtime stage ran ``pip install /wheels/*.whl``, which reaches out to PyPI for transitive deps. If any transitive dep resolves to an sdist on python:3.12-slim (e.g., a transient lack of a manylinux wheel), the runtime image has no C toolchain to build it and the build fails. Fix: pre-download every transitive wheel (including graphifyy) in the builder stage via ``pip wheel``. Runtime stage installs from /wheels with ``--no-index --find-links`` so PyPI is never touched at runtime build time. Review: - #122 (comment) - #122 (comment) https://claude.ai/code/session_01SH6iHNAqeMJHXdq7ubVcuJ
β¦ippet Copilot review on #122, four related consistency issues: - README + Setup-Guide install matrices showed ``ghcr.io/dfrostar/neuralmind`` as the primary Docker command. The image isn't published yet (auto-publish lands in Phase 3 / v0.7.x). Lead with ``docker build -t neuralmind:dev .`` so the command works verbatim today; keep the GHCR URL inline with a bold "build locally for now" so the future state is visible without being a trap. - README "Index a project" snippet hard-coded ``pip install neuralmind graphifyy`` immediately after the matrix's "Use whichever install method above" comment, contradicting it. Replaced with a placeholder comment. - README verify snippet labeled ``python -c "import neuralmind"`` as "works for every path" β false for pipx (isolated venv) and Docker (no host Python). Split: ``neuralmind --help`` works everywhere; the import line is now scoped to pip/uv/source with an inline note. Reviews: - #122 (comment) - #122 (comment) - #122 (comment) - #122 (comment) https://claude.ai/code/session_01SH6iHNAqeMJHXdq7ubVcuJ
β¦DMAP The v0.6.1 install matrix had landed in the README Quick Start, the install-paths walkthrough, the Setup-Guide, and five comparison pages β but several surfaces still framed v0.6.0 as "current" and reflected the pre-matrix single-pip install story. Consistency pass across every public-facing surface: - README.md: add v0.6.1 callout above v0.6.0 in the hero; add release notes link in the Resources table. - RELEASE_NOTES_v0.6.1.md (new): full release notes matching v0.6.0 structure β TL;DR, what's new (install matrix, Dockerfile, keywords, #115, #116), env vars, per-path verification snippet, what's next. - docs/wiki/Home.md: add v0.6.1 "What's New" entry above v0.6.0; refresh the Installation reference-table line. - docs/wiki/Installation.md: add the five-path install matrix at the top as the new canonical landing; add pipx / uv / Docker method sections to "Installation Methods"; replace the stale embedded Dockerfile example with a pointer to the repo-root Dockerfile; scope the verify snippet so the python -c line is documented as pip/uv/source-only. - docs/index.html: hero callout leads with v0.6.1 install matrix; v0.6.0 moves to the "Earlier" line. - docs/about.html: new "What's New in v0.6.1 β install anywhere" section above the existing v0.6.0 walkthrough. - ROADMAP.md: "Shipped in v0.6.1" section; reframe "Now (v0.7)" as the Always-On release per the handoff doc + #119; add "Then (v0.7.x) β Enterprise-Ready" section per #120; carry the prior v0.7 graph-view items into a "Graph-view backlog" section. No code changes; no tests changed; full suite still 388 passing. https://claude.ai/code/session_01SH6iHNAqeMJHXdq7ubVcuJ
β¦raft Audit of upstream agent hubs (2026-05-16): only Agent Zero publishes a public plugin registry (agent0ai/a0-plugins, in-app one-click install). OpenClaw and Hermes-Agent are config-only β already covered by the existing README integration blocks. This commit lands the Agent Zero pieces: - Agent Zero integration section in the README, matching the Hermes-Agent / OpenClaw block shape. Walks through the Web UI JSON registration path (A0 has no `mcp add` CLI; registration is the standard MCP `command`/`args`/`env` JSON pasted into Settings β MCP/A2A β External MCP Servers). Cross-links the upstream MCP setup guide and the shared synapse-store / multi-agent walkthrough. - Repo-root plugin.yaml refresh β the orphaned 0.3.3-era "neuralmind-local" manifest is replaced with the schema a0-plugins' validator requires (lowercase-underscores name matching the submission folder). Adds title, description, license, tags for any other tool that reads plugin.yaml. - Draft submission at docs/integration-submissions/agent-zero/index.yaml β kept in this repo as the canonical source. Comment header documents the a0-plugins schema constraints (50/500/2000-char caps, image size limits, one-plugin-per-PR rule). Strip the header when submitting to the a0-plugins fork. - ROADMAP: new "Ecosystem β hub & registry listings" section documenting the audit result and the A0 submission status; richer A0 plugin (UI surface, settings panel, embedded graph viewer) flagged as a follow-up if the MCP listing draws users. No code changes. Tests unchanged. The actual cross-repo PR to agent0ai/a0-plugins is deferred until maintainer go-ahead. https://claude.ai/code/session_01SH6iHNAqeMJHXdq7ubVcuJ
Summary
Phase 1 of the v0.6.1 "Install Anywhere" plan (#118) plus the two deferred review-feedback patches the v0.6.0 merge train left for v0.6.1 (#115, #116). See
docs/HANDOFF-v0.6.1.mdfor full context.Five logical commits:
fix(event_log): reopen rotated logs from offset 0 (#115)β split_open_at_end/_open_at_start, track which one the next reopen needs. Initial open still seeks to EOF (no history replay); post-rotation reopen seeks to offset 0 so already-written lines aren't dropped. New regression test simulates the race by writing 3 lines to the post-rotation file before the tailer detects the inode change.test(server): add /api/queries no-arg default-n test (#116)β the existing tests cover happy-path / clamping / bad-input but not the explicitGET /api/queries(non) β default 20 case. One focused test locks in the documented default.feat(install): add Dockerfile and PyPI keywords for v0.6.1 (#118)β multi-stageDockerfilein repo root (builderproduces the wheel,runtimeis slim + non-root). 8 new PyPI keywords matching v0.6.0 product copy (graph-view,hebbian-learning,force-directed-graph, β¦).docs(install): five-path install matrix in README, wiki, comparisons (#118)β README Quick Start matrix (pip/pipx/uv/ Docker / source) + Verify snippet. Newdocs/use-cases/install-paths.mdwalkthrough. Setup-Guide.md install matrix as canonical landing. "Install methods" row added to 5 comparison pages.docs(marketing): v0.6.1 LinkedIn drafts, screencast script, NotebookLM pack (#118)β 2 LinkedIn drafts (feature-tour + dev-honest), 60-sec screencast script (pipx installβdocker runβ both canvases pulsing), 3-doc NotebookLM source pack atdocs/notebooklm/v0.6.1/. All marketing drafts gated on maintainer approval before publication.Test plan
python -m pytest tests/β 388 passed, 4 environmental skips (none touched by these changes)ruff checkclean on changed filesblack --checkclean on changed filestest_tailer_recovers_from_rotation_without_dropping_prewritten_lineswould fail with the pre-fix code (lines pre-written to the new file before the tailer's next poll are skipped under_open_at_end) and passes after the fixtest_api_queries_defaults_n_to_20_when_omittedexercises the previously-untested code pathdocker build -t neuralmind:dev .succeeds (Docker daemon wasn't available in the dev environment for this session)Out of scope
/healthz, systemd/launchd, Aider β separate releaseCloses
https://claude.ai/code/session_01SH6iHNAqeMJHXdq7ubVcuJ
Generated by Claude Code