Files
darkforge/CLAUDE.md
Danny 029642ae5b Initial commit: DarkForge Linux — Phases 0-12
Complete from-scratch Linux distribution targeting AMD Ryzen 9 9950X3D +
NVIDIA RTX 5090 on ASUS ROG CROSSHAIR X870E HERO.

Deliverables:
- dpack: custom package manager in Rust (3,800 lines)
  - TOML package parser, dependency resolver, build sandbox
  - CRUX Pkgfile and Gentoo ebuild converters
  - Shared library conflict detection
- 124 package definitions across 4 repos (core/extra/desktop/gaming)
- 34 toolchain bootstrap scripts (LFS 13.0 adapted for Zen 5)
- Linux 6.19.8 kernel config (hardware-specific, fully commented)
- SysVinit init system with rc.d service scripts
- Live ISO builder (UEFI-only, squashfs+xorriso)
- Interactive installer (GPT partitioning, EFISTUB boot)
- Integration test checklist (docs/TESTING.md)

No systemd. No bootloader. No display manager.
Kernel boots via EFISTUB → auto-login → dwl Wayland compositor.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 11:30:40 +01:00

35 KiB
Raw Blame History

CLAUDE.md — Project Directive for DarkForge Linux

This file is the single source of truth for all AI-assisted work on this project. Every session must begin by reading this file in full. No exceptions.


Table of Contents

  1. Identity & Philosophy
  2. Ground Rules — Non-Negotiable
  3. Project Overview
  4. Hardware Target
  5. Architecture Decisions
  6. Project Structure
  7. Phase Breakdown & Execution Order
  8. dpack — The Package Manager
  9. Kernel Configuration
  10. Init System
  11. ISO & Installer
  12. Target Package List
  13. Reference Material
  14. Changelog Protocol
  15. Session Protocol
  16. Known Pitfalls & Guardrails

Identity & Philosophy

Project codename: DarkForge Linux Purpose: A custom, from-scratch Linux distribution built for one machine, one user, optimized ruthlessly for gaming and development. This is an internal-use tool — not a production distribution. Security theater (package signing, encrypted disk, etc.) is explicitly deprioritized. Raw performance and correctness are the goals.

Philosophy: Do not guess. Do not assume. If anything is ambiguous, stop and ask. Precision over speed. Every decision must be justifiable.


Ground Rules — Non-Negotiable

These rules apply to every single session, every single change, no matter how small.

1. Never Guess

If a requirement, version number, configuration flag, dependency, or design decision is unclear within this document or the codebase, stop and ask the user. After receiving clarification, update the relevant section of this document or the appropriate project docs so the ambiguity never recurs.

2. Changelog Is Mandatory

Every change to code, scripts, configs, or documentation must be logged in docs/CHANGELOG.md before the session ends. The format is strict and defined in the Changelog Protocol section below. No change is considered complete until the changelog entry exists.

3. Latest Versions Always

LFS, BLFS, CRUX, and Gentoo reference material often pins older package versions. Always research and use the latest stable release of every package, library, and toolchain component unless there is a documented, specific incompatibility. When a version is chosen, record it explicitly in the relevant package definition or build script with a comment explaining why that version was selected.

4. One Thing at a Time

This project has many interconnected subsystems. Work on them in the order defined by the Phase Breakdown. Do not jump ahead. Do not start Phase N+1 until Phase N is complete or explicitly paused by the user.

5. Atomic, Testable Changes

Every change should be small enough to reason about in isolation. If a change touches more than one subsystem, split it. Every script and build step should be independently testable where possible.

6. Comments and Documentation

All shell scripts must have a header comment block explaining purpose, inputs, outputs, and assumptions. All Rust code must have doc comments on public items. All kernel config choices must have inline comments explaining why they were set.

7. File Placement

Never create files outside the defined Project Structure without explicitly discussing it first. Temporary or scratch files go in /tmp or a clearly marked build/ directory and must be cleaned up.

8. No Systemd — Anywhere

This is a hard constraint. No systemd, no logind, no systemd-boot, no udev (use eudev instead), no anything from the systemd ecosystem. If a package has a hard systemd dependency, find an alternative or patch it out. Document the decision.

9. No Bootloader

