Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction

This repository is a Nix Flakes-based dotfiles and system configuration, managing NixOS systems and Home Manager user environments across multiple machines.

It uses flake-parts with autowire (from jig) for automatic module discovery and composition.

Repository Structure

flake.nix                    # Entry point, declares all inputs
  → flake/*.nix              # Flake-level glue (configs, formatter, activation)
  → packs/{home,nixos}/      # Autowired packs (common, host, container, gui)
  → mixins/{home,nixos}/     # Opt-in configs (manually imported by configurations)
  → home/*.nix               # Per-user base Home Manager configurations
  → nixos/{hosts,containers} # Per-host/container NixOS configurations
  • packs/ — Autowired collections — import a pack, get everything in it
  • mixins/ — Opt-in configuration pieces (services, hardware, versions)
  • home/ — Base Home Manager configs (yjpark.nix, yj.nix)
  • nixos/ — Per-host and per-container NixOS configs
  • secrets/ — SOPS-encrypted secrets (age keys, per-host)
  • private/ — Host-specific private configs (gitignored, present on deployed machines)

Architecture

Autowiring Pattern

Pack roots use wireImportsRecursively to auto-discover all .nix files recursively:

{flake, ...}: flake.inputs.autowire.wireImportsRecursively ./.

Subdirectories with a custom default.nix are treated as opaque — their default.nix is imported instead of recursing further. Adding a new .nix file to a pack directory automatically includes it.

Layered Composition

Configuration is built up in layers:

  1. flake.nix — Declares all inputs; outputs generated via flake-parts
  2. flake/*.nix — Flake-level glue (configs, formatter, activation). Each .nix file is a flake-parts module imported by flake.nix
  3. packs/{home,nixos}/ — Autowired packs (common, host, container, gui). Import a pack, get everything in it
  4. mixins/{home,nixos}/ — Opt-in configuration pieces (services, hardware, versions), manually imported by host configs
  5. home/*.nix — Per-user base Home Manager configurations
  6. nixos/{hosts,containers}/ — Per-host and per-container NixOS configurations

Custom Options

packs/home/common/options.nix defines the me option set used throughout Home Manager modules:

  • me.username
  • me.fullname
  • me.email

These are set in each user’s base config (e.g., home/yjpark.nix).

Key Commands

Tasks are defined in mise.toml. Use mise tasks to list all available tasks.

Daily Use

# Home Manager activation (applies user-level config)
mise run _activate-home

# Build NixOS config for current host (builds without switching by default)
mise run build-host

# Switch NixOS config (applies system-level config, requires sudo)
mise run _switch-host

Flake Maintenance

# Update all flake inputs
mise run flake-update

# Update specific inputs
mise run flake-update nixpkgs home-manager

# Show flake outputs
mise run show

# Format Nix files (uses nixpkgs-fmt)
nix fmt

Documentation

# Serve docs locally (hot-reload)
mise run docs-serve

# Build static docs site
mise run docs-build

Nix Directly

# Activate Home Manager (same as mise run _activate-home)
nix run

# Build a specific package
nix build .#docs

Home Manager

User Profiles

Two user profiles exist in this configuration:

UsernameUsed OnBase ConfigState Version
yjparkPhysical hostshome/yjpark.nix25.05
yjContainershome/yj.nix26.05

Host and Container Mixins

Host-specific configurations live in:

  • mixins/home/hosts/ — One .nix file per physical host
  • mixins/home/containers/ — One .nix file per container

Adding a .nix file to either directory automatically registers a new host or container — no manual imports needed.

Activation Logic

flake/activate-home.nix defines how mise run _activate-home resolves the correct Home Manager configuration:

  1. Matches current hostname against known hosts → activates yjpark@<host>
  2. Matches current hostname against known containers → activates yj@<host>
  3. Falls back to bare <username> for unknown hosts

Configuration Generation

flake/home-configs.nix generates username@host entries for each host/container mixin, plus a bare username fallback (without host suffix). This populates homeConfigurations in the flake outputs.

Secrets

Secrets are managed with SOPS-nix using age encryption.

Setup

  • Each host has its own age key
  • Encrypted secret files live in secrets/ directories and any files matching secret.*
  • The .sops.yaml file at the repo root defines which age keys can decrypt which secrets

Usage

Encrypted files are automatically decrypted at activation time by sops-nix and made available to NixOS/Home Manager modules as paths under /run/secrets/.

Refer to the sops-nix documentation for creating and editing secrets.

Flake Inputs

All inputs are declared in flake.nix. This page documents the purpose of each.

Core / Framework

InputPurpose
nixpkgsnixos-unstable — the primary package set
home-managerUser environment management
flake-partsFlake composition framework
jiggithub:edger-dev/jig — provides autowire lib for auto-discovering and composing .nix files

Software

InputPurpose
sops-nixDeclarative secret management with SOPS + age
nixvimNeovim configured via Nix
nixos-vscode-serverVS Code remote server support on NixOS
solaarLogitech device manager
llm-agentsLLM agent tools

Desktop / UI

InputPurpose
claude-desktopClaude desktop application
niriWayland compositor
xremap-flakeKey remapper for Wayland/X11
antigravity(UI tool)
jjuiTUI for the jj (Jujutsu) VCS

Active Tasks

In Progress

No tasks

Todo

Done (4)

All Tasks

Epics

Features

Tasks

Bugs

Drafts

Epics

Container-first infrastructure (flakes-qbvb)

Migrate services to containers, isolate host, restructure Nix config.

IP Scheme

10.100.0.1       host (bridge)
10.100.0.2+      infra containers
  .002           onecli
  .003           searxng
10.100.0.100+    agent containers
  .100           yolo
  .101           spacebot
  .102           hermes
10.100.0.200+    scratch
  .200           ubuntu

Architecture

  • Host becomes thin bridge: Caddy ingress, dnsmasq, SOPS secrets, onecli-seeder
  • OneCLI moves to its own container
  • SearXNG in its own container
  • Container→host traffic blocked (except DHCP/DNS) via nftables
  • Container↔container unrestricted on bridge
  • Secret flow: Host SOPS → seeder calls OneCLI API at .002 → pushes proxy-auth/CA to agent containers
  • CA cert injection made declarative via security.pki.certificateFiles
  • Drop nixos-unified for raw flake-parts (separate host/container config namespaces)

Features

Project-wise pane configuration in Zellij (flakes-1zlj)

StatusDone · archived
TypeFeature
Prioritynormal

Configure Zellij pane/tab naming to visually identify projects in multi-project sessions.

Design

State Management

  • State file: /tmp/zellij-tab-{ZELLIJ_SESSION_NAME} — one line per pane: {PANE_ID}={project_name}
  • Session root: Capture $PWD at shell init as ZELLIJ_SESSION_PROJECT — the “home” project for the session
  • Project name: Git repo root basename (git rev-parse --show-toplevel | basename), fallback to basename $PWD

Pane Name Behavior

ConditionPane name
PWD is within session’s starting project{command} (current behavior)
PWD is in a different project<{project}> {command}
Idle (no running command)<{project}> or empty (current behavior)

Updated in fish_preexec (command starts) and on PWD change.

Tab Name Behavior

On every PWD change in any pane:

  1. Write/update own entry in the state file
  2. Read all entries, collect unique project names
  3. If only one unique project: rename-tab "{project}" (same as today)
  4. If multiple: rename-tab "{project1} | {project2} | ..."

Cleanup

  • fish_exit event: Remove own pane entry from state file, rebuild tab name
  • Shell init: Prune entries whose pane IDs are no longer in the state file

Tasks

  • Add helper to resolve project name (git root basename, fallback to basename PWD)
  • Capture session project on shell init ($ZELLIJ_SESSION_PROJECT)
  • Implement state file writes (per-pane project tracking)
  • Update pane name logic: <project> command format when outside session project
  • Update tab name logic: aggregate unique projects from state file
  • Add cleanup on fish_exit
  • Add stale entry pruning on shell init (simplified: natural overwrite on pane ID reuse)

Summary of Changes

Implemented in modules/home/programs/fish/init/zellij.fish:

  • zellij_project_name: resolves git repo root basename, fallback to basename PWD
  • ZELLIJ_SESSION_PROJECT: captured at shell init to detect foreign projects
  • State file (/tmp/zellij-tab-{SESSION}): per-pane project tracking, scoped by session name
  • Pane names: <project> command when in foreign project, just command otherwise
  • Tab names: aggregated unique projects in pane order, joined with |
  • Cleanup on fish_exit removes pane entry and rebuilds tab name

Deploy OneCLI as credential proxy for yolo container (flakes-2aqm)

StatusDone · archived
TypeFeature
Prioritynormal

Set up OneCLI (MITM proxy) on edger host to inject API keys for agents running in the yolo Incus LXC container. Agents get placeholder keys; OneCLI injects real credentials at the network layer.

Tasks

  • Create mixins/nixos/services/onecli.nix (OCI containers + seeder service)
  • Create mixins/nixos/services/secrets/onecli-secrets.txt (sops-encrypted)
  • Modify configurations/nixos/edger/imports.nix (enable onecli)
  • Modify mixins/home/ai/tools/claude-mcp-add-context7.bash (use placeholder key)
  • Modify mixins/home/host/linux/scripts/incus/incus-launch-yolo.bash (push CA cert)

context7 Rule Fix

  • Update seeder to use per-secret config (hostPattern + headerName + valuePrefix)
  • Add CONTEXT7_API_KEY entry targeting context7.com with Authorization: Bearer injection

Proxy Auth & CA Trust Fixes

  • Use agent token (aoc_ prefix) instead of user API key (oc_ prefix) for proxy auth
  • Set /etc/onecli-proxy-auth to mode 644 so non-root users can read it
  • Append OneCLI CA to existing CA bundles (handles Nix store symlinks)
  • Add fish shell proxy config via Home Manager shellInit
  • Guard onecli-seed-secrets in mise tasks for hosts without OneCLI
  • Add verbose diagnostics to onecli-check-proxy script

Summary of Changes

Fixed three root causes preventing OneCLI proxy injection in containers:

  1. Wrong API key type — gateway expects agent tokens (aoc_), not user keys (oc_)
  2. CA trust — appended OneCLI CA directly to active CA bundles instead of using security.pki (which fails at Nix build time)
  3. Fish shell — profile.d scripts aren’t sourced by fish; moved proxy var setup to Home Manager’s programs.fish.shellInit

Host Caddy LAN proxy for Incus container services (flakes-68h7)

StatusDone · archived
TypeFeature
Prioritynormal

Add host-level Caddy reverse proxy to expose Incus container services to ZeroTier LAN via *.hostname.yjpark.org with Let’s Encrypt certs (Cloudflare DNS-01). Domain pattern: yolo-8080.edger.yjpark.org → http://10.100.0.100:8080.

Summary of Changes

Modified mixins/nixos/host/incus-ingress.nix:

  • Added pkgs.caddy.withPlugins with the Cloudflare DNS plugin (hash pinned to sha256-bL1cpMvDogD/...)
  • Added Caddyfile generation: HTTPS + HTTP fallback blocks, per-container host_regexp matchers
  • Added sops.secrets."cloudflare-caddy-env" declaration pointing to ./secrets/cloudflare-caddy.txt
  • Added systemd.services.caddy.serviceConfig.EnvironmentFile for the SOPS secret path
  • Added services.firewalld.zones.public.services = ["http" "https"]

Pending user action: create mixins/nixos/host/secrets/cloudflare-caddy.txt as a SOPS-encrypted dotenv file containing CLOUDFLARE_API_TOKEN=<token>.

Incus container ingress auto-discovery (flakes-7ckd)

StatusDone · archived
TypeFeature
Prioritynormal

Caddy reverse proxy inside container that auto-discovers listening ports and serves them via hostname routing (e.g. https://3000.yolo.incus). Includes ingress and ingress-sync shell commands.

Ingress hub page: service dashboard with iframe embedding (flakes-bti9)

StatusDone · archived
TypeFeature
Prioritynormal

A hub web page served inside each container that auto-discovers running services and presents them as a navigable list with iframe embedding. Built on existing Caddy + ingress-sync infrastructure.

Design

Overview

Single hub page per container at hub.<hostname>.incus — left sidebar lists discovered services, right pane shows selected service in an iframe.

Service Discovery

Extend existing generate-ingress-config script to also produce /var/lib/ingress/services.json:

  • ss -tlnp → port + PID + process name (existing logic)
  • readlink /proc/<pid>/cwd → working directory (new)
  • Shorten cwd (strip home prefix, show last 1-2 path segments)
  • Output format:
    [{"port": 3000, "process": "node", "cwd": "my-app", "url": "https://3000.hostname.incus"}]
    
  • Hub port excluded from the list (avoid self-reference)

Hub Page (Caddy Templates)

  • Static HTML file with embedded CSS/JS, served by Caddy templates directive
  • JS fetches services.json at load time
  • Left sidebar: service list showing <short_path> <process> :<port>
  • Right pane: iframe loading selected service URL
  • Iframe failure detection → fallback “open in new tab” link

Caddy Config Changes

  • New route: hub.<hostname>.incus serving the hub HTML + services.json
  • Strip X-Frame-Options and rewrite Content-Security-Policy headers on all proxied routes (enables iframe embedding)
  • Internal TLS unchanged

Nix Integration

  • All changes in mixins/nixos/container/ingress.nix
  • Hub HTML as a Nix file/package
  • ingress-sync regenerates both Caddy config and services.json
  • ingress command unchanged

Tasks

  • Extend generate-ingress-config to read /proc/<pid>/cwd and write services.json
  • Create hub HTML template (sidebar + iframe layout, JS service loader, iframe error fallback)
  • Add Caddy route for hub.<hostname>.incus serving hub page + services.json
  • Strip X-Frame-Options/CSP headers on proxied routes
  • Test with multiple running services

Not in v1

  • Manual label overrides
  • Cross-container aggregation (host-level hub)
  • Auto-refresh on service change (manual page reload for now)
  • Service grouping/categorization

Summary of Changes

Implemented ingress hub page for container service dashboard:

  • Hub page served at hub.<hostname>.incus (internal) and <container>-hub.<host>.yjpark.org (external)
  • Service discovery via ss -tlnp with process name and working directory from /proc/<pid>/cwd
  • Sidebar + iframe layout with resizable sidebar, compact mode (icon toolbar), and service list sorted by port
  • Smart URL routing: uses https://<container>-<port>.<host>.yjpark.org (real LE certs) when accessed externally, http://<port>.<hostname>.incus internally
  • Sync button triggers generate-ingress-config via Python API, shows ingress status output in dismissable modal
  • Favicon proxy at /api/icon/<port> fetches favicons from services (tries /favicon.ico then parses HTML <link rel=icon>), falls back to colored letter icons
  • Header stripping: removes X-Frame-Options and Content-Security-Policy on proxied routes for iframe embedding
  • Host ingress: added <container>-hub route to incus-ingress.nix for external access

Files changed:

  • mixins/nixos/container/ingress.nix — hub HTML, sync API, enhanced generate-ingress-config
  • mixins/nixos/services/incus-ingress.nix — hub route for host-level Caddy

Extract ingress hub scripts for Ubuntu compatibility (flakes-d4np)

StatusDone · archived
TypeFeature
Prioritynormal

Extract scripts from mixins/nixos/container/ingress.nix into standalone files under mixins/home/container/ingress/, refactor NixOS module to reference them, and add ubuntu-setup-ingress.bash for Ubuntu container support.

Tasks

  • Extract hub-index.html from ingress.nix
  • Extract generate-ingress-config.bash
  • Extract ingress-sync-api.py
  • Extract ingress.bash (status script)
  • Extract ingress-sync.bash
  • Create mixins/home/container/ingress/default.nix (Nix packages)
  • Refactor mixins/nixos/container/ingress.nix to use shared scripts
  • Create ubuntu-setup-ingress.bash

Summary of Changes

Extracted inline scripts from the NixOS module into standalone files:

  • Scripts live in mixins/home/container/ingress/ (source of truth)
  • Copies in mixins/nixos/container/ingress-scripts/ (needed due to Nix flake autowire boundaries)
  • NixOS module refactored to use builtins.readFile on local copies
  • Home Manager module adds scripts to PATH via home.packages
  • ubuntu-setup-ingress.bash handles apt packages, systemd units, dnsmasq, resolved, sudo rules
  • All three configs (yolo, yolo-lima, home/yj) evaluate successfully

Change Zellij pane background color based on project path (flakes-dkc4)

StatusDone · archived
TypeFeature
Prioritynormal

Visually distinguish panes belonging to different projects by assigning each project a unique background color in Zellij. Builds on the project-wise pane naming from flakes-1zlj.

Design

Palette

8 subtle Gruvbox-adjacent background tints (base bg is #282828):

IndexHexTint
0#2e1a1aRed
1#1a2e1aGreen
2#1a1a2eBlue
3#2e2e1aYellow
4#2e1a2eMagenta
5#1a2e2eCyan
6#2e241aOrange
7#1a2e24Teal

Color Assignment

  • Hash project name (simple checksum) mod palette size → deterministic color index
  • Same project always gets the same color
  • Known limitation: hash collisions possible, acceptable for now

Behavior

  • Home project (ZELLIJ_SESSION_PROJECT): no color change, stays at terminal default
  • Foreign project: apply palette color via zellij action set-pane-color --bg
  • On return to home project: zellij action set-pane-color --reset
  • Applied on PWD change and shell init

Files Changed

modules/home/programs/fish/init/zellij.fish only.

Tasks

  • Add color palette array
  • Add hash function for project name → palette index
  • Add zellij_update_pane_color function
  • Integrate into PWD hook and init block
  • Reset color when returning to home project

Summary of Changes

Added to modules/home/programs/fish/init/zellij.fish:

  • ZELLIJ_PANE_COLORS: 8 subtle Gruvbox-adjacent bg tints
  • zellij_project_color_index: djb2-style hash mod palette size, returns stable integer index
  • zellij_update_pane_color: applies color for foreign projects, resets for home project
  • Called from PWD hook and init block alongside existing pane/tab name updates

Declarative incus fleet management (flakes-ihxf)

StatusTodo
TypeFeature
Prioritylow
ParentContainer-first infrastructure (flakes-qbvb)

NixOS module to declare containers (image, IP, devices, ACLs) and have them rebuild/restart on _switch-host. Long-term goal.

Zellij WASM plugin for dynamic tab naming (flakes-je55)

StatusDraft
TypeFeature
Prioritynormal

Background

We implemented project-aware tab naming in Zellij via fish shell hooks. After extensive iteration, the current approach uses zellij action dump-layout to parse pane names in visual order and compose tab names (e.g., flakes | litmus).

What works well (current fish implementation)

  • Project detection via git root basename (zellij_project_name)
  • Pane naming with <project> prefix (zellij_update_panename)
  • Deterministic pane background colors per project (zellij_update_pane_color)
  • Tab name composed from unique project names in visual order (zellij_visual_projects)
  • dump-layout parsing gives correct visual order and avoids state file race conditions

Remaining trigger limitations (fish shell can’t solve)

  • Pane moves between tabs: no fish event fires when a pane is moved — tab name only updates on next cd
  • Pane detach/reattach: splitting a pane into a new tab doesn’t trigger any shell hook
  • Non-shell panes: panes running editors, Claude, or other long-running processes never return to fish prompt
  • All-tab updates: when a pane moves, both source and destination tabs need updating — fish can only rename the current tab

Why a WASM plugin is the right approach

  • Zellij plugins receive native events: TabUpdate, PaneUpdate, ModeUpdate
  • A plugin can react to pane moves, tab changes, and layout changes in real-time
  • It can update ALL tab names (not just the focused tab) via rename_tab
  • No shell hooks needed for tab naming — the plugin handles it entirely
  • Fish hooks can focus solely on pane-level concerns (pane name, pane color)

Design considerations

  • Research Zellij plugin API for tab/pane events
  • Determine how to detect pane project (read pane name set by fish, or query cwd?)
  • Prototype plugin that listens to layout changes and renames tabs
  • Decide whether to keep fish-based pane naming or move everything to the plugin
  • Package the plugin with Nix

Reference

  • Zellij plugin docs: https://zellij.dev/documentation/plugins
  • Current fish implementation: modules/home/programs/fish/init/zellij.fish
  • Tab bar plugin already in use: ~/.config/zellij/plugins/tab-bar.wasm

Niri config: declarative host-based mixin (flakes-p2qs)

StatusDone · archived
TypeFeature
Prioritynormal

Make niri KDL config fully declarative by moving host-specific extras into per-host mixins, eliminating the manual apply-extras step.

Summary of Changes

  • Added me.niri.extraConfig option to modules/home/options.nix
  • Updated modules/flake/home-configs.nix to support directory-based host mixins (falls back to /{host}.nix if no directory exists)
  • Created mixins/home/hosts/a13/ and mixins/home/hosts/edger/ with default.nix + niri.extras.kdl
  • Rewrote niri config module to concatenate config.common.kdl + config.me.niri.extraConfig
  • Deleted extras.a13.kdl, extras.edger.kdl, and niri.justfile from old location

Add mdBook documentation site (flakes-px5o)

StatusDone · archived
TypeFeature
Prioritynormal

Create a docs/ folder using mdBook to maintain documentation about the flakes configuration. Seed initial content from CLAUDE.md, integrate with Nix flake (packages.docs, apps.docs-serve), and add mise tasks (docs-build, docs-serve).

Summary of Changes

  • Created with mdBook structure (book.toml + 6 content pages seeded from CLAUDE.md)
  • Added with (nix build) and
  • Added and mise tasks
  • Added to

Fish functions for jj workspace management (flakes-rhqy)

StatusDone · archived
TypeFeature
Prioritynormal

Convention-based jj workspace management via fish shell functions. All workspaces at ~/workspaces// with a registry file at ~/.config/workspaces.conf for mapping project names to main repo paths.

Functions

AbbrFull nameBehavior
wlworkspace-listList all workspaces across all projects with bookmark + dirty/conflict status
wworkspace-cdcd to a workspace + show brief status. Tab-completes /
wcworkspace-createFrom inside a repo, create ~/workspaces// via jj workspace add
workspace-delete(no abbr)Forget + remove a workspace

Design Details

Convention

  • All workspaces at ~/workspaces//
  • = basename of the main repo root
  • Default workspace = the main repo itself

Registry (~/.config/workspaces.conf)

  • Maps project name to main repo path (e.g. llm-triage=/home/yj/code/llm-triage)
  • Auto-populated by wc on first use
  • Needed to discover default workspace / run jj commands from the right root

workspace-list (wl)

  • Iterates all registered projects
  • For each: runs jj workspace list from main repo, then for each workspace shows:
    • Workspace name (default or feature name)
    • Path (main repo or ~/workspaces//)
    • Bookmark name (or ‘no bookmark’)
    • Change-id (short)
    • Status: clean / dirty / conflicts
  • Grouped by project

workspace-cd (w)

  • w / → cd to workspace path + print one-line status (bookmark, change-id, dirty/conflicts)
  • w /default → cd to main repo root
  • Tab completion for all / combos
  • w with no args → do nothing

workspace-create (wc)

  • Must be run from inside a jj repo
  • wc → jj workspace add ~/workspaces//
  • Auto-registers project in ~/.config/workspaces.conf if not present
  • cd to the new workspace after creation

workspace-delete

  • workspace-delete / → jj workspace forget (from main repo) + rm -rf the directory
  • No abbreviation (destructive operation)
  • Tab completion same as w

Tasks

  • Create workspace-list.fish function
  • Create workspace-cd.fish function with completions
  • Create workspace-create.fish function
  • Create workspace-delete.fish function
  • Add abbrs (wl, w, wc) to abbrs.nix
  • Wire functions into fish module via nix (autowired automatically)

Zellij per-project auto-layouts on cd (flakes-u0yw)

StatusDone · archived
TypeFeature
Prioritynormal

Spec

When cd’ing to a project directory inside Zellij, automatically open a new tab with a layout matching the project’s configuration.

Preset Layout Files

Location: modules/home/programs/zellij/layouts/ → deployed to ~/.config/zellij/layouts/

claude_terminal.kdl — claude on left (50%), terminal on right (50%)

claude_beans-terminal.kdl — claude on left (50%), right side split: beans-serve --cors-origin "*" on top, stacked terminals below

Presets have no cwd — the fish hook passes --cwd at open time, keeping presets project-agnostic.

Layout Resolution Order

  1. .zellij-layout.kdl file in project root (inline layout, highest priority)
  2. ZELLIJ_LAYOUT_{USERNAME} env var (e.g., ZELLIJ_LAYOUT_yj=claude_beans-terminal) — only if $USER matches
  3. ZELLIJ_LAYOUT env var — generic fallback
  4. Neither → do nothing

Env vars are set via .envrc (direnv), e.g.:

export ZELLIJ_LAYOUT=claude_terminal
export ZELLIJ_LAYOUT_yj=claude_beans-terminal
export ZELLIJ_LAYOUT_yjpark=claude_terminal

Fish Hook Logic

Extend existing PWD hook in modules/home/programs/fish/init/zellij.fish:

  1. Not in Zellij? → skip
  2. Resolve project root (existing git root detection)
  3. Determine layout (resolution order above)
  4. Guard: check __zellij_opened_layouts fish global var — if project root already in list → skip
  5. zellij action new-tab --layout {layout_file} --cwd {project_root}
  6. Add project root to __zellij_opened_layouts

State resets when fish session ends. Re-opening after terminal restart is acceptable.

Relationship to existing bean

Related to flakes-kxju (predefined layout files) — this is the broader feature that subsumes it.

Tasks

  • Create claude_terminal.kdl preset layout
  • Create claude_beans-terminal.kdl preset layout
  • Extend zellij.fish PWD hook with layout resolution and auto-open logic
  • Test: cd to project with ZELLIJ_LAYOUT set → zz applies layout to current tab
  • Test: stacked layout, tab/status bars, clear buffer all working
  • Test: ZELLIJ_LAYOUT_yj overrides ZELLIJ_LAYOUT for user yj
  • Test: .zellij-layout.kdl in project root takes priority (not yet tested)

Setup SearXNG search for agents (flakes-woco)

StatusDone
TypeFeature
Prioritynormal
ParentContainer-first infrastructure (flakes-qbvb)

Deploy SearXNG as a self-hosted meta-search engine to provide web search capabilities for agents (spacebot, hermes, etc.).

  • https://github.com/searxng/searxng

Goals

  • Run SearXNG as a service accessible to agent containers over the LAN
  • Provide a search API endpoint agents can call (JSON format) without external API keys
  • Keep configuration declarative via Nix

Open Questions

  • Run as NixOS system service in a dedicated incus container at 10.100.0.3
  • Which search engines to enable by default?
  • Authentication/rate-limiting for the API endpoint?
  • Integration method: MCP server, direct HTTP API, or tool wrapper?

Summary of Changes

  • Created nixos/containers/searxng/ NixOS container config:
    • Static IP 10.100.0.3, services.searxng with JSON format enabled
    • Engines: google, bing, duckduckgo, wikipedia, github
    • Listens on 0.0.0.0:8080; no auth needed (LAN-only)
    • Uses full container pack (ingress.nix auto-discovers port 8080)
  • Registered “searxng” in flake/nixos-configs.nix
  • Added searxng to incus-ingress.nix ingressContainers (10.100.0.3)
  • Added incus-launch-searxng.bash
  • JSON API: http://10.100.0.3:8080/search?q=<query>&format=json
  • Caddy: searxng-8080.<host>.yjpark.org → http://10.100.0.3:8080

Add git worktree support to workspace commands (flakes-y87y)

StatusDone · archived
TypeFeature
Prioritynormal

Extend workspace-create, workspace-list, workspace-cd, workspace-delete, and completions to support git worktree in addition to jj workspaces. Runtime VCS detection (jj priority over git). Git worktrees create new branches by default.

Summary of Changes

Added git worktree support to all workspace commands:

  • workspace-create: detects jj vs git, uses git worktree add -b for git repos
  • workspace-list: shows (jj)/(git) indicator per project, git worktrees show branch/hash/status
  • workspace-cd: shows git branch/hash/status when navigating to git worktrees
  • workspace-delete: uses git worktree remove for git repos
  • completions: lists git worktrees alongside jj workspaces
  • New helper __workspace_list_git_entry.fish for git worktree display formatting

Tasks

Disable terminal bell sound (flakes-0u0f)

StatusDone · archived
TypeTask
Prioritynormal

Disable audible bell in kitty and wezterm to prevent loud alert sounds during terminal work.

Summary of Changes

  • kitty: set enable_audio_bell = no
  • wezterm: set audible_bell = 'Disabled'

Create mise-run-or-just fish function (flakes-0ycg)

StatusDone · archived
TypeTask
Prioritynormal

Create a fish wrapper function that auto-detects whether to use mise run or just based on whether mise is configured in the current directory. Update the j abbr to use it.

Summary of Changes

  • Created : wrapper that checks [ { “path”: “/home/yj/agents/flakes/mise.toml”, “tools”: [] } ] output; if non-empty array, uses , otherwise falls back to
  • Updated line 21: →

Enhance tv-mise-tasks to handle tasks with arguments (flakes-14he)

StatusDone · archived
TypeTask
Prioritynormal

Update tv-mise-tasks fish function to detect required args via ‘mise tasks info –json | jq’ and either run directly or pre-fill command line.

Make j abbreviation expand conditionally to mise run or just (flakes-1cc9)

StatusDone · archived
TypeTask
Prioritynormal

Update fish config to use abbr –function for j so it expands inline to ‘mise run’ or ‘just’ based on current directory

Convert onecli-reseed to a manually-invoked script (flakes-2ey6)

StatusDone
TypeTask
Prioritynormal

Remove the systemd service for onecli-init-ca-and-secrets and replace with a plain onecli-reseed command. Launch is manual so systemd wantedBy/autostart causes more trouble than it’s worth.

Summary of Changes

  • Renamed initScriptreseedScript with binary name onecli-reseed
  • Added reseedScript to environment.systemPackages directly
  • Removed systemd.services.onecli-init-ca-and-secrets block entirely
  • Deleted onecli-init-ca-and-secrets.bash (was just sudo systemctl start ...)
  • Removed auto-start block from mise run _switch-host
  • Updated mise run restart-onecli to call sudo onecli-reseed directly

Tidy up the shell title when running zellij (flakes-2fpy)

StatusDone · archived
TypeTask
Prioritynormal
Tagstweaks

Objective

Configure zellij so the terminal emulator’s tab title (kitty/wezterm tab bar) shows the zellij session name instead of the verbose <cwd> | <last command with args> format zellij currently sets.

Context

When zellij runs inside a kitty or wezterm tab, it overwrites the terminal’s tab title with its own format: <current directory> | <last command with arguments>. This is too long for a tab bar and makes tabs hard to distinguish.

Fish shell’s fish_title is already configured to show just the current directory or last command name, and works correctly when zellij is not running. The problem is specifically that zellij overrides the terminal title with its own verbose format.

Requirements

  • Configure zellij to set the terminal tab title to its session name (e.g. “main”, “dev”)
  • Do not modify fish_title or other shell-level title configuration
  • Zellij’s internal pane/tab titles (within zellij’s own UI) are out of scope and can remain as-is

Acceptance Criteria

  • When zellij is running in a kitty or wezterm tab, the tab bar shows the zellij session name
  • When zellij is not running, fish_title continues to work as before (current directory or last command name)
  • No regressions in zellij’s internal tab/pane display

Summary of Changes

  • : Return empty string when inside zellij — zellij’s make_terminal_title already shows just the session name, so an empty pane title avoids duplication (was: echo $ZELLIJ_SESSION_NAME which produced .skills | .skills)
  • : Removed zellij_update_tabname_pwd (PWD event hook) and zellij_update_panename_cmd (preexec event hook) — these were driving zellij’s verbose <cwd> | <command> terminal title format. Kept zellij_update_tabname call at startup only, which sets the zellij internal tab name to the initial directory once.

Revision: New Approach (2026-03-17)

Previous approach (empty fish_title inside zellij) broke zellij’s internal tab/pane renaming.

New approach: revert fish/zellij files to original, configure kitty and wezterm to extract just the session name (before ’ | ’) from the terminal title for display.

  • Revert fish_title.fish to original
  • Revert zellij.fish to original
  • Update kitty tab_title_template to use partition(’ | ’)[0]
  • Add wezterm format-tab-title event handler

Summary of Revised Changes

  • Reverted to original (no ZELLIJ_SESSION_NAME check)
  • Reverted to original (restored and hooks)
  • Updated kitty to use — strips suffix, showing only the session name
  • Added wezterm event handler that extracts text before using Lua pattern matching

Remove stateVersion mixin pattern, use defaults instead (flakes-5pbu)

StatusDone · archived
TypeTask
Prioritynormal

Set default stateVersion in base configs, delete nearly-empty mixin files, fix fallback key mismatch in activate-home.nix

Summary of Changes

  • Added home.stateVersion = "25.05" to configurations/home/yjpark.nix
  • Added home.stateVersion = "26.05" to configurations/home/yj.nix
  • Deleted nearly-empty host mixin files: alienware-13.nix, edger.nix, hp-g1.nix, pc.nix, and containers/yolo.nix
  • Restored mixins/home/containers/.gitkeep for future use
  • Simplified mixins/home/hosts/gpd-p2.nix: removed version import, kept only incus/edger.nix import
  • No change needed to activate-home.nix (the trailing @ on fallback key is required by nixos-unified; home-configs.nix omits it correctly as nixos-unified adds it internally)

Restructure home config host/container registration (flakes-6n5b)

StatusDone · archived
TypeTask
Prioritynormal

Move host/container registration to mixins/home/hosts/ and mixins/home/containers/, update home-configs.nix and activate-home.nix accordingly

Summary of Changes

  • Created files for alienware-13, edger, hp-g1, pc (each imports 25.05 version mixin)
  • Updated to add 25.05 version import
  • Created importing 26.05 version mixin
  • Deleted
  • Rewrote : removed configDir param, mixinDir now serves both roles
  • Rewrote : reads host names from hosts/ and containers/ dirs; fixed fallback key (removed trailing @)
  • Removed version imports from configurations/home/yjpark.nix and configurations/home/yj.nix

Verified: nix eval .#homeConfigurations --apply 'x: builtins.attrNames x' returns expected keys.

Install latest beans via nix flake (flakes-6ne0)

StatusTodo
TypeTask
Prioritynormal

Add beans (edger-dev/beans) as a flake input and install it as a home-manager package, replacing or supplementing the current beans installation.

Resolve username from host/container dir in activate-home.nix (flakes-7aac)

StatusDone · archived
TypeTask
Prioritynormal

Replace flat knownHosts list with separate hosts/containers lists so activate-home.nix determines username (yjpark vs yj) from which dir the hostname is found in, rather than using $(id -un). Also update home-configs.nix fallback key to use ‘username@’ format.

Summary of Changes

  • : replaced flat knownHosts with separate hosts and containers lists; shell script now checks hosts first (→ yjpark@$_host), then containers (→ yj@$_host), falling back to $(id -un)@ only when hostname is unknown
  • home-configs.nix: updated fallback key from ${username} to "${username}@" to match new shell script format

Setup markdown-oxide (flakes-7ih3)

StatusDone · archived
TypeTask
Priorityhigh
Tagstools

For neovim, zed, vscode

Automate OneCLI CA push to containers on boot (flakes-aurl)

StatusDone · archived
TypeTask
Prioritynormal

OneCLI CA cert gets wiped from container CA bundles on reboot/rebuild. Extend onecli-seed-secrets to also push the CA, and add wantedBy=multi-user.target + after=incus.service so it runs on every boot.

Design

Problem: init-ingress-ca on yolo copies system CAs to /var/lib/ingress/ca-bundle.crt on boot, wiping the OneCLI CA that was previously appended by onecli-push-ca. This breaks all HTTPS through the OneCLI MITM proxy (nix downloads, curl, git, etc.) until someone manually runs onecli-push-ca yolo.

Solution: Extend onecli-seed-secrets on edger (host) to:

  1. Fetch OneCLI CA from http://10.100.0.1:10254/api/gateway/ca
  2. Push to each running agent container via incus file push
  3. Append to CA bundles inside the container (handling Nix store symlinks + idempotency)

Also update the systemd service:

  • Add wantedBy = ["multi-user.target"] — runs on every boot
  • Add after = [..., "incus.service"] — ensures incus is up

Files to modify:

  • mixins/nixos/services/onecli.nix — extend seeder script + service config

Known gap: Container-side nixos-rebuild switch resets CA bundles. User must re-run sudo systemctl start onecli-seed-secrets on host. Acceptable since container rebuilds are manual.

Tasks

  • Add CA push logic to seeder script in onecli.nix
  • Rename onecli-seed-secrets service to onecli-init-ca-and-secrets (systemd service + script name)
  • Add wantedBy and after incus.service to systemd service
  • Add onecli-init-ca-and-secrets shell script on host (starts the systemd service via sudo) for easy manual use
  • Update onecli-check-proxy.bash error messages to suggest running onecli-init-ca-and-secrets on the host
  • Add CA bundle verification to check script: detect broken TLS (e.g. curl to github.com fails but --noproxy works) and surface a clear diagnosis
  • Update _switch-host in mise.toml to reference new service name
  • Verify build with mise run build-host

Summary of Changes

  1. mixins/nixos/services/onecli.nix — Renamed service onecli-seed-secretsonecli-init-ca-and-secrets. Added CA push logic (fetch from API, push to containers, append to CA bundles with symlink handling + idempotency). Added wantedBy = ["multi-user.target"] and after = ["incus.service"] so it runs on every boot.
  2. mise.toml — Updated _switch-host and restart-onecli tasks to reference new service name.
  3. mixins/home/host/linux/scripts/incus/onecli-init-ca-and-secrets.bash — New host script for easy manual triggering.
  4. mixins/home/container/scripts/onecli-check-proxy.bash — Updated error messages to point to onecli-init-ca-and-secrets. Added TLS verification check that detects “proxy works but TLS fails” scenario and surfaces clear fix instructions.

Set up Incus across machines (flakes-bxl7)

StatusDone · archived
TypeTask
Prioritynormal

Set up Incus (container/VM manager) across all machines.

Tasks

  • Create mixins/nixos/services/incus.nix — Incus daemon with KVM, directory storage pool, NAT networking
  • Create modules/home/packages/incus.nix — Incus client package + fish completions
  • Create mixins/home/settings/incus/edger.nix — sample remote config for edger.yjpark.org
  • Include mixin in at least one NixOS host to test (edger)

Decisions

  • No multi-host clustering
  • Both containers and VMs (KVM enabled)
  • Directory-based storage pool
  • No shell abbreviations for now
  • macOS colima setup is a separate future task

Reference

See clarified/2026-03-15_setup-incus.md for full clarification notes.

Summary of Changes

  • : Enables incus daemon with NAT bridge network (incusbr0), directory storage pool, KVM kernel modules, and adds yjpark to the incus-admin group
  • : Installs incus client and sources fish completions via shellInit
  • : Home activation script that registers edger.yjpark.org as an incus remote (idempotent, skips if already present; manual cert trust still needed)
  • : Added incus service mixin to edger host

Auto-trigger tab completion after j abbr expands to mise run _ (flakes-c03b)

StatusDone · archived
TypeTask
Prioritynormal

Replace _j_abbr function with _j_expand fish function that handles expansion and triggers completion automatically when in a mise directory. Bind Space to _j_expand.

Summary of Changes

  • Removed abbreviation entry from (was using function)
  • Replaced function with in : detects when command line is exactly , expands to + triggers completion in mise dirs, or otherwise; falls through to normal space + abbr expansion for any other input
  • Added to bind Space to (both normal and insert/vi mode)

Migrate container IPs to new scheme (flakes-cjao)

StatusDone
TypeTask
Prioritynormal
ParentContainer-first infrastructure (flakes-qbvb)

Update static IPs: spacebot .102→.101, hermes .103→.102, ubuntu .101→.200. Update incus-ingress.nix, launch scripts, and dnsmasq config.

Summary of Changes

  • Updated : spacebot .102→.101, hermes .103→.102
  • Updated @onecli static block to point to 10.100.0.2 (anticipating OneCLI containerization)
  • Note: ubuntu container IP (.101→.200) is managed imperatively via incus config device override ubuntu eth0 ipv4.address=10.100.0.200

Drop nixos-unified, use raw flake-parts (flakes-dght)

StatusDone
TypeTask
Priorityhigh
ParentContainer-first infrastructure (flakes-qbvb)

Replace nixos-unified.lib.mkFlake with flake-parts.lib.mkFlake. Separate host and container config namespaces. Rewrite home-configs.nix and activate-home.nix to own the logic directly. Keep autowire (from jig) for module discovery.

Plan

  • Move host configs: configurations/nixos/{edger,a13,g1,p2,pc} → configurations/nixos/hosts/
  • Move container configs: configurations/nixos/{yolo,spacebot,hermes} → configurations/nixos/containers/
  • Rewrite flake.nix: use flake-parts.lib.mkFlake with explicit imports
  • Rewrite modules/flake/toplevel.nix: remove nixos-unified imports
  • Create modules/flake/nixos-configs.nix: explicit nixosConfigurations + nixosModules.default + homeModules.default + overlays
  • Rewrite modules/flake/home-configs.nix: use home-manager.lib.homeManagerConfiguration directly
  • Rewrite modules/flake/activate-home.nix: use home-manager switch –flake directly
  • Remove nixos-unified from flake inputs
  • Update mise.toml build tasks — no changes needed, output names unchanged
  • Test: nix flake check (passes — niri hash mismatch is pre-existing, unrelated)
  • Test: mise run build-host (on edger) — blocked by pre-existing niri hash issue

Summary of Changes

Completed in two commits:

  1. fee9eea - Drop nixos-unified, use raw flake-parts

    • Replaced nixos-unified.lib.mkFlake with flake-parts.lib.mkFlake
    • Separated host/container configs into configurations/nixos/hosts/ and containers/
    • Rewrote home-configs.nix, activate-home.nix to own the logic directly
    • Removed nixos-unified flake input
  2. f69f1fd - Restructure into packs/ with wireImportsRecursively

    • Introduced packs/ directory with autowired module collections
    • Added wireImportsRecursively to jig (1f1b27c)
    • Removed 28 boilerplate default.nix files
    • Merged modules/ and relevant mixins/ into packs/
    • Retained mixins/ for opt-in pieces (services, versions, storage, lan)
    • Deduplicated shared config (ai/, removed pass-through files)

Unify terminal theme to Tokyo Night (flakes-hncv)

StatusDone · archived
TypeTask
Prioritynormal

Switch wezterm from Gruvbox Dark to Tokyo Night theme, and update Zellij pane background color palette from Gruvbox-adjacent tints to Tokyo Night-adjacent tints. Kitty already uses tokyo_night_night.

Summary of Changes

  • wezterm: Changed color_scheme from Gruvbox Dark (Gogh) to Tokyo Night in mixins/home/gui/linux/wezterm/wezterm.lua
  • Zellij pane colors: Updated palette in modules/home/programs/fish/init/zellij.fish from Gruvbox-adjacent tints (base #282828) to Tokyo Night-adjacent tints (base #1a1b26)

All terminal themes now unified on Tokyo Night: kitty (tokyo_night_night), wezterm (Tokyo Night), Zellij (tokyo-night-dark), and pane background tints.

Replace autowire.nix with jig lib (flakes-iymi)

StatusDone · archived
TypeTask
Prioritynormal

Migrate from standalone autowire.nix flake input to jig’s lib.autowire. Add shim in flake.nix, rename default→wireImports, fix generic gatherFiles calls, update docs.

Summary of Changes

  • Replaced autowire.url = "github:yjpark/autowire.nix" with jig.url = "github:edger-dev/jig" in flake.nix
  • Added shim: inputs = inputs // { autowire = inputs.jig.lib.autowire; } so all existing flake.inputs.autowire.* references keep working
  • Renamed autowire.defaultautowire.wireImports in 48 default.nix files
  • Updated 3 files using generic gatherFilesgatherFiles_ (pre-applied variant)
  • Updated CLAUDE.md and docs/src/architecture.md
  • Verified with nix flake show — evaluates cleanly

Set up firewalld as NixOS service and migrate existing firewall rules (flakes-jvmx)

StatusDone · archived
TypeTask
Prioritynormal

Objective

Replace NixOS’s built-in networking.firewall with firewalld across all hosts, enabling zone-based firewall management that integrates natively with incus.

Context

The repo currently uses NixOS’s networking.firewall — a simple declarative wrapper around iptables/nftables. This works for basic port allowlisting but doesn’t support zone-based policies. With incus now in the stack (mixins/nixos/services/incus.nix), zone-based rules are a better fit:

  • Incus has built-in firewalld support — it can automatically manage zones for bridge interfaces (incusbr0), so containers/VMs get proper network isolation without manual rules.
  • Already on nftablesnetworking.nftables.enable = true is set in the incus mixin. firewalld uses nftables as its default backend, so there’s no backend conflict.
  • Current LAN rules use raw iptables — the extraCommands in mixins/nixos/lan/*/firewall.nix inject iptables rules directly, which won’t work under firewalld’s managed ruleset.
  • Zone-based model is cleaner — instead of scattering port ranges across files, interfaces get assigned to zones with appropriate policies.

