Skip to content

Add implementation plans for profiles, custom images, and overlay disks#2

Merged
agarcher merged 1 commit intomainfrom
setup
Apr 10, 2026
Merged

Add implementation plans for profiles, custom images, and overlay disks#2
agarcher merged 1 commit intomainfrom
setup

Conversation

@agarcher
Copy link
Copy Markdown
Owner

@agarcher agarcher commented Apr 10, 2026

Summary

Adds a plans/ directory with three design documents capturing the path to fast, customizable pen shell startup:

  • plans/profiles-and-overlay.md — ready-to-implement plan for a two-layer persistence model: immutable profile-built images (bake in stable tools like claude, node, git) + per-VM overlay disks via overlayfs (persist runtime apk add, node_modules, project state). Includes a profile TOML schema, CLI surface, guest init changes (overlayfs + pivot_root + first-boot hook), a builder-VM pipeline for custom images, and a four-phase implementation order.
  • plans/future-vm-snapshots.md — high-level sketch of snapshot/restore as a future startup optimization. Flags the hard problems (stale state, env re-injection, snapshot portability, overlay consistency) and alternatives (backgrounded VMs, kexec).
  • plans/future-squashfs-sidecar.md — high-level sketch of a read-only squashfs sidecar for when initrd bloat eventually becomes an issue from baking heavy content (JDK, model weights, CUDA).

The main plan locks in two design decisions from prior discussion: profile setup script changes are not re-run against existing VMs (Option 1), and the first-boot-complete marker lives at /var/lib/pen/setup-done inside the merged rootfs view (chosen over a raw-disk path to keep the pivot_root sequence clean).

No code changes — planning only. Implementation lands in follow-up PRs per phase.

Test plan

  • Plans render correctly on GitHub
  • No code changes to verify

Summary by CodeRabbit

  • Documentation
    • Added planning documentation for a read-only squashfs sidecar optimization to reduce RAM usage for large profile scenarios and improve performance.
    • Added planning documentation for VM snapshots enabling sub-second shell startup times after the initial boot process.
    • Added specification for the profiles feature, combining custom images, persistent overlay disks, and first-boot setup hooks for better customization.

Introduces a plans/ directory with three design documents: a ready-to-implement
plan for the two-layer persistence model (immutable profile images plus per-VM
overlay disks, with a first-boot setup hook), and two high-level sketches for
future optimizations (VM snapshots and a read-only squashfs sidecar) to revisit
only if and when their motivating problems materialize.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 10, 2026

📝 Walkthrough

Walkthrough

Three new planning documents outline proposed future features: read-only squashfs sidecar optimization, VM snapshot restoration for sub-second startup, and a profiles-and-overlay system combining custom initrd images, persistent overlay disks, and first-boot setup hooks.

Changes

Cohort / File(s) Summary
Planning & Design Documents
plans/future-squashfs-sidecar.md, plans/future-vm-snapshots.md, plans/profiles-and-overlay.md
New planning documents describing three proposed features: read-only squashfs sidecar for memory-efficient VM content delivery, VM snapshot restoration for near-instant startup after first run, and a comprehensive profiles-with-overlay system combining custom initrd images, persistent per-VM overlay disks, and first-boot setup hooks with detailed CLI, filesystem layout, guest init flow, and phased implementation strategy.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~8 minutes

Poem

🐰 hippity-hops with glee
Future plans are sketched with care,
Squashfs sidecars and snapshots fair,
Profiles dancing through the air!
With overlays and setup hooks so bright,
The pen tools leap toward tomorrow's light! 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and comprehensively summarizes the main changeset: adding three implementation plan documents covering profiles, custom images, and overlay disks.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch setup

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
plans/future-squashfs-sidecar.md (1)

20-22: Optional wording cleanup for readability.