The kernel boots via UEFI Stub (EFISTUB). No GRUB, no systemd-boot, no rEFInd. The kernel is the bootloader. This affects how the kernel is compiled and how the EFI partition is structured.

10. No Display Manager

No SDDM, no GDM, no LightDM. The system boots directly into a TTY, auto-logs in the user, and launches the Wayland compositor (dwl) from the shell profile. This must be seamless and instant.


Project Overview

Build a complete Linux distribution comprising four major deliverables, each living in its own subdirectory under src/ and eventually becoming its own git repository:

  1. dpack (src/dpack) — A custom package manager written in Rust, positioned between CRUX's pkgutils and Gentoo's emerge in complexity and capability.
  2. ISO builder (src/iso) — Tooling to produce a bootable live CD/USB image of the distribution.
  3. Installer (src/install) — A CRUX-style interactive installer that runs from the live environment and walks the user through disk selection, user creation, locale, timezone, and keyboard setup.
  4. Package repository (src/repos) — The package definitions (recipes/ports) that dpack consumes to build and install software.

Hardware Target

This distribution targets exactly one machine. Every optimization decision — kernel config, compiler flags, scheduler tuning — is made for this specific hardware and nothing else.

Component Model
Motherboard ASUS ROG CROSSHAIR X870E HERO
CPU AMD Ryzen 9 9950X3D (Zen 5, 16C/32T, 3D V-Cache)
RAM Corsair Vengeance DDR5-6000 96GB CL30 (Dual Channel, 2×48GB)
Storage Samsung 9100 PRO 2TB NVMe (PCIe 5.0 x4)
GPU ASUS GeForce RTX 5090 ROG Astral LC OC 32GB GDDR7

Compiler Flags (Global)

These flags should be set as the default CFLAGS/CXXFLAGS for the entire toolchain and all package builds:

# Targeting Zen 5 (znver5) — if GCC/LLVM version doesn't yet support znver5, use znver4
# and leave a TODO to revisit when compiler support lands.
export CFLAGS="-march=znver5 -O2 -pipe -fomit-frame-pointer"
export CXXFLAGS="${CFLAGS}"
export MAKEFLAGS="-j32"    # 16 cores, 32 threads
export LDFLAGS="-Wl,-O1,--as-needed"

Note: -O2 is chosen over -O3 as the sane default. -O3 can be enabled per-package where benchmarks show measurable improvement (e.g., mesa, wine). Document any per-package flag overrides in the package definition.


Architecture Decisions

These are locked-in decisions. Do not revisit them unless the user explicitly asks.

Decision Choice Rationale
Init system SysVinit + custom rc scripts Matches CRUX model. Simple, transparent, fast.
Service management rc.conf + rc.d/ scripts No daemons managing daemons. Direct control.
Device manager eudev udev replacement, no systemd dependency.
Boot method EFISTUB (kernel as EFI binary) No bootloader. Kernel boots directly via UEFI.
Display protocol Wayland (via dwl compositor) Modern, performant, required for latest Nvidia support.
X compatibility XWayland For legacy apps (Steam, some games).
Package manager dpack (custom, Rust) Core deliverable of this project.
Shell bash (build) / zsh (user) Bash for build scripts, zsh as user's interactive shell.
Filesystem ext4 Simpler, faster, battle-tested. User confirmed.
Partition scheme GPT + EFI System Partition Required for EFISTUB boot on UEFI systems.
C library glibc Broadest compatibility, required by Steam/Wine/Proton.
Privilege escalation polkit + lxqt-policykit Qt-based password agent. Lightweight, minimal deps.
Network management dhcpcd Ethernet only. Minimal, no WiFi needed.
Audio PipeWire Modern replacement for PulseAudio + ALSA, best game compat.

Project Structure

project-root/
├── CLAUDE.md                  # THIS FILE — project directive
├── docs/
│   └── CHANGELOG.md           # Mandatory changelog (see protocol below)
├── src/
│   ├── dpack/                 # The custom package manager (Rust)
│   │   ├── Cargo.toml
│   │   ├── src/
│   │   │   ├── main.rs
│   │   │   ├── lib.rs
│   │   │   ├── config/        # Configuration parsing and management
│   │   │   ├── resolver/      # Dependency resolution engine
│   │   │   ├── sandbox/       # Build sandboxing (namespaces/bubblewrap)
│   │   │   ├── converter/     # Gentoo ebuild & CRUX Pkgfile converters
│   │   │   ├── db/            # Installed package database (file-based)
│   │   │   └── build/         # Package build orchestration
│   │   └── tests/
│   ├── iso/                   # Live CD/USB creation tooling
│   │   ├── build-iso.sh       # Main ISO build script
│   │   ├── overlay/           # Files overlaid onto the live filesystem
│   │   └── configs/           # ISO-specific configs (mkinitramfs, etc.)
│   ├── install/               # Installer scripts (runs from live env)
│   │   ├── install.sh         # Main installer entry point
│   │   ├── modules/           # Modular installer steps
│   │   │   ├── disk.sh        # Disk selection and partitioning
│   │   │   ├── user.sh        # User/password creation
│   │   │   ├── locale.sh      # Locale, timezone, keyboard
│   │   │   └── packages.sh    # Base system package installation
│   │   └── configs/           # Template configs deployed during install
│   └── repos/                 # Package repository (dpack format)
│       ├── core/              # Essential system packages (toolchain, kernel, coreutils, etc.)
│       ├── extra/             # Non-essential but common packages
│       ├── gaming/            # Steam, Proton, Wine, launchers
│       └── desktop/           # dwl, Wayland, fonts, themes, GUI apps
├── kernel/
│   └── config                 # The kernel .config file, fully commented
├── configs/
│   ├── rc.conf                # Init system configuration
│   ├── rc.d/                  # Service scripts
│   ├── fstab.template         # Template fstab
│   └── dwl/                   # dwl configuration and patches
└── reference/                 # Symlinks or notes pointing to LFS/BLFS/CRUX/Gentoo material

Rule: If you need to create a directory or file not shown above, discuss it first unless it's clearly a subdirectory of an existing defined location.


Phase Breakdown & Execution Order

This project is broken into sequential phases. Each phase has clear entry criteria, deliverables, and exit criteria. Work phases in order. Phases may have sub-phases for very large work items.

Phase 0 — Foundation & Toolchain Bootstrap

Goal: Establish a cross-compilation toolchain and minimal chroot environment capable of building everything else. This follows the LFS book chapters 4-8 conceptually, but with our hardware-specific flags and latest package versions.

Deliverables:

  • Toolchain build scripts (binutils, gcc, glibc, etc.) targeting znver5
  • A functional chroot with a working compiler and core utilities
  • All scripts in src/iso/ or a dedicated toolchain/ directory
  • Version manifest documenting every package version used

Exit criteria: Can compile and link a "Hello World" C program inside the chroot with correct -march=znver5 targeting.


Phase 1 — dpack Core (Minimum Viable Package Manager)

Goal: Build the core of dpack to the point where it can parse a package definition, resolve dependencies from a local repo, and build a package in a sandbox.

Sub-phases:

  1. 1a — Package format definition: Design and document the .toml package definition format (the recipe file). Must be expressive enough to handle the range from simple make install packages to complex multi-step builds like the kernel or mesa.
  2. 1b — Dependency resolver: Implement the dependency resolution engine. Must handle: direct deps, build deps, optional deps, version constraints, and circular dependency detection.
  3. 1c — Sandbox: Implement build sandboxing using Linux namespaces (mount, PID, network) or bubblewrap. Packages build in an isolated root with only their declared dependencies visible.
  4. 1d — Database: Implement the installed-package database. File-based (e.g., TOML or custom format in /var/lib/dpack/). Tracks: package name, version, installed files, dependencies with exact versions, whether deps are shared or static.
  5. 1e — Build & install orchestration: Wire it all together. dpack install <package> should resolve deps → sandbox build → install to system → update database.

Exit criteria: Can dpack install a simple package (e.g., zlib) from a local repo definition, building it in a sandbox, and track it in the database.


Phase 2 — dpack Advanced Features

Goal: Implement the converters and smart dependency management.

