Repository navigation
Conversation
…n registry - Modules shipped inside the root repo (gtd, research, outbox, ...) are core: update reports them as such instead of 'Not a git repository' and no longer counts them as failed; snapshot records them as source 'core' and restore/diff skip them. - snapshot restore puts modules and spaces ON their branch at the snapshot commit (switch -C, upstream set) instead of a detached HEAD. - update moves an already-detached module back to its default branch before pulling, and refuses without changing anything if commits would be left behind. - update makes sure the transport registry names the root repo (<root>), creating a minimal repositories.yaml on a machine that has none and saying so plainly; passes --root to the transport. - snapshot create records the root repo's source; --with-registry carries the private registry files, written on restore only where absent. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tor on Linux - checkVenvSupport builds a throwaway venv before init relies on one and names the exact fix (sudo apt install python3.X-venv on Debian/Ubuntu); the venv failure message in update carries the same hint. - ensureModuleDeps installs with npm ci from the tracked lock file, puts the lock back byte for byte, and skips the install when nothing changed, so update no longer leaves the root repo dirty. - doctor skips the Claude Desktop check where there is no Claude Desktop (Linux, or app not installed), reads .mcp.json from the data dir, prints the ledger rows, and only says 'Missing recommended dependencies' when one is missing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- datacore init --from-snapshot <file> clones the root from the snapshot's source, restores its spaces and modules before anything else, installs the modules' dependencies, and never creates a template space the snapshot provides (a failed clone is an error, not a template). - Interactive init asks once whether Datacore already runs on another machine and explains snapshot create --settings there and --from-snapshot here. - space --help lists join and audit (both existed, neither was listed) and points to the snapshot route for a whole machine; init and snapshot help describe the new flags. - Fixes a pre-existing typecheck error in ensureRecallHook. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Setting up Datacore on a second machine from a snapshot, fixed so it works without hand repairs. Every item below comes from a real headless Ubuntu 24.04 second-machine install made from a snapshot of an existing installation. The install worked in the end, but only after moving files by hand, and the first
datacore updatereported "37 module(s) failed" when nothing was broken.Fixes
1. Core modules are not failures. Modules that ship inside the root Datacore repo (gtd, research, outbox, goals, decisions, github, analytics, tab-capture, voice-terminal, whatsapp) have no
.gitof their own.datacore updatereported each one as "Not a git repository" and counted it as failed. A newmoduleKind()tells them apart: the module has its own clone, the root repo tracks it (core), or neither (local).updatenow reports core modules as "part of Datacore, updated with it".snapshot createrecords them assource: core, and restore and diff skip them. They used to be written aslocal, so restore warned that it "cannot restore" them.2. Root repo "not in registry". On a new machine
.datacore/registry/repositories.yamldoes not exist: it is private and gitignored, and the snapshot did not carry it. The sync transport then refused the root repo.updatenow makes sure the registry names the root under<root>. When there is no registry file it creates a minimal one and says so in one plain sentence (copy the full file from your other machine, or use--with-registry). When the file lacks the entry it adds it and keeps comments. It never touches a file it cannot parse. The transport now also gets an explicit--root. New:snapshot create --with-registrycarries the private registry files (repositories, infrastructure, principals). The snapshot is then written owner-only. Restore writes those files only where none exist.3. Restore left modules and spaces detached. Restore checked out exact commits, so on the real install 27 modules and 7 of 10 spaces were on a detached HEAD, and every
git pullfailed. Restore now runsgit switch -C <branch> <commit>with the upstream set, so each repo is on its branch at the snapshot commit.updatealso repairs a module that is already detached: it switches it back to its default branch before pulling. If HEAD has commits on no branch, it changes nothing and gives the command to keep them. Clone URLs from a lock file now go through execFile, not a shell string.4. init checks
python3 -m venvfirst. On Debian and Ubuntu, venv needspython3.X-venv. Without it the MCP server could not start, and init only found out after setup.checkVenvSupport()builds a throwaway venv with pip during the system-setup step and prints the exact command (sudo apt install python3.12-venv). In an interactive run it waits for you to install it and checks again. The venv error fromupdatenow carries the same hint.5.
datacore init --from-snapshot <file>. This clones the root from the snapshot's recorded source. Then, before any space or module step, it restores the snapshot's spaces and modules, on their branches. It installs the restored modules' own dependencies after the venv exists. It never creates a template space the snapshot provides: if that space's clone failed, init reports an error and creates no template. Interactive init now asks once, before anything is installed, whether Datacore already runs on another machine. If so, it explainsdatacore snapshot create --settingsthere and--from-snapshothere.snapshot restorealso warns when a non-git directory blocks a space, which is the template collision that hit the real install.6.
space --help. It said "Create, join, list and audit" but listed only create and list.joinandauditboth had handlers but were missing from the action list. Both are listed now, and the help points to the snapshot route for setting up a whole machine.Also, from the same install:
datacore updatedirtied the root repo on every run. It rewrote the tracked.datacore/modules/package-lock.json. It now installs withnpm cifrom the lock file, puts the lock file back byte for byte, and skips the install when nothing has changed.doctoron a headless server. It showed "✗ Claude Desktop config" on Linux, where there is no Claude Desktop, and ended with "Missing recommended dependencies" while every dependency was present: every status that was not ready got that message, including a degraded ledger. The Claude Desktop row now appears only where the app is installed, and.mcp.jsonis read from the data dir. The ledger rows are printed, and the closing line matches the real status.ensureRecallHook, which blockednpm run verify.Tests (written first, seen failing, then the code)
tests/second-machine.test.ts(21 tests, real git repos): core module detection, update, snapshot and diff; restore on-branch for modules and spaces; update pulls a restored module forward; detached repair, and refusal when commits would be lost; registry created, added, left alone, and not parsed;--rootpassed; private registry carried only on request and written only where absent; template-collision warning.tests/second-machine-setup.test.ts(18 tests): venv check and install hints;personalSpacePlannever chooses the template when the snapshot provides the space; root clone URL order; an unreadable snapshot refused before anything changes;--from-snapshotparsing; second-machine help text; doctor on Linux and on a Mac with and without the app; doctor verdicts; space actions and help.tests/python-env.test.ts(+3):npm ciwith a lock file, lock file stays byte-identical, no reinstall when nothing changed.Results:
bun test197 pass, 0 fail (155 before).tsc --noEmitclean.scripts/prepublish-verify.shpasses (types, tests, build, dist version, doctor from dist, no--rebase).Smoke test, not part of the suite: in an isolated HOME with local bare repos for the root, a personal space and one module,
init --from-snapshotcloned the root from the snapshot source and addedupstream. It restored the real personal space (no template) and the module, both onmainat the snapshot commits, tracking origin. Thenupdatemoved a detached module back tomainand pulled it to the tip.Not covered: no second run on a real Ubuntu machine yet. The interactive question and the venv re-check prompt are covered by code review only.
--settingsis still carried in the snapshot but not applied by restore, as before.Releasing (the owner's step, not done here)
Nothing was published. A release needs:
package.json(suggest 2.7.0: new flagsinit --from-snapshotandsnapshot create --with-registry).npm run verify.npm publish.Snapshots made by older CLIs still restore. Their core modules were recorded as
localand are skipped because they already arrive with the root.🤖 Generated with Claude Code