Skip to content

Latest commit

 

History

History
1442 lines (1285 loc) · 56.7 KB

File metadata and controls

1442 lines (1285 loc) · 56.7 KB

vibeutils - GNU Coreutils in Zig

Progress Summary

  • Completed: 47/47 utilities - ALL IMPLEMENTED
  • Utilities: basename, cat, chmod, chown, cp, cut, date, dd, df, dirname, du, echo, env, false, find, free, grep, head, id, ln, ls, mkdir, mktemp, mv, nl, printf, pwd, readlink, realpath, rm, rmdir, seq, sleep, sort, stat, tac, tail, tee, test, timeout, touch, tr, true, uniq, wc, whoami, yes
  • Flag coverage: 288/288 MUST, 220/220 SHOULD (100%)
  • Compatibility: 90-100% GNU feature coverage for completed utilities
  • Infrastructure: justfile build system, CI/CD, privileged testing, writer-based I/O, Zig 0.16.0, 7 shared common modules (time, path, glob, prompt, format, file_ops, lib color detection)
  • Packaging: Homebrew tap, Nix flake with Cachix binary cache (4 platforms), GitHub release binaries
  • Documentation: Claude Code quality check (/qc), man page style guide, testing strategy, CHANGELOG.md

Tiger Style remediation (deferred)

  • Enable scripts/tiger-check.sh in CI after the Tiger Style migration is finished (Phases 3-6 in docs/tiger-style-review/README.md). Add a CI job running scripts/tiger-check.sh --base origin/main to gate PRs on NEW Tiger Style violations. Deferred deliberately: the pre-commit hook already blocks NEW violations locally, and we want builds green through the migration before enforcing in CI (the tree still carries ~3442 pre-existing violations; --base only fails on newly introduced ones, but enable CI once the debt is burned down by the function-length, assertion, and cleanup phases).

Project Goals

  • Balance: 80% of GNU's usefulness with 20% of the complexity
  • High test coverage: 90%+ with TDD approach
  • Modern enhancements: Colors, icons, smart formatting, performance
  • OpenBSD-inspired: Clear options, concise man pages with examples
  • Practical compatibility: Features people actually use

POSIX Compliance & Flag Coverage

Step 1: Download POSIX specs

For each of the 37 POSIX utilities, download the OPTIONS section from pubs.opengroup.org/onlinepubs/9699919799/utilities/<util>.html and save as docs/specs/<util>-posix.txt. Plain text, flags and descriptions only.

37 POSIX utilities: basename, cat, chmod, chown, cp, cut, date, dd, df, dirname, du, echo, env, false, find, grep, head, id, ln, ls, mkdir, mv, nl, printf, pwd, rm, rmdir, sleep, sort, tail, tee, test, touch, tr, true, uniq, wc

Skip (non-POSIX): free, mktemp, readlink, realpath, seq, stat, tac, timeout, whoami, yes

Step 2: Capture reference flags from all sources

For each of the 47 utilities, capture four sources:

  • macOS man page + help: Parse flags from MANPATH=/usr/share/man man <util>, then append /bin/<util> --help (or -h) output under a --- --help output --- separator. Save to docs/specs/<util>-macos.txt.
  • OpenBSD man page: Fetch from man.openbsd.org/<util>.1 and save to docs/specs/<util>-openbsd.txt.
  • GNU coreutils: Run g<util> --help (from Nix coreutils package), save to docs/specs/<util>-gnu.txt.
  • Our flags: Run ./zig-out/bin/<util> --help, save to docs/specs/<util>-vibeutils.txt.

Step 3: Coverage decisions (interactive)

Create docs/specs/<util>-flags.md for each utility with a flags table:

| Flag | POSIX | macOS | OpenBSD | GNU | Ours | Tier |
|------|-------|-------|---------|-----|------|------|
| -a   | yes   | yes   | yes     | yes | yes  | MUST |
| -X   | no    | yes   | no      | yes | no   | SHOULD |
| -Z   | no    | no    | no      | yes | no   | WONT |

Auto-assign tiers:

  • MUST: All POSIX-required flags (target 100%)
  • MUST: All flags present in both macOS AND OpenBSD (platform parity baseline)

Prompt user for remaining flags: Use AskUserQuestion menu per utility to decide tier for flags that are GNU-only, macOS-only, or OpenBSD-only. Present the flag, its description, and which sources have it. Let user pick SHOULD or WONT.

Tiers:

  • MUST: POSIX-required + macOS/OpenBSD parity
  • SHOULD: User-approved GNU/platform flags
  • WONT: Rare/legacy flags (document rationale)

Step 4: Integration tests

Write bash scripts in tests/posix/, one per utility (e.g., tests/posix/test_cp.sh). Each script:

  • Validates every MUST and SHOULD flag is accepted
  • Tests correct behavior against expected output
  • Does NOT compare against GNU coreutils directly
  • Run via just test-posix

TDD Development Cycle

For each utility:

  1. Red: Write failing tests for basic functionality
  2. Green: Implement minimal code to pass tests
  3. Refactor: Improve code quality while keeping tests green
  4. Repeat: Add more test cases for edge cases and flags

Implementation Order

Phase 1: Essential & Simple Utilities

1. echo ✓

  • Test: Basic text output
  • Test: No newline flag (-n)
  • Test: Escape sequences (-e)
  • Test: Multiple arguments
  • Test: Empty input
  • Test: Combined flags (-en, -ne)
  • Test: Octal sequences (\101)
  • Test: Hex sequences (\x41)
  • Implement: Basic functionality
  • Implement: Flag parsing
  • Implement: Escape sequence handling
  • Implement: --help and --version flags
  • Man page: Write concise man page with examples
echo - Additional GNU features (TDD): ✓
  • Test: -E flag disables escapes even after -e
  • Test: -E flag behavior in combined flags
  • Implement: -E flag to explicitly disable escape sequences

2. cat ✓

  • Test: Single file reading
  • Test: Multiple files concatenation
  • Test: STDIN reading
  • Test: Line numbering (-n)
  • Test: Show ends (-E)
  • Test: Show tabs (-T)
  • Test: Non-existent file error
  • Test: Number non-blank lines (-b)
  • Test: Squeeze blank lines (-s)
  • Test: Show non-printing (-v)
  • Implement: Basic file reading
  • Implement: STDIN support
  • Implement: Line numbering
  • Implement: Special character display
  • Man page: Write concise man page with examples
cat - Additional GNU features (TDD): ✓
  • Test: -A flag combines -vET behavior
  • Test: -e flag combines -vE behavior
  • Test: -t flag combines -vT behavior
  • Test: -u flag is silently ignored
  • Test: -A with control characters
  • Implement: -A (--show-all) combination flag
  • Implement: -e combination flag
  • Implement: -t combination flag
  • Implement: -u flag (no-op for POSIX)
  • Implement: Long option support (--show-all already works)