Sub-phases:

  1. 2a — CRUX Pkgfile converter: Parse CRUX Pkgfile format and emit a .toml definition. Handle the common patterns (source download, build(), install steps).
  2. 2b — Gentoo ebuild converter: Parse Gentoo .ebuild files and emit .toml definitions. This is significantly more complex — handle USE flags by mapping them to dpack's optional dependency system, handle eclasses by inlining or converting common ones.
  3. 2c — Shared library conflict detection: Implement the smart dependency resolution described in the spec: detect when a shared library version is needed by multiple packages, check if an update exists that satisfies all consumers, and if not, prompt the user about static compilation.
  4. 2d — Package upgrade/remove: dpack upgrade, dpack remove with proper dependency reverse-tracking.

Exit criteria: Can convert a real CRUX Pkgfile and a real Gentoo ebuild into dpack format and build them successfully. Shared lib conflict detection works on a constructed test case.


Phase 3 — Base System Packages

Goal: Write dpack package definitions for the complete base system (everything LFS builds, plus eudev, PipeWire, networking, etc.). Build and install them all using dpack.

Deliverables:

  • Complete src/repos/core/ with all base system packages
  • A bootable (in a VM or chroot) minimal system with: kernel, init, shell, coreutils, networking, eudev

Exit criteria: System boots in a QEMU VM via EFISTUB, drops to a shell, has networking.


Phase 4 — Kernel Configuration

Goal: Produce a fully optimized, hardware-specific kernel config for the target machine.

Key decisions (all must be commented in the config):

  • Scheduler: EEVDF (default in 6.19+) or BORE patchset — research and decide
  • CPU governor: schedutil (Zen 5 optimized)
  • Preemption model: PREEMPT (full preemption for gaming latency)
  • NVMe: PCIe 5.0, Samsung 9100 PRO specific optimizations
  • GPU: Nvidia DRM/KMS, nvidia-open module support (RTX 5090)
  • USB: XHCI for USB 3.x/4.0 on X870E
  • Audio: snd-hda-intel for onboard, plus USB audio class
  • Networking: Realtek RTL8125BN (2.5GbE on X870E Hero), no WiFi
  • IOMMU: AMD-Vi enabled (for potential GPU passthrough later)
  • Filesystem: ext4/btrfs built-in (not module) for root
  • Disable everything not needed: no Bluetooth (unless user wants it), no legacy ISA, no ancient network drivers, no PCMCIA, no infrared, etc.

Exit criteria: Kernel compiles, boots via EFISTUB on QEMU (and eventually on real hardware), detects all target hardware.


Phase 5 — Init System & Service Scripts

Goal: Implement the SysVinit + rc.d service management layer.

Deliverables:

  • rc.conf — system-wide configuration (hostname, timezone, locale, keymap, network, daemons array)
  • rc.d/ scripts for: networking, eudev, syslog, PipeWire, dbus (needed for polkit)
  • /etc/inittab configured for auto-login on tty1
  • Shell profile that auto-starts dwl on login to tty1

Exit criteria: System boots → auto-logs in → launches dwl compositor, all without user interaction.


Phase 6 — Desktop Environment (dwl + Wayland Stack)

Goal: Build and configure dwl with patches, plus the full Wayland stack.

Deliverables:

  • dpack definitions for: wayland, wayland-protocols, wlroots, dwl (with patches), xwayland, foot/wezterm, dmenu/fuzzel/tofi (launcher)
  • dwl patches applied: bar (status bar), gaps (window gaps), plus any others useful for gaming/dev (vanitygaps, autostart, etc.)
  • dwl config.h tailored for the user's workflow
  • Nvidia-specific Wayland env vars (WLR_NO_HARDWARE_CURSORS, etc.)

Exit criteria: dwl launches with bar and gaps, can open a terminal, can launch Firefox.


Phase 7 — Nvidia Driver Stack

Goal: Build and install the proprietary Nvidia driver (or nvidia-open) for the RTX 5090.

Key concerns:

  • RTX 5090 (Blackwell) requires very recent driver branches — likely 570.x+ or newer
  • Must build DKMS or manual kernel module against our custom kernel
  • Needs: nvidia-drm, nvidia-modeset, nvidia-uvm
  • Vulkan ICD, OpenGL, EGL, GBM support
  • 32-bit compatibility libs for Wine/Proton

Exit criteria: nvidia-smi works, Vulkan vkcube renders, OpenGL glxgears renders via XWayland.


Phase 8 — Gaming Stack

Goal: Install Steam, Proton, Wine, and game launchers.

Deliverables:

  • dpack definitions for: Steam (native Linux), Wine (latest stable + staging), Proton-GE or official Proton, protontricks, winetricks, gamemode, mangohud
  • Ubisoft Connect via Wine/Proton prefix
  • PrismLauncher (Minecraft launcher) — requires Java (OpenJDK)
  • 32-bit multilib support as needed by Steam/Wine

Exit criteria: Steam launches, can download and run a Proton game. PrismLauncher launches Minecraft.


Phase 9 — Application Stack

Goal: Install remaining user applications.

Deliverables:

  • dpack definitions for: Firefox, WezTerm, FreeCAD, polkit + polkit-agent (lxqt-policykit or polkit-gnome-agent for password prompts)
  • AMD microcode package (for CPU microcode updates via early initramfs loading)

Exit criteria: All listed applications launch and function correctly.


Phase 10 — ISO Builder

Goal: Build tooling that produces a bootable live USB/CD image containing the installer and a minimal live environment.

Deliverables:

  • src/iso/build-iso.sh — orchestrates the full ISO build
  • Live environment contains: base system, dpack, installer scripts, basic shell tools
  • Boots via EFISTUB (ISO uses El Torito + ESP for UEFI boot)
  • squashfs compressed root filesystem for the live environment

Exit criteria: ISO boots in QEMU, drops into a live shell, installer can be launched.


Phase 11 — Installer

Goal: Build the CRUX-style interactive installer.

Installer flow:

  1. Welcome screen — brief info about the distro
  2. Disk selection — list available disks, let user choose, offer auto-partition (GPT: ESP + root + optional swap) or manual
  3. Filesystem — format partitions (ext4/btrfs)
  4. Base install — extract/install base system packages via dpack
  5. Kernel install — copy kernel to ESP
  6. User setup — create user account, set password, set root password
  7. Locale/timezone/keymap — interactive selection
  8. Bootloader (EFISTUB) — set up EFI boot entry via efibootmgr
  9. Post-install package selection — offer to install desktop/gaming/dev packages
  10. Finalize — generate fstab, set hostname, unmount, reboot

Exit criteria: Full install from live ISO to bootable system in QEMU.


Phase 12 — Integration Testing & Polish

Goal: End-to-end testing of the complete flow: ISO → install → boot → desktop → gaming.

Deliverables:

  • Test checklist covering every phase's exit criteria
  • Bug fixes and polish
  • Final CHANGELOG update

dpack — The Package Manager

Package Definition Format (.toml)

The format is a TOML file. Here's the canonical structure:

[package]
name = "zlib"
version = "1.3.1"
description = "Compression library"
url = "https://zlib.net/"
license = "zlib"

[source]
url = "https://zlib.net/zlib-${version}.tar.xz"
sha256 = "abc123..."  # Always verify sources

[dependencies]
# Runtime dependencies
run = []

# Build-time only dependencies
build = ["gcc", "make"]

# Optional features (inspired by Gentoo USE flags)
[dependencies.optional]
static = { description = "Build static library", default = true }
minizip = { description = "Build minizip utility", deps = [] }

[build]
# Build steps — executed in sandbox
configure = "./configure --prefix=/usr"
make = "make"
install = "make DESTDIR=${PKG} install"

# Per-package flag overrides (optional)
[build.flags]
cflags = ""   # Empty = use global defaults. Set explicitly to override.
ldflags = ""

This format is a starting point. It will evolve during Phase 1. Any changes must be documented.

Database Location and Format

Installed package database lives at /var/lib/dpack/db/. One TOML file per installed package:

/var/lib/dpack/db/
├── zlib.toml        # Tracks version, files, deps
├── gcc.toml
└── ...

Sandbox Implementation

The build sandbox must:

  • Use Linux namespaces (mount, PID, optionally network) or wrap bubblewrap (bwrap)
  • Mount only the declared dependencies into the sandbox's /usr, /lib, etc.
  • Use a fresh tmpfs or overlay for the build directory
  • Prevent network access during build (optional: configurable, some packages need to download at build time)
  • Capture the installed files via DESTDIR to a staging area before committing to the real filesystem