Requirements

1. Enable firewalld as a NixOS service

  • Set services.firewalld.enable = true in an appropriate NixOS module
  • This automatically disables networking.firewall — both cannot be active simultaneously

2. Migrate all existing networking.firewall usages

The following files need migration:

FileCurrent rulesMigration approach
mixins/nixos/lan/my/firewall.nixOpen ports 1000-65535 for 10.0.0.0/8 (iptables)Create a zone (e.g., “lan”) with these rules, assign LAN interface
mixins/nixos/lan/cn/firewall.nixSame as aboveSame zone approach
mixins/nixos/dev/ports.nixTCP ranges 3000-3999, 8000-8999, 29000-29999Add port ranges to appropriate zone
modules/nixos/services/airplay.nixTCP 7000,7001,7100 + UDP 6000,6001,7011firewalld service definition or rich rules
modules/nixos/services/clash-verge.nixTCP ports for clashfirewalld service or zone rules
modules/nixos/services/zerotierone.nixUDP port for zerotierfirewalld service or zone rules
mixins/nixos/ext4/k3s.ext4.nixk3s TCP ports + rangesfirewalld zone for k3s
mixins/nixos/zfs/k3s.zfs.nixk3s TCP ports + rangesfirewalld zone for k3s
configurations/nixos/alienware-13/ports.nixTCP 2342 (photoprism)firewalld service or zone rule

3. Configure incus integration

  • Ensure incusbr0 bridge interface is assigned to an appropriate firewalld zone
  • Verify incus can manage its own firewall rules through firewalld without manual intervention

4. Design the zone layout

Decide on zones — at minimum:

  • public (default) — external-facing interface, restrictive
  • trusted or custom lan zone — for 10.0.0.0/8 traffic with broader access
  • incus zone — for incusbr0, managed by incus

Acceptance Criteria

  • services.firewalld is enabled and networking.firewall is no longer used
  • All previously open ports/ranges remain accessible in the correct contexts
  • LAN-scoped rules (10.0.0.0/8 broad access) work via firewalld zones instead of raw iptables
  • Incus containers/VMs have working network access through incusbr0
  • No regressions — services (airplay, clash-verge, zerotier, k3s, photoprism) remain reachable
  • nix fmt passes on all changed files

Dependencies

  • Depends on incus being configured (already done in mixins/nixos/services/incus.nix)
  • Hosts not using incus should still work with firewalld (zone config just won’t include incus zone)

Setup quartz to preview and publish oxide projects (flakes-k391)

StatusTodo
TypeTask
Prioritynormal
Tagstools

Check MCPVault, to see whether it’s a better option for the markdowns (flakes-k3pr)

StatusTodo
TypeTask
Prioritynormal

Install Zeroclaw (flakes-kj17)

StatusTodo
TypeTask
Prioritynormal

Install Zeroclaw (https://github.com/zeroclaw-labs/zeroclaw) — evaluate and set up in the environment.

Fix CA cert injection to be declarative (flakes-krtw)

StatusDone
TypeTask
Prioritynormal
ParentContainer-first infrastructure (flakes-qbvb)

Replace manual /etc/ssl/certs mutation with security.pki.certificateFiles. Seeder pushes CA to a known path, NixOS handles cert bundle integration.

Summary of Changes

  • packs/nixos/container/onecli-proxy.nix: added /var/lib/onecli/ tmpfiles dir, onecli-ca-bundle.service (oneshot, rebuilds bundle idempotently from system certs + CA), and onecli-ca-bundle.path (watches /var/lib/onecli/ca.crt, re-triggers on every push/rotation). Updated NODE_EXTRA_CA_CERTS to point to the new stable path.
  • mixins/nixos/services/onecli.nix: seeder now writes CA to /var/lib/onecli/ca.crt only — no more in-container symlink replacement or bundle appending.
  • packs/home/host/linux/scripts/incus/onecli-push-ca.bash: same simplification.

Update CLAUDE.md to reflect current state (flakes-nyvs)

StatusDone · archived
TypeTask
Prioritynormal

Fix outdated command names, module descriptions, overlays, flake inputs, and add Home Manager activation subsection

Summary of Changes

  • Fixed → On branch dev Changes not staged for commit: (use “git add …” to update what will be committed) (use “git restore …” to discard changes in working directory) modified: CLAUDE.md modified: flake.lock

Untracked files: (use “git add …” to include in what will be committed) .beans/flakes-nyvs–update-claudemd-to-reflect-current-state.md

no changes added to commit (use “git add” and/or “git commit -a”)

  • Fixed build-host description: “dry run” → “builds without switching”
  • Simplified modules/ description (removed stale subdirectory list)
  • Simplified mixins/ description (removed specific version numbers)
  • Simplified configurations/ description (removed stale “plus version and platform mixins”)
  • Fixed overlays/default.nix description: autowires from ./ not ./packages/
  • Added Desktop/UI flake inputs group: claude-desktop, niri, xremap-flake, antigravity, jjui
  • Added Home Manager Activation subsection covering yjpark/yj profiles, host/container mixin dirs, activate-home.nix logic, and home-configs.nix structure

Setup colima with incus (flakes-o04s)

StatusDone · archived
TypeTask
Priorityhigh
Tagstools

Add edit-in-place script (flakes-oh4v)

StatusDone · archived
TypeTask
Prioritynormal

Create modules/home/scripts/edit-in-place.bash to back up and replace home-manager managed symlinks with writable copies for local testing

Summary of Changes

Created modules/home/scripts/edit-in-place.bash — autowired automatically. Script backs up the symlink to .bak, removes the symlink, copies .bak back as a regular file, and sets 644 permissions.

Add GitHub token via OneCLI + container git config (flakes-oi2x)

StatusDone · archived
TypeTask
Prioritynormal

Add GitHub fine-grained token to OneCLI for transparent auth injection into yolo container. Add container-specific git config to rewrite SSH URLs to HTTPS.

Summary of Changes

  1. mixins/nixos/services/onecli.nix — Added GITHUB_TOKEN secret config with *.github.com host pattern and Authorization: token {value} injection
  2. mixins/home/container/git.nix — New file: rewrites SSH GitHub URLs to HTTPS (routes through OneCLI proxy) and sets GIT_TERMINAL_PROMPT=0
  3. mixins/nixos/services/secrets/onecli-secrets.txt — User needs to add real token via sops

Refactor ai.nix into ai/ directory (flakes-ojyn)

StatusDone · archived
TypeTask
Prioritynormal

Convert mixins/home/host/common/ai.nix into a folder (ai/), moving scripts/installs/ under ai/installs/ and extracting inline scripts into bash files.

Summary of Changes

  • Converted mixins/home/host/common/ai.nixai/ directory
  • ai/default.nix: autowire pattern for extensibility
  • ai/ai.nix: package declarations (bun, nodejs_25)
  • ai/installs/default.nix: gatherScriptPackages_bash
  • Moved scripts/installs/install-claude-mcp-context7.bash and install-claude-mcp-verena.bashai/installs/
  • Extracted inline clone-beans and install-ccline scripts into ai/installs/
  • Removed scripts/installs/ directory (now empty)

Configure jjui theme for readability with Pencil Dark terminal theme (flakes-p7hc)

StatusDone · archived
TypeTask
Prioritynormal

Add settings.ui.colors overrides to programs.jjui in modules/home/programs/jujutsu.nix to fix readability issues with the Pencil Dark (Gogh) WezTerm color scheme. The default dark theme uses ‘bright black’ for dimmed text and selected backgrounds, which is too dark/invisible in Pencil Dark.

Summary of Changes

Added settings.ui.colors overrides to programs.jjui block in modules/home/programs/jujutsu.nix. Key fixes:

  • dimmed: "bright black""#808080" (mid-gray, readable in Pencil Dark)
  • selected / revisions details selected bg: "bright black""#3a3a3a"
  • revset completion bg: "black""#1a1a1a"
  • revset completion dimmed: same fix as dimmed

Config verified at ~/.config/jjui/config.toml after just activate-home.

Unify incus container image build tasks (flakes-p8hf)

StatusDone
TypeTask
Prioritynormal

Replace per-container build-image/build-metadata/build-and-import tasks with a single parameterized task that builds image+metadata and imports directly without staging in images/

Summary of Changes

Replaced 9 per-container tasks (build-yolo-image, build-yolo-metadata, build-and-import-yolo, and equivalents for spacebot/hermes) with a single mise run build-container <name> task.

  • Uses usage field with KDL choices for shell auto-complete (covers all 5 containers)
  • Builds metadata + image sequentially, resolves nix store paths directly from result symlink
  • Pipes both tarballs straight to incus image import — no images/ staging directory needed
  • Removed images/ directory entirely

Setup OpenCode and Claude for spacebot container (flakes-pr3i)

StatusDone
TypeTask
Prioritynormal

Configure OpenCode with the claude-code-plugin (github:unixfox/opencode-claude-code-plugin) in the spacebot incus container, enabling Claude as a coding assistant within spacebot’s environment.

Summary of Changes

  • Added opencode-claude-code-plugin flake input (github:unixfox/opencode-claude-code-plugin, flake=false)
  • Updated mixins/home/containers/spacebot.nix:
    • Added llm-agents.opencode and llm-agents.claude-code to packages
    • Added xdg.configFile."opencode/plugins/claude-code" pointing to plugin source
  • Plugin placed at ~/.config/opencode/plugins/claude-code for OpenCode to load
  • Also fixed minor bug in spacebot-restart (was calling spacebot-restart instead of spacebot-status)

Integrate Home Manager as a NixOS module (flakes-rg27)

StatusDone · archived
TypeTask
Prioritynormal

Create modules/nixos/settings/home-manager.nix to import home-manager as a NixOS module so nixos-rebuild switch handles both system and home config in one command.

Summary of Changes

Created modules/nixos/settings/home-manager.nix which:

  • Imports home-manager.nixosModules.home-manager
  • Sets useGlobalPkgs = true and useUserPackages = true
  • Passes extraSpecialArgs with the flake argument so home modules get their expected {flake, ...} argument
  • Wires home-manager.users.yjpark to import configurations/home/yjpark.nix plus any host-specific mixin from mixins/home/hosts/<hostname>.nix

The module is auto-included in all NixOS hosts via the autowired modules/nixos/settings/ directory. Verified with nix flake check and just build-host — home-manager generation is now built as part of the NixOS system build.

Migrate from just to mise for task running (flakes-rg2j)

StatusDone · archived
TypeTask
Prioritynormal

Add mise.toml files and shell abbreviations to migrate task running from just to mise. Keep justfiles intact during transition.

Summary of Changes

  • Created at repo root with all 12 tasks from the main justfile
  • Created with task
  • Created with 4 preset tasks (update-presets + 3 individual)
  • Added and abbreviations to fish () and nushell ()
  • Justified files remain intact for the transition period
  • All tasks verified working via mise tasks and mise run vcs-status

Full jjui theme with terminal-independent hex colors (flakes-sk2r)

StatusDone · archived
TypeTask
Prioritynormal

Replace the partial Pencil Dark fix with a complete theme using only hex/ANSI256 colors (no ANSI 0-15) so it looks good on any dark terminal.

Summary of Changes

Replaced partial Pencil Dark fix with a complete One Dark-inspired theme in modules/home/programs/jujutsu.nix. Covers all 60+ color keys: core, flash, confirmation, help, revisions list/details, revset/completion, status, menu, picker, oplog, evolog, rebase/squash/duplicate/revert/set_parents, input, choose. All colors use explicit hex values — no ANSI 0-15 — so the theme is terminal-agnostic.

Containerize OneCLI (flakes-t9u2)

StatusDone
TypeTask
Prioritynormal
ParentContainer-first infrastructure (flakes-qbvb)

Move OneCLI + postgres from podman-on-host to a dedicated incus container at 10.100.0.2. Update seeder to target container IP. Convert to NixOS service with local postgres (no more podman-in-podman).

Summary of Changes

  • Created nixos/containers/onecli/ with NixOS config:
    • Static IP 10.100.0.2, native postgresql, podman onecli image with –network=host
    • Selective imports (skips ingress.nix and onecli-proxy.nix)
  • Registered “onecli” in flake/nixos-configs.nix
  • Updated mixins/nixos/services/onecli.nix: removed podman setup, now just the seeder pointing to 10.100.0.2
  • Updated packs/nixos/container/onecli-proxy.nix: reference 10.100.0.2
  • Updated all launch/utility scripts: spacebot .102→.101, hermes .103→.102, ubuntu .101→.200, onecli scripts 10.100.0.1→10.100.0.2
  • Rewrote onecli-reset-db.bash to use incus exec instead of podman
  • Added incus-launch-onecli.bash

Inhibit idle/sleep during audio/video playback (flakes-va02)

StatusDone · archived
TypeTask
Prioritynormal

Add sway-audio-idle-inhibit to prevent hypridle from powering off monitors when audio is playing (e.g. YouTube, Netflix in Chrome). Changes: add package to hypridle.nix and spawn at niri startup.

Summary of Changes

  • Added sway-audio-idle-inhibit package to mixins/home/gui/linux/services/hypridle.nix
  • Added spawn-at-startup "sway-audio-idle-inhibit" to niri config (config.common.kdl)

The daemon monitors PipeWire/PulseAudio for active audio streams and sends a Wayland idle inhibit signal, preventing hypridle from powering off monitors during video/audio playback.

Dynamic per-host Home Manager configs via flake module (flakes-vaiq)

StatusDone · archived
TypeTask
Prioritynormal

Create home-hosts.nix flake module to auto-generate homeConfigurations for all NixOS hosts, with optional host mixins. Delete per-host config files.

Summary of Changes

  • Created modules/flake/home-hosts.nix: dynamically generates homeConfigurations for all NixOS hosts by reading configurations/nixos/ dirs, with optional per-host mixins from mixins/home/hosts/<host>.nix
  • Created mixins/home/hosts/gpd-p2.nix: imports incus/edger mixin only for gpd-p2
  • Updated modules/flake/activate-home.nix: adds fallback to plain yjpark config when hostname isn’t in known NixOS hosts
  • Deleted all per-host configurations/home/yjpark@<host>.nix files (pc, edger, alienware-13, hp-g1, gpd-p2)
  • Key fix: used lib.mkForce on whole legacyPackages attrset (not just homeConfigurations sub-key) to override autoWire’s perSystem definition

Container-to-host network isolation (flakes-x821)

StatusDone
TypeTask
Prioritynormal
ParentContainer-first infrastructure (flakes-qbvb)

Add nftables INPUT rules on incusbr0 to block container→host traffic except DHCP (67/68) and DNS (53/5354). Container↔container traffic via FORWARD chain stays unrestricted.

Summary of Changes

  • Updated packs/nixos/host/incus.nix: removed target = "ACCEPT" from incus firewalld zone
  • Added explicit services: “dhcp” (UDP 67) and “dns” (TCP/UDP 53) for container→host DHCP/DNS
  • Added ports 5354 TCP/UDP for custom dnsmasq DNS
  • Container↔container traffic via FORWARD chain is unaffected (bridge forwarding)

Add rtk-rewrite.sh hook to claude module with home-manager linking (flakes-y887)

StatusDone · archived
TypeTask
Prioritynormal

Add the rtk-rewrite.sh hook file to modules/home/programs/claude/hooks/ and set up home.file linking to ~/.claude/hooks/rtk-rewrite.sh

Summary of Changes

  • Created modules/home/programs/claude/hooks/rtk-rewrite.sh (copied from ~/.claude/hooks/rtk-rewrite.sh)
  • Created modules/home/programs/claude/hooks/default.nix linking it to ~/.claude/hooks/rtk-rewrite.sh with executable=true
  • Autowire in claude/default.nix picks up the new hooks/ subdirectory automatically — no other files changed

Replace CopyQ with cliphist (Wayland-native clipboard manager) (flakes-yyox)

StatusDone · archived
TypeTask
Prioritynormal

Replace CopyQ (XWayland) with cliphist for Wayland-native clipboard history. Adds fuzzel picker keybinding, television cable channel, and fish function.

Summary of Changes

  • Deleted mixins/home/gui/linux/services/copyq.nix (removed CopyQ with forceXWayland)
  • Created mixins/home/gui/linux/services/cliphist.nix (enables cliphist service)
  • Added Mod+V keybinding in niri config to open fuzzel clipboard history picker
  • Added xdg.configFile for television cable channel in modules/home/programs/television.nix
  • Created modules/home/programs/fish/functions/clip.fish for tv-based clipboard selection
  • Added tc abbreviation in modules/home/programs/fish/abbrs.nix

Add mdbook-beans tasks section to docs (flakes-zvh8)

StatusDone · archived
TypeTask
Prioritynormal

Integrate mdbook-beans preprocessor into the flakes documentation, mirroring the litmus project setup. Adds kanban and all-tasks pages.

Summary of Changes

  • Added mdbook-beans flake input to flake.nix
  • Updated docs/book.toml with beans preprocessor config and sidebar CSS
  • Created docs/src/beans/tasks.md (all tasks) and docs/src/beans/kanban.md (active tasks)
  • Copied docs/src/beans-sidebar.css from litmus for bean styling
  • Updated docs/src/SUMMARY.md with Kanban and All Tasks links
  • Updated modules/flake/docs.nix to include mdbook-beans and .beans data in build
  • Updated mise.toml docs tasks to use nix (ensuring mdbook-beans is available)

Bugs

Fix Ctrl+Shift+C in wezterm clobbering zellij clipboard (flakes-5oyz)

StatusDone · archived
TypeBug
Prioritynormal

Copy (to system clipboard) doesn’t work when using wezterm → incus shell → zellij. Root cause: Ctrl+Shift+C runs CopyTo(‘Clipboard’) which copies empty terminal selection, overwriting what zellij put in clipboard via OSC 52. Fix: only copy when there’s an actual selection.

Summary of Changes

Changed binding in from a direct action to a callback that first checks if there’s an actual terminal selection. Only copies when selection is non-empty, matching kitty’s behavior and preventing the clipboard from being clobbered when zellij has already set it via OSC 52.

Auto-restart firewalld when zone config changes (flakes-ja9k)

StatusTodo
TypeBug
Prioritynormal

NixOS services.firewalld module doesn’t restart/reload the firewalld service when zone config changes, so switch-host applies new XML but the running daemon keeps old rules until manually restarted.

Context

Discovered while debugging ICMP/ping access (commits 84638b0, 235381f). After running mise run _switch-host with new services.firewalld.zones.lan settings (added protocols = ["icmp"] and extra source range), the active runtime config from firewall-cmd --zone=lan --list-all still showed the old rules. Manual sudo systemctl restart firewalld was required.

Investigation

  • Confirm root cause: check whether nixpkgs services.firewalld module sets restartTriggers / reloadTriggers on the systemd unit when zone XML or settings change
  • Decide between restart vs reload (firewall-cmd --reload is non-disruptive and is likely what we want)
  • Check if upstream nixpkgs already has an open issue/PR

Implementation

  • Add a fix in packs/nixos/common/settings/firewalld.nix — likely a systemd.services.firewalld.reloadTriggers referencing the generated zone config files, or a small activation script that runs firewall-cmd --reload when config changes
  • Test by editing a zone (e.g. add a port), running _switch-host, and verifying firewall-cmd --zone=… --list-all reflects the change without manual intervention
  • If a clean fix exists, consider upstreaming to nixpkgs

Fix mise.toml var args bug (flakes-m3r8)

StatusDone · archived
TypeBug
Prioritynormal

Remove unused args and fix the var=true arg to be optional (default=‘’) in mise.toml

Summary of Changes

  • : removed unused — task never needed extra args
  • : changed to so it’s optional
  • : removed unused trailing
  • : removed unused trailing

Fix git push auth inside Incus container via OneCLI proxy (flakes-nz9y)

StatusDone · archived
TypeBug
Prioritynormal

git push inside the container failed with ‘could not read Username for https://github.com: terminal prompts disabled’. Two root causes were identified and fixed.

Summary of Changes

Problem

git push inside the Incus container failed with:

fatal: could not read Username for 'https://github.com': terminal prompts disabled

The OneCLI MITM proxy was correctly configured and the proxy was being used, but two issues prevented authentication from working.

Root Cause 1: gh credential helper override

Home Manager’s programs.gh module auto-registers gh auth git-credential as a git credential helper for github.com. The lib.mkForce "" in git.nix cleared the helper list, but gh re-added its helper after the clear. Git would call gh auth git-credential, which tried the placeholder GH_TOKEN=onecli-managed, failed, then fell back to terminal prompt.

Fix: programs.gh.gitCredentialHelper.enable = false in mixins/home/container/git.nix

Root Cause 2: Wrong auth format for GitHub’s git HTTP endpoint

OneCLI was injecting Authorization: token <PAT> which works for GitHub’s REST API (api.github.com) but NOT for GitHub’s git smart HTTP endpoint (github.com). The git endpoint requires Basic auth: Authorization: Basic base64(x-access-token:<PAT>).

Fix: Added encoding = "basic-auth" field to GITHUB_TOKEN secret config in mixins/nixos/services/onecli.nix. The seeder script base64-encodes x-access-token:<value> when this encoding is set, and the valueFormat was changed to Basic {value}.

Key diagnostic commands

  • GIT_CURL_VERBOSE=1 git push — revealed git wasn’t sending Proxy-Authorization (fixed by http.proxyAuthMethod = basic)
  • OneCLI gateway logs (podman logs onecli) — confirmed MITM + injection was happening but GitHub returned 401
  • Certificate issuer in TLS handshake — confirmed OneCLI CA vs real cert (MITM vs tunnel)

Files modified

  • mixins/home/container/git.nix — disabled gh credential helper, removed extraHeader workaround, added proxyAuthMethod = basic
  • mixins/nixos/services/onecli.nix — changed GITHUB_TOKEN to Basic auth format with base64 encoding at seed time

Pass currentSystem to NixOS-integrated home-manager extraSpecialArgs (flakes-sytx)

StatusDone
TypeBug
Priorityhigh

nixos-rebuild on g1 fails with infinite recursion in packs/home/host because the NixOS-integrated home-manager module (packs/nixos/common/settings/home-manager.nix) doesn’t pass currentSystem via extraSpecialArgs. Standalone home configurations get it via flake/home-configs.nix but NixOS hosts that use home-manager.users.* don’t.

Summary of Changes

Updated packs/nixos/common/settings/home-manager.nix to:

  • Take pkgs as module argument
  • Pass currentSystem = pkgs.stdenv.hostPlatform.system via extraSpecialArgs

This mirrors what flake/home-configs.nix already does for standalone home configurations. The integrated home-manager NixOS module evaluates packs/home/host (via home/yjpark.nix imported through packs/nixos/host/yjpark.nix), and that module reads currentSystem in its imports to conditionally include the linux subdirectory.

Verified: g1 evaluation now progresses past the recursion point (fails only on an unrelated network fetch of Smithay/smithay.git).

Drafts

Zellij WASM plugin for dynamic tab naming (flakes-je55)

StatusDraft
TypeFeature
Prioritynormal

Background

We implemented project-aware tab naming in Zellij via fish shell hooks. After extensive iteration, the current approach uses zellij action dump-layout to parse pane names in visual order and compose tab names (e.g., flakes | litmus).

What works well (current fish implementation)

  • Project detection via git root basename (zellij_project_name)
  • Pane naming with <project> prefix (zellij_update_panename)
  • Deterministic pane background colors per project (zellij_update_pane_color)
  • Tab name composed from unique project names in visual order (zellij_visual_projects)
  • dump-layout parsing gives correct visual order and avoids state file race conditions

Remaining trigger limitations (fish shell can’t solve)

  • Pane moves between tabs: no fish event fires when a pane is moved — tab name only updates on next cd
  • Pane detach/reattach: splitting a pane into a new tab doesn’t trigger any shell hook
  • Non-shell panes: panes running editors, Claude, or other long-running processes never return to fish prompt
  • All-tab updates: when a pane moves, both source and destination tabs need updating — fish can only rename the current tab

Why a WASM plugin is the right approach

  • Zellij plugins receive native events: TabUpdate, PaneUpdate, ModeUpdate
  • A plugin can react to pane moves, tab changes, and layout changes in real-time
  • It can update ALL tab names (not just the focused tab) via rename_tab
  • No shell hooks needed for tab naming — the plugin handles it entirely
  • Fish hooks can focus solely on pane-level concerns (pane name, pane color)

Design considerations

  • Research Zellij plugin API for tab/pane events
  • Determine how to detect pane project (read pane name set by fish, or query cwd?)
  • Prototype plugin that listens to layout changes and renames tabs
  • Decide whether to keep fish-based pane naming or move everything to the plugin
  • Package the plugin with Nix

Reference

  • Zellij plugin docs: https://zellij.dev/documentation/plugins
  • Current fish implementation: modules/home/programs/fish/init/zellij.fish
  • Tab bar plugin already in use: ~/.config/zellij/plugins/tab-bar.wasm