3. ls ✓ (Phases 1-5 complete)

  • Test: Basic directory listing
  • Test: Hidden files (-a)
  • Test: One file per line (-1)
  • Test: Alphabetical sorting
  • Test: Empty directory handling
  • Test: Mixed files and directories
  • Implement: Basic listing
  • Implement: Directory iteration
  • Implement: Hidden file filtering
  • Implement: Alphabetical sorting
  • Man page: Write concise man page with examples
ls - Implementation Plan (Balanced Approach)
Phase 1: Essential Features (TDD) ✓
  • Test: Long format (-l) with permissions, size, date
  • Test: stat() wrapper for file attributes
  • Test: Permission string formatting (e.g., -rw-r--r--)
  • Test: Human readable sizes (-h) with K/M/G/T
  • Test: Kilobyte sizes (-k) always in 1K blocks
  • Test: Show all files (-a) including . and ..
  • Test: Almost all (-A) excluding . and ..
  • Implement: stat() wrapper in common library
  • Implement: Permission string formatter
  • Implement: Size formatters (bytes, human, kilobytes)
  • Implement: Date/time formatter (smart: recent vs old)
  • Implement: Long format assembly
  • Implement: User/group name lookup via C interop
  • Implement: Hard link count display
  • Implement: Total blocks calculation
Phase 2: Sorting & Display Options (TDD)
  • Test: Sort by time (-t) newest first
  • Test: Sort by size (-S) largest first
  • Test: Reverse sort (-r) for any sorting mode
  • Test: File type indicators (-F) /=*@|
  • Test: Directory itself (-d) without recursion
  • Test: Symlink target display with -l
  • Implement: Modular sorting system
  • Implement: Time-based comparator
  • Implement: Size-based comparator
  • Implement: Reverse sort wrapper
  • Implement: File type detection and indicators
  • Implement: Symlink target reading and display
Phase 3: Modern UX & Color (TDD)
  • Test: Color capability detection (isatty, TERM)
  • Test: --color=auto/always/never modes
  • Test: Basic color scheme (dirs, executables, symlinks) ✓
  • Test: LS_COLORS environment variable parsing ✓
  • Test: --group-directories-first option ✓
  • Test: Terminal width detection for columns ✓
  • Test: Smart column formatting (-C is default) ✓
  • Implement: Color system with graceful degradation ✓
  • Implement: LS_COLORS parser (simplified) ✓
  • Implement: Directory grouping logic ✓
  • Implement: Responsive column layout ✓
Phase 4: Recursive & Nice-to-Have (TDD) ✓
  • Test: Recursive listing (-R) with proper formatting
  • Test: Recursive with cycle detection
  • Test: Inode display (-i) before filename
  • Test: Numeric user/group IDs (-n)
  • Test: Comma-separated output (-m)
  • Test: Single column force (-1) ✓ already done
  • Implement: Recursive directory walker
  • Implement: Symlink cycle detection
  • Implement: Inode display formatting
  • Implement: Comma-separated formatter
Phase 5: Modern Enhancements ✓
  • Test: Nerd font icon detection
  • Test: Icon mapping for common file types
  • Test: Git status integration (modified/new files)
  • Test: Smart date formatting ("2 hours ago")
  • Implement: Optional icon system
  • Implement: Git repository detection
  • Implement: Human-friendly date formatting
ls - Features We're NOT Implementing
  • SELinux context (-Z, --context) - Too Linux-specific
  • Author field (--author) - Nobody uses this
  • Emacs dired mode (-D, --dired) - Too niche
  • Complex quoting styles - Just escape when needed
  • Multiple time formats - One smart format is enough
  • Block size gymnastics (--block-size) - Just -h and -k
  • All the --indicator-style variants - Just -F
  • Explicit --si flag - We use binary (1024) for -h

4. cp ✓ (Complete implementation)

  • Test: Single file copy
  • Test: Copy to existing directory
  • Test: Error on directory without recursive flag
  • Test: Preserve attributes (-p)
  • Test: Directory copy (-r)
  • Test: Interactive mode (-i)
  • Test: Force overwrite (-f)
  • Test: Symbolic link handling (-d)
  • Test: Error cases (permission denied, disk full)
  • Implement: Basic file copying
  • Implement: Attribute preservation (mode, timestamps)
  • Implement: Copy to directory detection
  • Implement: Directory recursion
  • Implement: Symlink handling (-d/--no-dereference)
  • Man page: Write concise man page with examples

5. mv ✓

  • Test: File rename in same directory
  • Test: Move to different directory
  • Test: Directory move
  • Test: Interactive mode (-i)
  • Test: Force mode (-f)
  • Test: Cross-filesystem move
  • Test: Atomic rename when possible
  • Implement: Basic move/rename
  • Implement: Cross-filesystem support
  • Implement: Directory handling
  • Man page: Write concise man page with examples

6. rm ✓

  • Test: Single file removal
  • Test: Multiple files
  • Test: Directory removal (-r)
  • Test: Force mode (-f)
  • Test: Interactive mode (-i)
  • Test: Write-protected file handling
  • Test: Non-existent file behavior
  • Implement: Basic removal
  • Implement: Recursive removal
  • Implement: Safety checks
  • Man page: Write concise man page with examples
rm - Advanced Implementation (TDD) ✓

Phase 1: Basic File Removal

  • Test: Basic file removal
  • Test: Non-existent file with force
  • Test: Multiple file removal
  • Test: Directory without recursive flag
  • Test: Verbose output
  • Implement: Core removal logic
  • Implement: Force mode handling
  • Implement: Error reporting

Phase 2: Safety and Interaction

  • Test: Interactive mode prompts
  • Test: Force mode bypasses prompts
  • Test: Root directory protection
  • Test: Same-file detection (hard links)
  • Test: Empty path handling
  • Test: Path traversal attack prevention
  • Implement: User interaction system
  • Implement: Write-protected file prompts
  • Implement: Interactive once mode (-I)
  • Implement: Critical system path protection