Converter Architecture

Converters are separate modules that parse foreign package formats and emit .toml TOML:

  • CRUX converter: Parses Pkgfile (bash-like syntax with source=(), build() function). Relatively straightforward.
  • Gentoo converter: Parses .ebuild (bash + eclasses + complex variable expansion). Best-effort conversion — flag anything that can't be cleanly converted and require manual review. Map common USE flags to dpack optional deps. Do not try to replicate the full Portage system.

Shared Library Conflict Resolution

When dpack install foo would update a shared library that bar also depends on:

  1. Check if bar has an update that works with the new library version.
  2. If yes, offer to update bar as well.
  3. If no, warn the user and offer options: (a) compile foo with the library statically linked, (b) hold back the library update, (c) force it (user accepts the risk).
  4. Track the decision in the database.

Kernel Configuration

Kernel version: 6.19.8 (or latest 6.19.x stable at time of build — verify before building)

Critical Config Flags

# CPU — AMD Zen 5 (9950X3D)
CONFIG_MZEN5=y                        # If available, otherwise MZEN4
CONFIG_X86_X2APIC=y
CONFIG_AMD_MEM_ENCRYPT=y               # SME support
CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y
CONFIG_X86_AMD_PSTATE=y                # AMD P-State driver (preferred over acpi-cpufreq for Zen 5)
CONFIG_AMD_PMC=y                       # Platform Management Controller

# Scheduler
CONFIG_PREEMPT=y                       # Full preemption for low-latency gaming
CONFIG_HZ_1000=y                       # 1000Hz tick for responsiveness
CONFIG_NO_HZ_FULL=y                    # Tickless for idle cores

# NVMe — Samsung 9100 PRO (PCIe 5.0)
CONFIG_BLK_DEV_NVME=y                  # Built-in (not module) — root is on NVMe
CONFIG_NVME_MULTIPATH=n                # Single disk, not needed

# GPU — NVIDIA RTX 5090 (Blackwell)
CONFIG_DRM=y
CONFIG_DRM_NOUVEAU=n                   # Disable nouveau — proprietary driver only
CONFIG_DRM_SIMPLEDRM=y                 # Fallback framebuffer before nvidia loads

# Network — Realtek RTL8125BN (2.5GbE on X870E Hero)
CONFIG_R8169=y                         # Realtek 8125/8169 family driver
CONFIG_NET_VENDOR_REALTEK=y

# USB/Thunderbolt — X870E has USB4
CONFIG_USB_XHCI_HCD=y
CONFIG_USB4=y                          # Unified USB4/Thunderbolt support
CONFIG_THUNDERBOLT=y

# IOMMU — AMD-Vi
CONFIG_AMD_IOMMU=y
CONFIG_AMD_IOMMU_V2=y
CONFIG_IOMMU_DEFAULT_DMA_LAZY=y

# Sound — Onboard ALC4082 (or similar on X870E Hero)
CONFIG_SND_HDA_INTEL=y
CONFIG_SND_HDA_CODEC_REALTEK=y

# Filesystem
CONFIG_EXT4_FS=y                       # Or BTRFS — whichever is chosen
CONFIG_TMPFS=y
CONFIG_VFAT_FS=y                       # For EFI partition
CONFIG_EFI_PARTITION=y
CONFIG_EFIVAR_FS=y
CONFIG_EFI_STUB=y                      # THIS IS CRITICAL — enables direct UEFI boot

# Disable bloat
CONFIG_BLUETOOTH=n                     # Enable if user wants it — ASK
CONFIG_WIRELESS=n                      # Enable if WiFi needed — ASK  
CONFIG_PCMCIA=n
CONFIG_INFINIBAND=n
CONFIG_ISDN=n
CONFIG_INPUT_JOYSTICK=y                # Keep for gaming controllers!
CONFIG_INPUT_TOUCHSCREEN=n
CONFIG_SOUND_OSS_CORE=n                # ALSA only, no OSS emulation

These are starting points. The full .config will be generated during Phase 4 with make menuconfig as the base, then these overrides applied and verified. Every non-default choice must have a comment.


Init System