Lines 20–22 start successive bullets with “When…”. Consider varying one opener to reduce repetition.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plans/future-squashfs-sidecar.md` around lines 20 - 22, The three consecutive
bullets in plans/future-squashfs-sidecar.md all start with "When…", which is
repetitive; edit one bullet (e.g., the second bullet that begins "When a natural
use case (ML tooling, JDK-based agents) appears…") to vary the opener — for
example change "When" to "If" or rephrase to "A natural use case is…" — keeping
the meaning intact and preserving the emphasis that mutable state belongs on the
per-VM overlay disk in the third bullet.
plans/profiles-and-overlay.md (1)

89-93: Cache key inputs should include builder pipeline/version identity.

Current hash inputs (Line 90) omit builder logic/toolchain identity. If packing behavior changes, stale build.hash may incorrectly hit cache. Add builder version/salt to the cache key definition.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plans/profiles-and-overlay.md` around lines 89 - 93, Update the image cache
key definition to include the builder pipeline/toolchain identity (a builder
version or salt) in addition to the existing inputs; specifically, change the
"Image cache key = sha256 of `packages` + `build` + base kernel/initrd version"
to include a builder identifier (e.g., `builder_version` or `builder_salt`), and
ensure this combined value is what is written to and compared in
`images/profiles/<name>/build.hash` so that changes in packing logic/toolchain
invalidate the cache and trigger rebuilds on the next `pen shell --profile`.
plans/future-vm-snapshots.md (1)

21-30: Define a concrete snapshot metadata manifest now (even if feature is deferred).

Lines 21–30 list invalidation rules, but without a manifest contract (e.g., snapshot.json fields), implementation can drift. Add a minimal schema for keys like image hash, overlay fingerprint, env hash, host/vz version, and created-at.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plans/future-vm-snapshots.md` around lines 21 - 30, Add a concrete snapshot
metadata manifest contract (e.g., snapshot.json) that lists minimal required
fields and semantics: include imageHash (guest image content hash),
overlayFingerprint (overlay disk hash or mtime+size), envHash (hash of injected
environment vars), hostVzVersion (host OS + vz library version and CPU
generation tag), createdAt (ISO timestamp) and an optional invalidateReasons
array; document expected formats and when each field must be checked (restore
validation uses imageHash, overlayFingerprint, envHash, hostVzVersion) and when
to bump invalidateReasons. Ensure names match this manifest (snapshot.json
imageHash, overlayFingerprint, envHash, hostVzVersion, createdAt) so code like
snapshot creation, restore validation, and invalidation logic can reliably
read/write the same keys.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plans/profiles-and-overlay.md`:
- Around line 42-59: The markdown has bare triple-backtick fences in
plans/profiles-and-overlay.md around the filesystem tree starting with
"~/.config/pen/" and the numbered init sequence starting "1. Mount proc, sys,
dev, tmp, run, devpts"; update those fences to include language identifiers (use
```text for the filesystem tree block and ```sh or ```text for the init sequence
block as appropriate) so the fenced code blocks satisfy markdownlint MD040 and
avoid lint failures.

---

Nitpick comments:
In `@plans/future-squashfs-sidecar.md`:
- Around line 20-22: The three consecutive bullets in
plans/future-squashfs-sidecar.md all start with "When…", which is repetitive;
edit one bullet (e.g., the second bullet that begins "When a natural use case
(ML tooling, JDK-based agents) appears…") to vary the opener — for example
change "When" to "If" or rephrase to "A natural use case is…" — keeping the
meaning intact and preserving the emphasis that mutable state belongs on the
per-VM overlay disk in the third bullet.

In `@plans/future-vm-snapshots.md`:
- Around line 21-30: Add a concrete snapshot metadata manifest contract (e.g.,
snapshot.json) that lists minimal required fields and semantics: include
imageHash (guest image content hash), overlayFingerprint (overlay disk hash or
mtime+size), envHash (hash of injected environment vars), hostVzVersion (host OS
+ vz library version and CPU generation tag), createdAt (ISO timestamp) and an
optional invalidateReasons array; document expected formats and when each field
must be checked (restore validation uses imageHash, overlayFingerprint, envHash,
hostVzVersion) and when to bump invalidateReasons. Ensure names match this
manifest (snapshot.json imageHash, overlayFingerprint, envHash, hostVzVersion,
createdAt) so code like snapshot creation, restore validation, and invalidation
logic can reliably read/write the same keys.

In `@plans/profiles-and-overlay.md`:
- Around line 89-93: Update the image cache key definition to include the
builder pipeline/toolchain identity (a builder version or salt) in addition to
the existing inputs; specifically, change the "Image cache key = sha256 of
`packages` + `build` + base kernel/initrd version" to include a builder
identifier (e.g., `builder_version` or `builder_salt`), and ensure this combined
value is what is written to and compared in `images/profiles/<name>/build.hash`
so that changes in packing logic/toolchain invalidate the cache and trigger
rebuilds on the next `pen shell --profile`.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a2969ebf-79b5-422e-8236-45a87669b3b6

📥 Commits

Reviewing files that changed from the base of the PR and between 34f4f58 and cd9f679.

📒 Files selected for processing (3)
  • plans/future-squashfs-sidecar.md
  • plans/future-vm-snapshots.md
  • plans/profiles-and-overlay.md

Comment on lines +42 to +59
```
~/.config/pen/
├── images/
│ ├── vmlinuz # base kernel (unchanged location)
│ ├── initrd # base initrd (unchanged location)
│ └── profiles/
│ └── <profile-name>/
│ ├── initrd # custom initrd built from profile
│ └── build.hash # sha256 of image-affecting profile fields
├── profiles/
│ └── <profile-name>.toml # user-authored profile config
└── vms/
└── <vm-name>/
├── vm.json # existing
├── pen.lock # existing
├── pid # existing
└── overlay.img # new: ext4 sparse file, per-VM persistent disk
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add language identifiers to fenced code blocks to satisfy markdownlint (MD040).