Phase 3: Recursive Directory Operations

  • Test: Recursive directory removal
  • Test: Deep nested directories
  • Test: Symlink handling (don't follow)
  • Test: Permission handling with force
  • Implement: Depth-first directory traversal
  • Implement: Symlink detection
  • Implement: Permission modification for force mode
  • Implement: Inode tracking for cycles

Phase 4: Advanced Safety Features

  • Test: Symlink cycle detection
  • Test: Cross-filesystem boundary handling
  • Test: Race condition protection
  • Implement: Complex symlink cycle detection
  • Implement: Device ID tracking for filesystem boundaries
  • Implement: Atomic operations using *at() syscalls
  • Implement: File descriptor-based removal for TOCTOU protection

7. mkdir ✓

  • Test: Single directory creation
  • Test: Parent creation (-p)
  • Test: Mode setting (-m)
  • Test: Multiple directories
  • Test: Already exists error
  • Test: Permission denied
  • Implement: Basic mkdir
  • Implement: Parent directory creation
  • Implement: Permission setting (partial - chmod TODO)
  • Man page: Write concise man page with examples

8. rmdir ✓

  • Test: Empty directory removal
  • Test: Non-empty directory error
  • Test: Parent removal (-p)
  • Test: Multiple directories
  • Test: Non-existent directory
  • Test: File instead of directory error
  • Test: Verbose output (-v)
  • Test: Ignore fail on non-empty (--ignore-fail-on-non-empty)
  • Test: Parent removal stops on error
  • Test: Path traversal protection
  • Test: Symbolic link detection
  • Test: Unicode path handling
  • Test: Long path support
  • Test: Memory management (no leaks)
  • Test: Progress indicators
  • Implement: Basic removal with atomic operations
  • Implement: Parent cleanup with ParentIterator (memory-safe)
  • Implement: Verbose output with colors
  • Implement: --ignore-fail-on-non-empty flag
  • Implement: Path validation (traversal, symlinks, system paths)
  • Implement: Atomic removal with unlinkat syscall
  • Implement: Progress indicators for bulk operations
  • Man page: Write concise man page with examples

9. touch ✓

  • Test: Create new file
  • Test: Update existing file timestamp
  • Test: Specific time (-t)
  • Test: Reference file (-r)
  • Test: Access time only (-a)
  • Test: Modification time only (-m)
  • Test: -h/--no-dereference for symlinks
  • Test: --time=WORD support
  • Test: Multiple files
  • Test: -c/--no-create flag
  • Test: Timestamp parsing validation
  • Test: Error handling
  • Test: Pre-1970 date validation
  • Implement: File creation
  • Implement: Timestamp manipulation
  • Implement: Reference file support
  • Implement: Atomic operations (no race conditions)
  • Implement: Dynamic path allocation
  • Implement: Comprehensive error handling
  • Man page: Write concise man page with examples

10. pwd ✓

  • Test: Basic working directory
  • Test: Logical path (-L)
  • Test: Physical path (-P)
  • Test: Symlink resolution
  • Test: PWD environment variable validation
  • Test: Flag precedence (last flag wins)
  • Test: Security validation with inode comparison
  • Test: Output format validation
  • Implement: Basic pwd
  • Implement: Path resolution options
  • Implement: Secure PWD validation using inode comparison
  • Implement: Proper error handling with common library
  • Implement: GNU/POSIX compliant flag handling
  • Man page: Write concise man page with examples

11. chmod ✓

  • Test: Basic permission changes (numeric: 755, 644)
  • Test: Symbolic mode changes (u+x, g-w, o=r)
  • Test: Recursive mode (-R)
  • Test: Preserve root (-c, --changes)
  • Test: Error handling (permission denied)
  • Test: Special bits (setuid, setgid, sticky)
  • Implement: Numeric mode parser
  • Implement: Symbolic mode parser
  • Implement: Recursive directory walker
  • Man page: Write concise man page with examples

12. chown ✓

  • Test: Basic ownership change (user:group)
  • Test: User only change
  • Test: Group only change (:group)
  • Test: Recursive mode (-R)
  • Test: Dereference/no-dereference (-h, -H, -L, -P)
  • Test: From reference file (--reference)
  • Implement: User/group parsing
  • Implement: Ownership change syscalls
  • Implement: Recursive walker with symlink handling
  • Man page: Write concise man page with examples

13. ln ✓

  • Test: Create hard link
  • Test: Create symbolic link (-s)
  • Test: Force overwrite (-f)
  • Test: Interactive mode (-i)
  • Test: Create links in directory (-t)
  • Test: Relative symlinks (--relative)
  • Test: Error cases (cross-device hard link)
  • Implement: Hard link creation
  • Implement: Symbolic link creation
  • Implement: Path resolution for relative links
  • Implement: Path security validation
  • Man page: Write concise man page with examples

14. basename ✓

  • Test: Strip directory from path
  • Test: Strip suffix (-s, --suffix)
  • Test: Multiple paths (-a, --multiple)
  • Test: Zero delimiter (-z, --zero)
  • Test: Edge cases (/, //, no slash)
  • Implement: Path parsing logic
  • Implement: Suffix stripping
  • Implement: Multiple file handling
  • Man page: Write concise man page with examples

15. dirname ✓

  • Test: Extract directory from path
  • Test: Multiple paths
  • Test: Zero delimiter (-z, --zero)
  • Test: Edge cases (/, //, no slash, .)
  • Implement: Path parsing logic
  • Implement: Multiple path handling
  • Man page: Write concise man page with examples

16. sleep ✓

  • Test: Sleep for seconds
  • Test: Sleep for decimal seconds (0.5)
  • Test: Sleep for minutes/hours/days suffix (5m, 2h, 1d)
  • Test: Multiple time arguments (sleep 1m 30s)
  • Test: Signal handling (interruptible)
  • Implement: Time parsing with units
  • Implement: High-precision sleep
  • Implement: Signal-safe sleep
  • Man page: Write concise man page with examples

17. true ✓

  • Test: Always returns 0 exit code
  • Test: Ignores all arguments
  • Implement: Minimal implementation
  • Man page: Write concise man page

18. false ✓

  • Test: Always returns 1 exit code
  • Test: Ignores all arguments
  • Test: Produces no output
  • Test: Handles empty arguments array
  • Test: Handles many arguments
  • Implement: Minimal implementation
  • Man page: Write concise man page

19. test ✓

  • Test: File existence checks (-e, -f, -d, -r, -w, -x)
  • Test: String comparisons (=, !=, -z, -n)
  • Test: Numeric comparisons (-eq, -ne, -lt, -le, -gt, -ge)
  • Test: Logical operators (-a, -o, !)
  • Test: Complex expressions with parentheses
  • Test: Exit codes (0 for true, 1 for false, 2 for error)
  • Test: Both test and [ ] forms
  • Test: Terminal tests (-t)
  • Test: Special file tests (-p, -S, -b, -c, -L/-h)
  • Test: File size test (-s)
  • Test: Permission bit tests (-g for setgid)
  • Test: Operator precedence and negation
  • Test: Error handling for invalid expressions
  • Implement: Expression parser with proper precedence
  • Implement: File test operations (all POSIX types)
  • Implement: String and numeric comparison operations
  • Implement: Logical operators with POSIX precedence
  • Implement: Parentheses grouping support
  • Implement: Both test and [ executable forms
  • Man page: Write concise man page with examples

20. date ✓

  • Test: Display current date/time
  • Test: Custom format string (+FORMAT)
  • Test: Set date/time (-s, --set)
  • Test: Display file's date (-r, --reference)
  • Test: UTC mode (-u, --utc)
  • Test: RFC formats (--rfc-3339, --rfc-email)
  • Test: Relative dates (-d "2 days ago")
  • Implement: Format string parser (strftime-like)
  • Implement: Date parsing for various formats
  • Implement: Relative date calculations
  • Man page: Write concise man page with examples

21. env ✓

  • Test: Print current environment
  • Test: Run command with modified env (env VAR=value cmd)
  • Test: Clear environment (-i, --ignore-environment)
  • Test: Unset variables (-u, --unset)
  • Test: Change directory (-C, --chdir)
  • Test: Split string arguments (-S)
  • Implement: Environment manipulation
  • Implement: Command execution with env
  • Implement: Argument splitting parser
  • Man page: Write concise man page with examples

22. seq ✓

  • Test: Generate sequence (seq 10)
  • Test: Start and end (seq 5 10)
  • Test: Start, increment, end (seq 1 2 10)
  • Test: Floating point sequences (seq 0.1 0.1 1.0)
  • Test: Format string (-f "%03g")
  • Test: Separator (-s ", ")
  • Test: Equal width (-w)
  • Implement: Number sequence generation
  • Implement: Format string support
  • Implement: Width calculation
  • Man page: Write concise man page with examples

23. tee ✓

  • Test: Write to stdout and file
  • Test: Write to multiple files
  • Test: Append mode (-a, --append)
  • Test: Ignore interrupts (-i)
  • Test: Diagnose write errors (-p)
  • Test: Binary data handling
  • Implement: Multi-writer system
  • Implement: Signal handling
  • Implement: Error diagnosis
  • Man page: Write concise man page with examples

24. yes ✓

  • Test: Repeat "y" infinitely
  • Test: Repeat custom string
  • Test: Multiple arguments joined with space
  • Test: Performance (must be fast)
  • Test: SIGPIPE handling
  • Implement: Efficient output loop
  • Implement: Buffer optimization
  • Implement: Signal handling
  • Man page: Write concise man page with examples

25. whoami ✓

  • Test: Print effective username
  • Test: No options accepted
  • Test: Error when can't determine user
  • Implement: Get effective user ID
  • Implement: User lookup
  • Man page: Write concise man page with examples

26. id ✓

  • Test: Print all IDs (default)
  • Test: User ID only (-u, --user)
  • Test: Group ID only (-g, --group)
  • Test: All group IDs (-G, --groups)
  • Test: Names instead of numbers (-n, --name)
  • Test: Real instead of effective (-r, --real)
  • Test: Different user (id username)
  • Implement: ID retrieval syscalls
  • Implement: User/group lookups
  • Implement: Format selection
  • Man page: Write concise man page with examples

27. printf ✓

  • Test: Basic format strings (%s, %d, %f)
  • Test: Escape sequences (\n, \t, \x41)
  • Test: Width and precision (%.2f, %10s)
  • Test: Multiple arguments with reuse
  • Test: Octal/hex formats (%o, %x, %X)
  • Test: Error handling (type mismatches)
  • Implement: Format string parser
  • Implement: Type conversions
  • Implement: Escape sequence handling
  • Man page: Write concise man page with examples

28. free ✓

  • Test: Basic memory information display (total, used, free, available)
  • Test: Human readable format (-h) with K/M/G/T units
  • Test: Show swap information (default)
  • Test: Hide swap information (-s, --no-swap)
  • Test: Continuous monitoring (-c, --count with interval)
  • Test: Wide format (-w) for better readability
  • Test: Color-coded memory usage levels (green/yellow/red)
  • Test: Cross-platform support (Linux /proc/meminfo, macOS vm_stat)
  • Implement: Linux memory parsing (/proc/meminfo)
  • Implement: macOS memory info via syscalls (host_statistics64)
  • Implement: Human-readable size formatting
  • Implement: Color-coded output with terminal detection
  • Implement: Inline usage bar (parallels df's --bar)
  • Implement: Continuous monitoring with refresh
  • Man page: Write concise man page with examples

Phase 2: Text Processing Utilities

29. dd ✓

  • Test: Basic copy (if=input of=output)
  • Test: Block size (bs=1M, ibs=512, obs=4096)
  • Test: Count limit (count=100)
  • Test: Seek/skip (seek=10, skip=5)
  • Test: Conversion (conv=ucase,lcase,notrunc,sync)
  • Test: Status output (status=progress)
  • Test: Direct I/O (iflag=direct, oflag=direct)
  • Implement: Block-based I/O
  • Implement: Conversion operations
  • Implement: Progress reporting
  • Man page: Write concise man page with examples

30. realpath ✓

  • Test: Resolve to absolute path
  • Test: Canonicalize existing (-e, --canonicalize-existing)
  • Test: Canonicalize missing (-m, --canonicalize-missing)
  • Test: No symlinks (-s, --strip, --no-symlinks)
  • Test: Relative to directory (--relative-to)
  • Test: Relative base (--relative-base)
  • Implement: Path resolution
  • Implement: Symlink following
  • Implement: Relative path computation
  • Man page: Write concise man page with examples

31. readlink ✓

  • Test: Print symlink target
  • Test: Canonicalize (-f, --canonicalize)
  • Test: Canonicalize existing (-e)
  • Test: Canonicalize missing (-m)
  • Test: No newline (-n, --no-newline)
  • Test: Error on non-symlink
  • Implement: Symlink reading
  • Implement: Path canonicalization
  • Man page: Write concise man page with examples

32. mktemp ✓

  • Test: Create temporary file
  • Test: Create temporary directory (-d, --directory)
  • Test: Custom template (mktemp /tmp/test.XXX)
  • Test: Dry run (-u, --dry-run)
  • Test: Custom tmpdir (--tmpdir)
  • Test: Suffix (--suffix=.txt)
  • Implement: Secure random name generation
  • Implement: Atomic file creation
  • Implement: Template parsing
  • Man page: Write concise man page with examples

33. timeout ✓

  • Test: Basic timeout with seconds (timeout 5 sleep 10)
  • Test: Command succeeds before timeout (exit status 0)
  • Test: Command killed on timeout (exit status 124)
  • Test: Floating point durations (timeout 2.5 sleep 3)
  • Test: Time units (5s, 2m, 1h, 0.5d)
  • Test: Zero timeout disables (timeout 0 sleep 1)
  • Test: Exit status preservation (--preserve-status)
  • Test: Kill after timeout (-k 2s kills if TERM ignored)
  • Test: Custom signals (-s INT, -s KILL, -s 15)
  • Test: Foreground mode (-f) for interactive commands
  • Test: Verbose mode (-v) diagnostic output
  • Test: Command not found (exit 127)
  • Test: Command not executable (exit 126)
  • Test: Signal handling (SIGTERM, SIGKILL propagation)
  • Test: Child process handling
  • Test: Error cases (invalid duration, invalid signal)
  • Implement: Duration parser (float + units)
  • Implement: Process spawning with exec
  • Implement: Timer using setitimer or timerfd
  • Implement: Signal management and propagation
  • Implement: Foreground TTY handling
  • Implement: Exit status handling
  • Implement: Verbose diagnostic messages
  • Man page: Write concise man page with examples
timeout - Implementation Notes

Why Priority: macOS lacks timeout, causing issues in scripts/CI Key Features: Must support both simple (timeout 5 cmd) and complex (timeout -k 2s -s INT 10s cmd) usage Platform Considerations:

  • Linux: Use timerfd_create for precise timing
  • macOS/BSD: Use setitimer or kqueue timers
  • Signal handling must be robust across platforms

34. tac ✓

  • Test: Reverse file lines
  • Test: Multiple files
  • Test: Custom separator (-s, --separator)
  • Test: Separator before line (-b, --before)
  • Test: Regex separator (-r, --regex)
  • Test: Large file handling
  • Implement: Reverse line reading
  • Implement: Memory-efficient algorithm
  • Implement: Separator handling
  • Man page: Write concise man page with examples

35. nl ✓

  • Test: Number all lines (default)
  • Test: Number non-empty lines (-b a, -b t)
  • Test: Number format (-n ln, -n rn, -n rz)
  • Test: Starting number (-v 100)
  • Test: Increment (-i 2)
  • Test: Width (-w 4)
  • Test: Separator (-s ": ")
  • Implement: Line numbering logic
  • Implement: Format options
  • Implement: Section handling
  • Man page: Write concise man page with examples

36. head ✓

  • Test: Default 10 lines
  • Test: Custom line count (-n)
  • Test: Byte count (-c)
  • Test: Multiple files
  • Test: STDIN input
  • Test: File headers with multiple files
  • Implement: Line-based reading
  • Implement: Byte-based reading
  • Implement: Multi-file handling
  • Man page: Write concise man page with examples

37. tail ✓

  • Test: Default 10 lines
  • Test: Custom line count (-n)
  • Test: Follow mode (-f)
  • Test: Follow mode truncation detection
  • Test: Follow retry file rotation (-F)
  • Test: Follow retry nonexistent file (-F)
  • Test: Follow + reverse mutual exclusion
  • Test: Byte count (-c)
  • Test: Multiple files
  • Test: Reverse line reading
  • Test: Zero-terminated lines (-z)
  • Test: Files without final newline
  • Implement: Efficient line reading from end
  • Implement: Follow mode with kqueue (macOS) and inotify (Linux)
  • Implement: Follow retry with file rotation detection (-F)
  • Implement: Multi-file follow (GNU tail follows all files)
  • Implement: CircularLineBuffer for performance
  • Implement: Zero-terminated line support
  • Implement: Zig 0.15.1 Reader API migration
  • Man page: Write concise man page with examples

38. wc ✓

  • Test: Line count (-l)
  • Test: Word count (-w)
  • Test: Byte count (-c)
  • Test: Character count (-m)
  • Test: Maximum line length (-L)
  • Test: Multiple files
  • Test: STDIN input
  • Test: Unicode handling
  • Test: Default behavior (lines, words, bytes)
  • Test: File error handling
  • Implement: Efficient counting with streaming
  • Implement: Unicode support with proper character counting
  • Implement: Performance-optimized byte counting
  • Man page: Write concise man page with examples

39. sort ✓

  • Test: Basic alphabetical sort
  • Test: Numeric sort (-n)
  • Test: Reverse sort (-r)
  • Test: Key-based sort (-k)
  • Test: Unique sort (-u)
  • Test: Case-insensitive (-f)
  • Test: Memory limit handling
  • Implement: In-memory sorting
  • Implement: External merge sort
  • Implement: Key extraction
  • Man page: Write concise man page with examples

40. uniq ✓

  • Test: Remove adjacent duplicates
  • Test: Count occurrences (-c)
  • Test: Only duplicates (-d)
  • Test: Only unique (-u)
  • Test: Skip fields (-f)
  • Test: Case-insensitive (-i)
  • Implement: Line comparison
  • Implement: Counting logic
  • Implement: Field skipping
  • Man page: Write concise man page with examples

41. cut ✓

  • Test: Byte selection (-b)
  • Test: Character selection (-c)
  • Test: Field selection (-f)
  • Test: Delimiter (-d)
  • Test: Complement (-c)
  • Test: Multiple files
  • Implement: Range parsing
  • Implement: UTF-8 character handling
  • Implement: Field extraction
  • Man page: Write concise man page with examples

42. tr ✓

  • Test: Character translation
  • Test: Character deletion (-d)
  • Test: Squeeze repeats (-s)
  • Test: Complement set (-c)
  • Test: Character classes [:alpha:]
  • Test: Range expansion [a-z]
  • Implement: Translation tables
  • Implement: Unicode support
  • Implement: Character class parsing
  • Man page: Write concise man page with examples

Phase 3: File Information Utilities

43. stat ✓

  • Test: File information display
  • Test: Custom format (-c)
  • Test: Filesystem info (-f)
  • Test: Dereference (-L)
  • Test: Terse output (-t)
  • Implement: System call wrapper
  • Implement: Format string parser
  • Implement: Human-readable output
  • Man page: Write concise man page with examples

44. du ✓

  • Test: Directory size calculation
  • Test: Human readable (-h)
  • Test: Summary only (-s)
  • Test: Max depth (-d)
  • Test: Exclude patterns
  • Test: Hard link handling
  • Implement: Directory traversal
  • Implement: Size calculation
  • Implement: Caching for performance
  • Man page: Write concise man page with examples

45. df ✓

  • Test: Filesystem listing
  • Test: Human readable (-h)
  • Test: Filesystem type (-t)
  • Test: Inode information (-i)
  • Test: Mount point resolution
  • Implement: Mount point parsing
  • Implement: Space calculation
  • Implement: Filesystem filtering
  • Man page: Write concise man page with examples

Phase 4: Advanced Utilities

46. find ✓

  • Test: Name matching (-name)
  • Test: Type filtering (-type)
  • Test: Size filtering (-size)
  • Test: Time filtering (-mtime)
  • Test: Execution (-exec)
  • Test: Logical operators
  • Test: Depth control
  • Implement: Expression parser
  • Implement: Directory walker
  • Implement: Action execution
  • Man page: Write concise man page with examples

47. grep ✓

  • Test: Basic pattern matching
  • Test: Regular expressions (-E)
  • Test: Case insensitive (-i)
  • Test: Invert match (-v)
  • Test: Line numbers (-n)
  • Test: Recursive (-r)
  • Test: Binary file handling
  • Implement: Pattern compilation
  • Implement: Line matching
  • Implement: Performance optimizations
  • Man page: Write concise man page with examples

Testing Strategy

  • Coverage Goals: 90%+ line, 85%+ branch, 100% error paths
  • Unit Tests: Individual flags, combinations, edge cases
  • Integration Tests: Pipes, signals, GNU compatibility, benchmarks

Custom Argument Parser Implementation ✓

Replace zig-clap Dependency (COMPLETED)

Goal: Replace zig-clap's 3,000 lines with focused ~400-line library supporting 95% of real usage patterns

Design Philosophy:

  • API-first design with type-safe interfaces
  • Zero allocations for flag parsing (positionals may allocate)
  • Compile-time validation where possible
  • Self-documenting through struct field names
  • OpenBSD-inspired simplicity with GNU compatibility
Phase 1: Core Parsing Engine (COMPLETED) ✓
  • Test: Boolean flag parsing (-h, --help, -v, --verbose)
  • Test: Combined short flags (-abc = -a -b -c)
  • Test: Unknown flag error handling
  • Test: Flag mapping generation from struct reflection
  • Test: Memory management (no leaks)
  • Implement: Core ArgParser.parse() function with generic struct support
  • Implement: Comptime flag mapping using @typeInfo()
  • Implement: Boolean flag state management
  • Implement: ParseResult with proper cleanup
  • Implement: Error types (InvalidArgument, UnknownFlag, MissingValue)
Phase 2: String Options and Positionals (COMPLETED) ✓
  • Test: String option parsing (--color=auto, --output file)
  • Test: Both --option=value and --option value syntax
  • Test: Missing value error for string options
  • Test: Positional argument collection
  • Test: GNU -- separator handling
  • Test: Single - as positional (stdin convention)
  • Implement: String option value extraction
  • Implement: Two-pass parsing (flags first, then values)
  • Implement: Positional argument allocation and management
  • Implement: State machine for parsing stages
Phase 3: Help Generation System (COMPLETED) ✓
  • Test: Help text parsing from struct meta field
  • Test: Automatic help formatting matching GNU style
  • Test: Usage line generation with positional indicators
  • Test: Option description alignment and formatting
  • Test: Integration with existing --help flag patterns
  • Implement: printHelp() function
  • Implement: Help text parser for embedded descriptions
  • Implement: GNU-style help formatting
  • Implement: Usage line generation based on struct analysis
Phase 4: GNU Compatibility and Edge Cases (COMPLETED) ✓
  • Test: POSIX compliance for argument ordering
  • Test: Error message format matching GNU conventions
  • Test: Complex combined flags with string options
  • Test: Edge cases (empty args, only positionals, only flags)
  • Test: Integration with all existing utility patterns
  • Implement: Full GNU argument parsing compatibility
  • Implement: Comprehensive error reporting
  • Implement: Performance optimization (comptime where possible)
Migration Plan (COMPLETED) ✓
  • echo: Migrated simplest case (boolean flags only)
  • cat: Multiple boolean flags, combination flags (-A, -e, -t)
  • ls: Complex case with string options (--color, --time-style)
  • cp/mv/rm: Interactive flags and mixed option types
  • mkdir/rmdir/touch: Mode settings and timestamp options
  • All utilities: Complete migration for all 22 implemented utilities
Integration and Cleanup (COMPLETED) ✓
  • Test: Drop-in compatibility with existing utility code
  • Test: Performance benchmarks vs zig-clap
  • Test: Binary size comparison
  • Test: Compile time comparison
  • Update: build.zig to remove zig-clap dependency
  • Update: build.zig.zon to remove clap entry
  • Verify: All existing tests pass with new parser
  • Document: API documentation in argparse.zig

Success Criteria:

  • Library under 500 lines total (vs 3,000 for zig-clap)
  • 95%+ test coverage with embedded tests
  • All existing utilities work unchanged
  • Argument parsing <1ms for complex cases
  • Zero regressions in functionality
  • Binary size comparable or smaller than zig-clap

API Design Pattern:

const EchoArgs = struct {
    help: bool = false,        // -h, --help
    version: bool = false,     // -V, --version
    suppress_newline: bool = false, // -n
    positionals: []const []const u8,
    
    pub const help_text = 
        \\-h, --help     Display this help and exit.
        \\-V, --version  Output version information and exit.
        \\-n             Do not output the trailing newline.
        \\<str>...       Text to echo.
    ;
};

const args = Args.parse(EchoArgs, allocator) catch |err| switch (err) {
    error.InvalidArgument => return usage_error(),
    else => return err,
};
defer args.deinit(allocator);

Stdout Testing Infrastructure ✓

Overview

Implemented idiomatic Zig writer pattern to enable comprehensive testing of stdout/stderr output without hangs or skipped tests.

Design Principles

  • Pass writers as parameters (idiomatic Zig pattern) ✓
  • Enable full output testing without process-level complexity ✓
  • Maintain production behavior while improving testability ✓
  • Zero allocation overhead for production code ✓

Implementation Completed

Phase 1: Core Infrastructure ✓

  • Writer parameter pattern implemented across all utilities
  • Test infrastructure using buffer writers (std.ArrayList(u8).writer())
  • Stdout/stderr isolation in all utilities
  • Memory management with proper cleanup patterns

Phase 2: All Utilities Updated ✓

  • cat - printVersion, printHelp with writer parameters
  • ls - lsMain function accepting writer parameter
  • mkdir - runMkdir with stdout/stderr writers
  • rmdir - handleError returning !void for proper error propagation
  • touch - mainWithWriter accepting both writers
  • mv - Complete parameter threading for progress functions
  • ln - createSingleLink with writer parameters, test_mode support
  • cp - runCp and all sub-modules updated (errors.zig, user_interaction.zig, etc.)
  • chmod - printHelp and printVersion updated
  • chown - printHelp and printVersion updated
  • common/lib.zig - printErrorTo function added
  • echo - Already had writer support, updated for consistency
  • rm - Already had writer support, maintained
  • pwd - Already had writer support, maintained

Phase 3: Test Infrastructure ✓

  • Implemented anytype writer compatibility across all utilities
  • Verified stdout/stderr isolation in tests
  • Removed dead code buffering tests (746 lines of stdlib testing)
  • Fixed writer parameter patterns to prevent test stderr pollution

Phase 4: Pattern Documentation ✓

  • Consistent runXxx() pattern returning ExitCode
  • main() as thin wrapper calling runXxx()
  • All output functions accept writer parameters
  • Tests use buffer writers for output verification

Success Achieved

  • Zero test hangs due to stdout buffering
  • All utilities use consistent writer pattern
  • Full test coverage for output functionality
  • No performance regression (verified with timing tests)
  • Clear pattern established for future utilities

Architecture Decisions

Design Philosophy

  • Balance OpenBSD clarity with GNU usefulness
  • Modern UX improvements (colors, icons, responsive layouts)
  • Smart defaults (auto-color, readable dates, parallel I/O)

Shared Components

  • Create common library for:
    • Error handling (fatal, printError, printWarning, ExitCode)
    • Color output (Style with terminal detection)
    • Progress indicators (Progress with ETA)
    • Version/help support (CommonOpts)
    • Advanced argument parsing (using zig-clap)
    • File operations helpers (stat wrappers, permission formatting)
    • Unified file permissions (file_ops.zig - prevents macOS SIGABRT)
    • Size formatters (bytes, -k kilobytes, -h human readable)
    • Date/time formatting helpers (smart recent vs old)
    • User/group name lookup (getpwuid/getgrgid via C interop)
    • CI environment detection (isRunningInCI, shouldSkipMacOSCITest)
    • Internal stderr color detection (stderrSupportsColor in lib.zig — removed ~500 hardcoded isTty calls)
    • C time bindings (time.zig — c_tm, localtime_r, gmtime_r, strftime, mktime, TimeUnit, parseTimeString)
    • Path canonicalization (path.zig — canonicalizeMissing for non-existent path components)
    • Glob matching (glob.zig — globMatch/globMatchInsensitive with bracket expressions)
    • Interactive prompts (prompt.zig — promptYesNo for cp/mv/rm confirmation)
    • Human-readable formatting (format.zig — formatHumanReadable with SI/IEC suffixes, parseBlockSize)
    • File content copying (file_ops.zig — copyFileContents, isSameFile)
    • Terminal width detection for responsive layouts
    • Parallel I/O utilities for performance

Build System

  • Set up build.zig
  • Configure test runner
  • Common library module system
  • Integrate zig-clap dependency
  • Basic Makefile for common tasks (removed in 0.8.0)
  • justfile migration: Full parity with Makefile, now sole task runner
  • Security fixes: Replace fragile version parsing with safe ZON parser
  • Modular architecture: Metadata-driven utility configuration in build/utils.zig
  • Memory management: Fix memory leaks and add proper cleanup
  • Error handling: Replace @panic() calls with graceful error returns
  • Test coverage: Comprehensive unit tests for build system functions
  • Code quality: Pre-commit hook for automatic formatting and testing
  • Coverage system: Removed non-functional coverage system (Zig 0.15.1 lacks native coverage)
  • CI/CD pipeline: GitHub Actions workflows for cross-platform testing
  • Multi-platform releases: GitHub Actions matrix build (linux arm64/amd64, darwin arm64/amd64)
  • Release automation: release.sh extracts notes from CHANGELOG.md and updates GitHub release
  • Cachix binary cache: Explicit push via nix build --print-out-paths | cachix push
  • Weekly flake update: CI updates flake.lock and pushes fresh builds to Cachix
  • Add install targets for man pages

Documentation

  • Man page style guide (OpenBSD-inspired):
    • Concise DESCRIPTION
    • Clear OPTIONS section
    • 2-3 practical EXAMPLES
    • Brief SEE ALSO
    • No verbose explanations
  • Help text standardization (via --help flag)
  • Help text consistency test (automated checks across all utilities)
  • Man page standardization (mdoc format, consistent sections across 48 pages)
  • Design philosophy document
  • Zig patterns reference (ZIG_PATTERNS.md)
  • Standard library summary (STD_LIBRARY_SUMMARY.md)

Modern Enhancements

Color Support

  • Terminal capability detection (basic, 256, truecolor)
  • NO_COLOR environment variable support
  • VIBEUTILS_STYLE environment variable (plain/color/full)
  • Graceful fallback for limited terminals
  • Colored help output with syntax highlighting
  • Nerd Font glyphs in help and ls
  • LS_COLORS parsing and theming

Privileged Testing Strategy

Overview

Comprehensive cross-platform testing for commands that require elevated privileges (chmod, chown, etc.) across Linux, macOS, OpenBSD, FreeBSD, and NetBSD in GitHub Actions.

Platform-Specific Approaches

Linux (Best Support)

  • Tools: fakeroot, unshare (user namespaces), podman (rootless containers)
  • Strategy: Full privilege simulation without actual root
  • Coverage: 100% of privilege-related tests

macOS (Limited Options)

  • Tools: Real sudo (GitHub Actions allows), limited fakeroot
  • Strategy: Focus on error paths, use sudo for critical tests
  • Coverage: ~70% through error simulation + real sudo tests

BSD Systems (VM-Based)

  • FreeBSD: fakeroot available in ports
  • OpenBSD: Use doas for privilege testing
  • NetBSD: Basic permission testing
  • Strategy: Run in VMs via vmactions/* GitHub Actions

Commands Requiring Privileged Testing

Currently Implemented

  • rm: chmod operations on write-protected files
  • mkdir: Setting custom permissions with -m flag
  • cp: Preserving permissions/ownership with -p
  • ls: Displaying special permission bits
  • chmod: Permission modification (setuid/setgid/sticky) - tests migrated to privilege framework ✓
  • chown: Ownership changes

Planned Commands

  • ln: Hard link permission requirements
  • stat: Ownership/permission display
  • find: Permission-denied scenarios
  • du/df: Restricted directory access

Implementation Plan

1. Test Infrastructure ✓

  • Create src/common/privilege_test.zig module
  • Add platform detection (fakeroot, unshare, etc.)
  • Implement test skip annotations for unprivileged environments
  • Add mock system calls for unit testing

2. GitHub Actions Workflow ✓

  • Linux: Test with fakeroot (automated privilege simulation)
  • macOS: Native testing with privilege simulation support
  • BSD: Set up VM-based testing with vmactions (not implemented; no BSD workflow in .github/workflows/)
  • Add privileged test matrix to CI pipeline
  • Cross-platform CI/CD with Ubuntu and macOS runners
  • Coverage reporting with Codecov integration
  • Security scanning with Dependabot and CodeQL
  • Automated release workflow with multi-platform binaries

3. Test Categories

  • Permission Simulation: Test actual permission changes (infrastructure ready)
  • Error Paths: Test permission-denied handling
  • Integration Tests: Real operations in permitted locations (tests/privilege_integration/file_ops_test.zig, workflow_test.zig)
  • Mock Tests: Unit tests with injected syscalls (via requiresPrivilege)

4. justfile Targets ✓

  • test-privileged: Cross-platform privileged test runner
  • test-privileged-local: macOS with Docker fallback
  • test-linux-privileged: Linux Docker container

Fallback Strategies

  1. Test error paths (permission denied scenarios)
  2. Use dependency injection for mockable syscalls
  3. Focus on logic testing without privilege operations
  4. Document privilege requirements

Success Metrics

  • All privilege-related tests pass on Linux with fakeroot (infrastructure ready)
  • Core functionality works without privileges
  • Clear test output indicating skipped privileged tests

CI/CD Infrastructure (Implemented) ✓

GitHub Actions Workflows

  • Test Workflow (.github/workflows/test.yml)

    • Cross-platform testing (Ubuntu, macOS)
    • Unit tests and integration tests
    • Privileged test support with fakeroot
  • Integration Workflow (.github/workflows/integration.yml)

    • Full integration test suite (48 utilities)
    • Cross-platform (Ubuntu, macOS)
  • Documentation Workflow (.github/workflows/docs.yml)

    • GitHub Pages deployment
    • Man page conversion to HTML
  • Release Workflow (.github/workflows/release.yml)

    • Automated release on tag push
    • Multi-platform binary generation (4 targets)
    • GitHub Release creation with asset upload
    • Homebrew tap formula auto-update
    • Cachix binary cache push (explicit, not daemon)
  • Update Flake Workflow (.github/workflows/update-flake.yml)

    • Weekly flake.lock update (Monday 6am UTC)
    • Cachix push across 4 platforms after update
    • Manual trigger via workflow_dispatch

Supporting Infrastructure

  • Cachix Binary Cache: Prebuilt binaries for darwin-arm64, darwin-amd64, linux-arm64, linux-amd64
  • Release Script: Extracts notes from CHANGELOG.md, updates GitHub release after CI
  • Privileged Testing: Smart detection and fallback for privilege simulation
  • CI Environment Detection: Helper functions for CI-specific behavior

Modern Features Roadmap

See docs/plans/2026-03-01-modern-features-design.md for full design.

1. Colored --help Output ✓

  • Modify argparse to render colored help on TTY
  • Bold utility name and section headers
  • Cyan flag names, yellow arguments
  • Respect NO_COLOR, plain text when piped
  • Nerd-font glyphs for section headers
  • Yellow UPPERCASE metavariable highlighting in descriptions
  • Handle trailing punctuation and (s) suffixes

2. grep --color=auto

  • Highlight matched text in bold red
  • Filename in magenta, line numbers in green
  • --color=auto/always/never flags
  • Match GNU grep color conventions

3. VIBEUTILS_STYLE Environment Variable ✓

  • VIBEUTILS_STYLE=full: color, icons, git status (TTY only)
  • VIBEUTILS_STYLE=color: color only, no icons (TTY only)
  • VIBEUTILS_STYLE=plain: no color, no icons, no glyphs
  • VIBEUTILS_STYLE=always: force all features through pipes
  • Presets respect TTY detection (no ANSI leaking into pipes)
  • NO_COLOR still respected
  • Integrated in ls, grep, du, and help output
  • --color=auto checks isatty(stdout) in ls
  • df: human-readable by default (df.zig:88)
  • du: human-readable by default (currently du.zig:33 defaults human_readable = false)
  • ls -l: human-readable by default (currently ls/main.zig:27 defaults human_readable = false)
  • Explicit flags always override

3a. Command Linter Warnings ✓

  • chown: warn when argument looks like octal mode
  • chmod: warn when numeric mode contains 8 or 9
  • rm: refuse to remove '/' without --no-preserve-root
  • cp/mv: hint about -i for interactive overwrite prompts
  • ln: warn when creating dangling symlinks

3b. ls Git Status Auto-Detection ✓

  • Auto-enable git status when inside a git repo
  • --git=WHEN flag (always/auto/never)
  • Respects VIBEUTILS_STYLE (plain/color disable git)
  • Fix: suppress git status and icons in -1 mode
  • Fix: alphabetize --help flags
  • Fix: flush stderr in fatalWithWriter before exit

4. Color-Coded Numeric Output

  • df: green/yellow/red by usage percentage
  • df: optional inline usage bar
  • du: color size relative to largest entry
  • du: file-type icons before paths (--icons=WHEN)
  • wc: semantic column colors (--color=WHEN)
  • Icon coverage: 59 extensions, brand colors, dark-bg visibility

5. tree Utility

  • Recursive directory listing with box-drawing lines
  • File-type icons via common/icons
  • Truecolor/256/basic icon coloring (reuse ls pattern)
  • -L depth limit, -d directories only
  • -I pattern exclusion
  • Summary line (N directories, M files)
  • --color=auto/always/never, respect NO_COLOR
  • Man page

6. Progress Feedback for cp/mv/dd

  • Progress module in src/common/
  • Show status line on stderr after 2s delay
  • Update in place, clear when done
  • Only when stderr is a TTY

7. Smarter Error Messages

  • Permission denied with actionable hint
  • Directory not empty with rm -r suggestion

Testing Improvements (Post-Issue #5 Analysis)

The O_APPEND bug (issue #5) exposed gaps in our testing strategy. These items address the categories of testing that would have caught it — and similar bugs — earlier.

1. File Descriptor Mode Tests

  • Generic test harness that runs each binary under different fd configurations
  • Test >> file append mode for every utility
  • Test pipe mode (| cat) for every utility
  • Test truncate mode (> file) for every utility
  • Test dup'd descriptors (2>&1 >> file)

2. POSIX Behavioral Conformance Suite

  • >> must append, not overwrite
  • Stdout to a closed pipe must produce SIGPIPE/EPIPE
  • Stderr must be unbuffered
  • Exit codes conform to POSIX spec
  • Utility-agnostic: same I/O contract tests run against every binary

3. Adopt Shared TestDir Across All Utilities

  • Replace ad-hoc testing.tmpDir(.{}) usage with shared common.test_dir.TestDir in all utility tests
  • Ensure all tests use absolute paths (no fchdir)
  • Utilities to migrate: cat, chmod, chown, cut, dd, du, find, grep, head, ln, ls, mkdir, mktemp, nl, pwd, readlink, realpath, rm, rmdir, stat, tac, tail, tee, test, touch, tr, uniq, wc
  • Consolidate mv.zig's local TestDir into the shared one

4. Fix LLVM Backend Test Failures ✓

  • cp overwrite hint test fails under .use_llvm = true but passes with self-hosted backend
  • mv overwrite hint test has the same issue
  • Root cause: likely Style/writer generic instantiation differs between backends
  • Blocking accurate coverage numbers (2 of 49 binaries fail)

Resolved during the Zig 0.16 migration. build.zig:409, 434 still set use_llvm = true and zig build test is fully green, including cp.zig:1181-1276 and mv.zig:1033+ overwrite-hint tests.

5. main() Function Coverage

  • Test the writer setup code path in main(), not just runUtil() with test-provided writers
  • Integration tests that exercise the compiled binary's actual I/O initialization

6. dd MUST-tier conv= Integration Coverage

Salvaged from closed PR #34. tests/utilities/dd_test.sh lacks behavioral coverage for several MUST-tier conv= values; some existing tests also compare against macOS /usr/bin/dd, which produces empty output and silently passes.

  • Replace macOS /usr/bin/dd comparisons with hardcoded GNU-equivalent expected values
  • Add behavioral tests for conv=sync (NUL padding + full block), conv=notrunc vs. truncate contrast, conv=fsync, conv=osync, conv=ascii, conv=ebcdic, conv=ibm, conv=noerror
  • Cross-check against the existing rejection tests added in commit cc57c2a (conv=sparse/par*/files=)

Bugs

  • ls does not switch to single-column output when stdout is a pipe (POSIX violation, found 2026-04-25, tracked as #113). GNU/BSD ls auto-detect a non-tty stdout and emit one entry per line. vibeutils ls keeps multi-column layout with column-aligned padding even under a pipe, so pipelines like ls dir | grep | sort | tail see lines with embedded trailing whitespace from the alignment. This silently broke the gale upgrade script (gale-project/scripts/bootstrap.sh): the padded line 0.11.3.lock slipped past grep -v '\.lock$' because the suffix is no longer at end-of-line, then sort -V | tail -1 picked it as the "highest" version, and the script wrote that garbage into ~/.gale/gale.toml. gale-project worked around it by replacing the ls pipeline with a bash glob, but the underlying behavior is non-POSIX and surprises any tool that pipes ls. Repro:
    ls /Users/tcole/.gale/pkg/gale | grep -v '\.lock$' \
      | sort -V | tail -1 | cat -A
    # 0.11.3.lock                   $
    
    Expected (matching GNU/BSD): single-column output, no padding, the highest non-.lock entry on its own line. Spec: POSIX ls says "If the standard output is not a terminal, the default format shall be the same as the -1 option." (pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html).

Success Criteria

  • All utilities pass GNU coreutils test suite
  • 90%+ test coverage
  • Clean static analysis reports
  • Privileged operations tested (Linux, macOS)
  • CI/CD pipeline operational