/etc/inittab (Skeleton)

# DarkForge Linux inittab
id:3:initdefault:

si::sysinit:/etc/rc.d/rc.sysinit
l3:3:wait:/etc/rc.d/rc.multi

# Auto-login on tty1 — no password prompt
1:2345:respawn:/sbin/agetty --autologin danny --noclear 38400 tty1 linux
2:2345:respawn:/sbin/agetty 38400 tty2 linux

ca::ctrlaltdel:/sbin/shutdown -r now

Shell Profile Auto-Start (~/.bash_profile or ~/.profile)

# Auto-start dwl on tty1 if not already running
if [ -z "${WAYLAND_DISPLAY}" ] && [ "$(tty)" = "/dev/tty1" ]; then
    exec dwl
fi

rc.conf

# DarkForge Linux System Configuration

HOSTNAME="darkforge"
TIMEZONE="America/New_York"       # Set during install — placeholder, confirm with user
KEYMAP="us"                       # Set during install — placeholder, confirm with user
LOCALE="en_US.UTF-8"              # Set during install — placeholder, confirm with user

# Daemons to start at boot (order matters)
DAEMONS=(eudev syslog dbus dhcpcd pipewire)

# Kernel modules to load at boot (if any aren't autoloaded)
MODULES=(nvidia nvidia-modeset nvidia-drm nvidia-uvm)

ISO & Installer

ISO Build Requirements

  • squashfs-tools — compress the live root filesystem
  • xorriso or genisoimage — create the ISO9660 image
  • mtools — manipulate the EFI boot image within the ISO
  • The ISO must support UEFI boot (El Torito with EFI System Partition image)
  • No legacy BIOS boot support needed (target hardware is UEFI only)