Line 42 and Line 116 use bare triple-backtick fences. Add explicit languages (text, sh) to avoid lint noise/failures.

Proposed doc-only lint fix
-```
+```text
 ~/.config/pen/
 ├── images/
 ...
-```
+```

-```
+```text
 1. Mount proc, sys, dev, tmp, run, devpts                    (unchanged)
 ...
 9. exec /bin/sh -l                                           (unchanged)
-```
+```

Also applies to: 116-142

🧰 Tools
🪛 markdownlint-cli2 (0.22.0)

[warning] 42-42: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plans/profiles-and-overlay.md` around lines 42 - 59, The markdown has bare
triple-backtick fences in plans/profiles-and-overlay.md around the filesystem
tree starting with "~/.config/pen/" and the numbered init sequence starting "1.
Mount proc, sys, dev, tmp, run, devpts"; update those fences to include language
identifiers (use ```text for the filesystem tree block and ```sh or ```text for
the init sequence block as appropriate) so the fenced code blocks satisfy
markdownlint MD040 and avoid lint failures.

@agarcher agarcher merged commit 532ae84 into main Apr 10, 2026
2 checks passed
agarcher added a commit that referenced this pull request Apr 11, 2026
- plans/profiles-and-overlay.md: top-level status now "Phase 1
  complete". Phase 1 section annotated DONE with commit hashes and a
  pointer to TestOverlayPersistence. Open question #2 (disk-not-clean
  recovery) resolved — ext4 journal replay was observed working during
  smoke testing, no explicit e2fsck needed.

- CLAUDE.md: add a terse "Testing" section stating that
  `make test-integration` must be run before marking any task
  complete, since CI cannot run it. Kept to two sentences; details
  live in ARCHITECTURE.md.

- docs/ARCHITECTURE.md: note in the CI/CD section that
  test-integration is deliberately not wired into CI because
  GitHub's hosted macOS runners are themselves Anka VMs and Apple VZ
  refuses nested virt (actions/runner-images#13505, closed "not
  planned"). Integration tests are local-only.

- .gitignore: ignore .claude/settings.local.json (Claude Code harness
  state).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@agarcher agarcher deleted the setup branch April 12, 2026 18:32
@coderabbitai coderabbitai Bot mentioned this pull request Apr 12, 2026
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant