Claude Code keeps per-project memory at <home>/.claude/projects/<key>/,
where <key> is the project's absolute path with every separator and the
drive colon turned into a dash. That makes it both rename-fragile and
machine-specific, and this project has hit each of those once:
- D:\DEV\Schunix -> D:\DEV\SchOS changed the key, and 43 memories were
invisible until moved across by hand.
- Development happens from Windows and from Linux, and each looks in a
different place for the same checkout.
Committing .claude/memory/ fixes both -- git carries it across renames
and between hosts -- and `import` puts it wherever the local machine
expects. .claude/settings.local.json stays ignored: those are per-machine
permissions.
The colon maps to a dash rather than being dropped. Deleting it gives
D-DEV-SchOS, which matches nothing and silently finds zero memories; that
was the first attempt. On Git Bash the key comes from `cygpath -w`,
because Claude Code is a Windows program and sees D:\DEV\SchOS, not
/d/DEV/SchOS.
2.6 KiB
2.6 KiB
| name | description | metadata | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| schunix-build-speed | The build is fast now (no-op ~2s); the four things that made it slow and the traps that will make it slow again |
|
A no-op make went from 1m48s to ~2s on 2026-08-04, and a full kernel
rebuild from ~110s to ~7s. Almost none of it was compilation — with only 2.4s
of CPU in that 1m48, it was I/O across WSL's /mnt/d boundary. Four causes,
all still worth not reintroducing:
tools/mkfsbuilt the image on the file, onelseek+ one 512-bytewriteper block: 300,000 syscall pairs, 150,000 of them just to zero it. It now assembles the image in RAM and writes once. It also stops at the last non-zero block andftruncates, so ~2 MB is written instead of 147 MB.- The image was rebuilt on every invocation.
sysroot-installis phony, so everything depending on it always ran. There is now abuild/sysroot.stampwhose mtime only advances when afind-based summary of the staged tree actually changes (thecmp -s ... || mvidiom — do not add atouch, and notetouch -cstill updates an existing file's mtime, which is exactly the bug I wrote and had to remove). ports/toyboxre-linked its 236 applets every build, because port.mk declaresinstall.PHONY for every port. It hangs off$(BUILDDIR)/toybox.installednow. This was the sneaky one: it bumped the mtime of 236 files insysroot/and so invalidated the stamp above.- mkfs and mkschfs re-read every file to dedup it. They now check
(st_dev, st_ino)first — toybox's applets are real hard links, so 236 of them are settled by onefstatinstead of ~500 MB of reads.
Two real bugs found in the Makefile while doing this:
$(BUILD)/kernel/**/*.donly matched one directory level. make's wildcard has no recursive**.arch/x86_64/andfs/schfs/therefore had no header dependency tracking at all — editinginclude/schfs.hleft stale objects that linked fine. It uses$(shell find ...)now.CFLAGSis recursively expanded and had a$(shell)appended, so the stack-protector probe re-ran on every expansion: one extra gcc per object file. Probed once intoNO_SSP :=now.
schunix.img is no longer .PHONY (it is a real file), and MAKEFLAGS += -j$(nproc) is on by default — use make -j1 for readable output from a
failing build.
Verify with make schfs-check plus schunix-verify-by-driving-shell; the
superblock checksum is printed by mkfs and should not change when only build
mechanics change.