Installer Requirements

  • Interactive, text-based (dialog/whiptail or plain shell prompts)
  • Must ask for: target disk, partition scheme (auto/manual), filesystem, username, user password, root password, timezone, locale, keymap
  • Must setup: partitions, install base packages via dpack, install kernel to ESP, configure fstab/rc.conf/inittab, create EFI boot entry via efibootmgr
  • Must be idempotent where possible (re-running a step doesn't break things)

Target Package List

These packages must have dpack definitions and be installable by the end of the project. Organized by repo category:

core/

Base system (toolchain, kernel, coreutils, util-linux, bash, glibc, binutils, gcc, make, etc.), eudev, sysvinit, dbus, dhcpcd, openssl, curl, git, tar, xz, zstd, bzip2, gzip, pkg-config, meson, ninja, cmake, python, perl

extra/

PipeWire, wireplumber, polkit, lxqt-policykit (password agent), mesa, vulkan-loader, vulkan-tools, libdrm, fontconfig, freetype, harfbuzz, pango, cairo, glib, gtk3, gtk4, qt6-base

desktop/

wayland, wayland-protocols, wlroots, dwl (with patches), xwayland, wezterm, firefox, freecad, foot (backup terminal), fuzzel or tofi (launcher), grim + slurp (screenshots), wl-clipboard

gaming/

steam, wine (latest stable), proton-ge (or valve proton), protontricks, winetricks, gamemode, mangohud, lib32 compatibility packages, dxvk, vkd3d-proton, prismlauncher, openjdk


Reference Material

The following reference documents are available in the project root and should be consulted during the relevant phases:

Material Location Used In
LFS Book 13.0 LFS-BOOK-r13.0-4-NOCHUNKS.html Phase 0, 3
BLFS Book 12.4 BLFS-BOOK-12.4-nochunks.html Phase 3, 6-9
GLFS (Gaming LFS) glfs-13.0/ Phase 7, 8
MLFS (Musl LFS) mlfs/ Reference only
SLFS slfs-13.0/ Reference only
CRUX ISO build scripts crux_iso/ Phase 10
CRUX ports (all repos) crux_ports/ Phase 2a, 3
Gentoo ebuilds gentoo/ Phase 2b, 3
dwl source dwl/ Phase 6
dwl patches dwl-patches/ Phase 6

Always cross-reference multiple sources when writing package definitions. LFS gives build instructions, CRUX gives packaging patterns, Gentoo gives dependency information and USE flag mappings.


Changelog Protocol

Location: docs/CHANGELOG.md

Every change must produce an entry. No exceptions. The format is:

## V<N> <YYYY-MM-DD HH:MM:SS>

**<Short description — one line, imperative mood>**

### Changes:
- <What was added, modified, or removed. Be specific. Reference file paths.>
- <Another change>

### Plan deviation/changes:
- <Any changes to the plan, scope, or architecture decisions. "None" if none.>

### What is missing/needs polish:
- <Known issues, TODOs, rough edges left behind. "None" if none.>

---

Rules:

  • <N> is an auto-incrementing integer starting at 1. Never reuse a number.
  • Timestamps are in UTC.
  • The short description uses imperative mood: "Add zlib package definition" not "Added zlib package definition".
  • If a session produces multiple logical changes, each gets its own entry.

Session Protocol

At the start of every session:

  1. Read this file in full. Non-negotiable.
  2. Read docs/CHANGELOG.md to understand where the project left off.
  3. Ask the user: "Where should we pick up?" or propose the next logical step based on the phase plan.
  4. Confirm the plan for this session before writing any code.

At the end of every session:

  1. Write changelog entries for everything done.
  2. Summarize what was accomplished and what the next step is.
  3. Flag any open questions or decisions needed from the user.

Known Pitfalls & Guardrails

These are lessons learned and things to watch out for. Add to this section as the project progresses.

  1. znver5 compiler support: As of early 2025, GCC 14 and LLVM 18 may not fully support -march=znver5. If not, use -march=znver4 and leave a TODO to revisit. Check gcc -march=native -Q --help=target on the target hardware if possible.

  2. RTX 5090 driver maturity: The RTX 5090 (Blackwell) is very new. The open-source nvidia-open kernel module may not fully support it yet. Be prepared to use the proprietary blob. Track the driver version requirement carefully.

  3. Steam 32-bit dependencies: Steam requires a large set of 32-bit libraries (multilib). This significantly complicates the build. Plan for it early — the toolchain may need multilib GCC, and many packages need 32-bit builds.

  4. Wine/Proton 32-bit: Same as Steam. Wine needs a multilib build environment.

  5. dwl patch conflicts: dwl patches are written against specific commits. Applying multiple patches will almost certainly produce conflicts. Plan to apply them one at a time, resolve conflicts, and test after each one.

  6. EFISTUB quirks: Some UEFI firmware implementations are picky about the kernel binary location on the ESP. Standard location is /EFI/Linux/vmlinuz.efi or /EFI/BOOT/BOOTX64.EFI. Test with the target motherboard's firmware.

  7. PipeWire without systemd: PipeWire is designed to work with systemd user sessions. Running it without systemd requires manually starting it (and WirePlumber) from the shell profile or an rc.d script. This is doable but requires careful setup.

  8. Polkit without systemd: Similar to PipeWire — polkit's default backend uses systemd. You'll need the polkit-duktape or polkit-mozjs backend with an elogind or seatd session. Investigate seatd as the minimal seat manager.

  9. Wayland + Nvidia: Nvidia Wayland support has improved dramatically but still requires specific env vars and careful driver setup. WLR_NO_HARDWARE_CURSORS=1 is often still needed. wlroots must be built with the Nvidia backend.

  10. Gentoo ebuild conversion is best-effort. Ebuilds can be extraordinarily complex (eclasses, conditional deps, slot dependencies, multi-phase builds). The converter should handle 80% of cases and flag the rest for manual review. Do not try to build a full Portage reimplementation.


Resolved Questions

All open questions have been answered (2026-03-19). These decisions are now locked in.

  1. Filesystem: ext4 — simpler, faster, battle-tested.
  2. Bluetooth: Disabled (CONFIG_BLUETOOTH=n).
  3. WiFi: Ethernet only. No WiFi drivers, no iwd.
  4. Network manager: dhcpcd (minimal, ethernet-only).
  5. Default shell: zsh for the user. Bash remains the build script shell.
  6. Ubisoft launcher: Skipped for now. Can add later.
  7. Password agent: lxqt-policykit (Qt-based, lightweight).
  8. Swap: 96GB swap partition (matching RAM size) to enable hibernation/sleep.
  9. Hostname: darkforge
  10. Username: danny