This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
pi-gen is a tool for creating Raspberry Pi OS images and custom images based on Raspberry Pi OS. This repository builds 64-bit ARM images (from the arm64 branch) while 32-bit images are built from the master branch.
This fork is customized for Computado Rita OS (CROS), a rebranded version configured for Costa Rica with Spanish localization. See config and docs/ for branding details.
# Edit config file first to set IMG_NAME and other variables
./build.sh# For systems without Debian-based OS or for isolation
./build-docker.sh
# Continue after fixing errors
CONTINUE=1 ./build-docker.sh
# Preserve container for incremental changes
PRESERVE_CONTAINER=1 ./build-docker.sh
# Clean rebuild of last stage only
CLEAN=1 ./build.sh# 1. Add SKIP_IMAGES to stages with EXPORT_* files to prevent image generation during development
touch ./stage2/SKIP_IMAGES ./stage4/SKIP_IMAGES ./stage5/SKIP_IMAGES
# 2. Add SKIP files to stages you don't want to build
touch ./stage3/SKIP ./stage4/SKIP ./stage5/SKIP
# 3. Initial full build
./build.sh
# 4. Add SKIP to earlier successful stages
touch ./stage0/SKIP ./stage1/SKIP
# 5. Modify and rebuild only the last stage
CLEAN=1 ./build.shThe build process iterates through stage directories (stage0-stage5) in alphanumeric order. Each stage builds upon the previous one using rsync to copy the rootfs.
Stage Progression:
- stage0: Bootstrap - Creates minimal filesystem via debootstrap. Installs raspberrypi-bootloader. NOT bootable.
- stage1: Truly minimal bootable system - Configures /etc/fstab, bootloader, networking, raspi-config
- stage2: Lite system - Produces Raspberry Pi OS Lite. Adds wireless/bluetooth, timezone/locale, fake-hwclock, swap
- stage3: Desktop system - Full desktop with X11, LXDE, web browsers, development tools
- stage4: Standard image - System for 4GB cards with documentation and user-friendly tools
- stage5: Full image - Additional development tools, email, Scratch, sonic-pi, office suite
Within each stage directory:
prerun.shruns (typically copies from previous stage)- Process each numbered subdirectory (00-, 01-, etc.) containing:
00-debconf: Debconf configuration passed to debconf-set-selections00-packages: Packages to install with apt-get install -y00-packages-nr: Packages to install with --no-install-recommends00-patches/: Directory of quilt patches to apply00-run.sh: Executable shell script (runs on host)00-run-chroot.sh: Shell script run inside chroot
- Check for EXPORT_IMAGE or EXPORT_NOOBS markers
- Generate images if marked
Important: Subdirectories must be named with two-digit padded numbers at the beginning (00-, 01-, 02-, etc.)
build.sh: Main build orchestrator (sources config, iterates stages, calls common functions)scripts/common: Shared functions including:bootstrap(): Runs debootstrap with arm64 architecturecopy_previous(): Rsyncs previous stage rootfson_chroot(): Executes commands in chroot with proper mounts (proc, dev, sys, run, tmp)unmount(): Safely unmounts chroot filesystemslog(): Timestamped logging
The config file (sourced by build.sh) sets environment variables:
Essential variables:
IMG_NAME: Root name of the OS image (default: cros-$RELEASE-$ARCH)RELEASE: Debian release version (default: trixie for arm64 branch)STAGE_LIST: Override default stage order or add custom stages
Customization variables:
LOCALE_DEFAULT,TARGET_HOSTNAME,KEYBOARD_KEYMAP,KEYBOARD_LAYOUT,TIMEZONE_DEFAULTFIRST_USER_NAME,FIRST_USER_PASS,DISABLE_FIRST_BOOT_USER_RENAMEENABLE_SSH,PUBKEY_SSH_FIRST_USER,WPA_COUNTRY
Build control:
WORK_DIR: Build cache location (default: $BASE_DIR/work) - stores complete copy per stageDEPLOY_DIR: Output location (default: $BASE_DIR/deploy)DEPLOY_COMPRESSION: none|zip|gz|xz (default: zip)ENABLE_CLOUD_INIT: Install cloud-init and netplan (default: 1)
SKIP: Place in stage directory to bypass that stage entirelySKIP_IMAGES: Place in stage to prevent image export even if EXPORT_IMAGE existsEXPORT_IMAGE: Marks stage for image generationEXPORT_NOOBS: Marks stage for NOOBS bundle generation
- Base path must NOT contain spaces (debootstrap limitation)
- WORK_DIR must be on a proper Linux filesystem, not NTFS
- Requires Debian-based OS released after 2017
- arm64 branch builds 64-bit images only; use master branch for 32-bit
Install with: apt install coreutils quilt parted qemu-user-static debootstrap zerofree zip dosfstools e2fsprogs libarchive-tools libcap2-bin grep rsync xz-utils file git curl bc gpg pigz xxd arch-test bmap-tools kmod
See depends file for complete list in format <tool>[:<debian-package>].
stage*/: Build stages with numbered subdirectoriesexport-image/: Scripts for image finalization (creates .img file from rootfs, set-partuuid, network config, user-rename)export-noobs/: NOOBS bundle generationscripts/: Common functions and utilities including scripts/common (core functions)rebrand/: Rebranding scripts and utilities for Computado Rita customizationdocs/: Documentation for Computado Rita rebranding and package informationwork/: Build cache (gitignored, can be large - tens of GB)deploy/: Output images (gitignored)
After stages complete, the export-image/ scripts run to create the final .img file:
prerun.sh: Creates empty .img file, partitions it (bootfs + rootfs), mounts partitions- Numbered subdirectories run (00-, 01-, etc.) to configure the image
- Final .img is compressed according to
DEPLOY_COMPRESSIONsetting - Output:
deploy/CROS-YYYY-MM-DD-arm64.img.xz(or .zip/.gz depending on config)
The image includes:
- Boot partition (FAT32, 512MB): kernel, firmware, config.txt
- Root partition (ext4): complete filesystem from final stage
Build fails with "binfmt_misc" error:
- Ensure qemu-user-static is installed:
apt install qemu-user-static - Load kernel module:
modprobe binfmt_misc - On WSL:
sudo update-binfmts --enable
Permission errors during build:
- build.sh must run as root:
sudo ./build.sh - Check WORK_DIR is on Linux filesystem (not NTFS)
Out of space errors:
- WORK_DIR stores complete copy per stage (can use 50GB+)
- Clean up:
sudo rm -rf work/ - Set WORK_DIR to larger partition in config
Continue interrupted build:
- Docker:
CONTINUE=1 ./build-docker.sh - Rebuild only last stage:
CLEAN=1 ./build.sh
Debugging stage failures:
- Check logs:
cat work/*/build.log - For chroot issues: Verify arm64 emulation with
arch-test arm64 - Add SKIP to failing stage, examine work/stageN/rootfs manually
Comprehensive documentation is available in the docs/ directory:
- docs/README.md - Documentation index and quick reference for CROS
- docs/REBRANDING_CHANGES.md - Complete rebranding summary from Raspberry Pi to Computado Rita
- docs/IMAGE_REBRANDING_GUIDE.md - Guide to replacing visual assets and branding images
- docs/RASPBERRY_PI_SPECIFIC_PACKAGES.md - Documentation of Pi-specific packages (essential for understanding dependencies)
- docs/RASPBERRY_PI_TEXT_REPLACEMENT_GUIDE.md - Guide for safe text replacements
- docs/RASPBIAN_TO_CROS_REPLACEMENTS.md - Raspbian/RaspiOS to CROS replacement guide