Compare commits

...

39 Commits

Author SHA1 Message Date
rust
41bd72fc40 chore: add Gas Town directories to gitignore
Added .runtime/, .claude/, and .logs/ to gitignore for Gas Town polecat workspace.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 18:20:24 -08:00
2cdc15163c fix(flake): apply claude-code overlay to all platforms
Some checks failed
CI / check (push) Failing after 2m17s
The custom claude-code overlay (for GCS-based builds) was only being
applied to darwinModules. Extract to shared customUnstableOverlays and
apply to nixosModules and nixosModulesUnstable as well.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 17:35:14 -08:00
a77b1230fe update beads
Some checks failed
CI / check (push) Failing after 4m50s
2026-01-21 15:15:39 -08:00
623a387127 flake: update gastown to a069ff34 (rebased on upstream)
Some checks failed
CI / check (push) Failing after 4m9s
Rebased local patches onto 45 new upstream commits.

Executed-By: mayor
Role: mayor
2026-01-20 22:19:45 -08:00
737f2b09e4 chore(flake): update gastown to gitea fork with timeout fix
Some checks failed
CI / check (push) Failing after 4m16s
Point gastown input to local Gitea fork which includes:
- Increased ClaudeStartTimeout from 60s to 120s
- Fixes intermittent refinery/polecat startup timeouts

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 10:34:01 -08:00
cddc9de14a chore(deps): lock file maintenance
All checks were successful
CI / check (push) Successful in 6m18s
2026-01-19 20:15:34 -08:00
53e3bbe78f fix(claude-code): preserve bun appended bundle during NixOS build
All checks were successful
CI / check (push) Successful in 3m32s
Bun standalone executables store their JavaScript code by appending it
after the ELF sections, marked with "---- Bun! ----". The standard Nix
build process was corrupting this:

- autoPatchelfHook rewrites the entire ELF, losing appended data
- strip removes data after ELF sections
- patchelf shrink-rpath also rewrites the ELF

Fix by:
- Using dontStrip and dontPatchELF to skip automatic fixup
- Manually running patchelf --set-interpreter which modifies in-place
  without rewriting the entire file structure

This restores the binary from 99MB (bare bun runtime) to 220MB (full
claude-code application).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

Executed-By: mayor
Role: mayor
2026-01-19 10:39:58 -08:00
c258eafe34 fix: apply claude-code overlay to NixOS modules
All checks were successful
CI / check (push) Successful in 4m11s
The custom claude-code package (from GCS) was only being applied to
darwinModules, causing NixOS systems to use the older version from
nixpkgs-unstable instead of the updated version from packages/claude-code.

Extract claudeCodeOverlay as a shared definition and apply it to all
module sets: nixosModules, nixosModulesUnstable, and darwinModules.

Executed-By: mayor
Role: mayor
2026-01-19 10:28:11 -08:00
03d0b76f97 feat: switch gastown input to local Gitea fork
All checks were successful
CI / check (push) Successful in 5m9s
Fork includes mayor startup protocol fix for escalation checking.
2026-01-19 08:58:23 -08:00
b5f7233214 ci: Use semver tag for gitea-actions/nix-setup
All checks were successful
CI / check (push) Successful in 3m21s
Switch from @main to @v1 for stability. Major version tag auto-updates
to latest v1.x.x while avoiding breaking changes.

Closes: nix-7zf
2026-01-18 17:54:24 -08:00
1203662237 feat(home/development): add sqlite3 package
Some checks failed
CI / check (push) Has been cancelled
2026-01-18 08:13:16 -08:00
6ad714b57c chore(beads): remove redirect-mode remnant files
All checks were successful
CI / check (push) Successful in 4m29s
These files should not exist in repos using redirect mode.
The beads data lives in the redirect target instead.
2026-01-17 14:55:19 -08:00
5440214295 chore(claude-code): update to v2.1.12
All checks were successful
CI / check (push) Successful in 4m33s
2026-01-17 13:14:18 -08:00
cc305af899 feat(dev): add gastown multi-agent workspace manager
- Add gastown flake input (non-flake, source only)
- Build gastown package using buildGoModule in development role
- Configure renovate for daily updates of gastown and beads
- Binary: gt (Gas Town CLI by Steve Yegge)
2026-01-17 13:14:12 -08:00
c06adec7d8 feat(dev): add systemd timer for beads gate check
All checks were successful
CI / check (push) Successful in 3m8s
Add periodic timer (every 5 min) that runs `bd gate check --type=timer`
across all beads workspaces with running daemons.

This enables self-scheduling molecules - workflows that can set timer
gates to schedule their own future execution (e.g., watchers that scan
Slack every 8 hours).

The timer:
- Only runs on Linux (uses systemd user services)
- Discovers workspaces via `bd daemon list`
- Silently skips if no beads daemons are running

Related: nixos-configs-1rk.2 (Time beads scheduling mechanism)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 09:23:25 -08:00
7903b2dfd0 refactor(dev): restructure Claude commands/skills directories
All checks were successful
CI / check (push) Successful in 3m16s
Correct terminology mismatch:
- Rename skills/ to commands/ (these are user-invokable commands)
- Create new skills/ for reference materials
- Move bd_workflow.md to skills/ (it's reference material)
- Add micro-skills and formulas directories
- Update default.nix to install both commands and skills

Commands → ~/.claude/commands/ (invokable as /command-name)
Skills → ~/.claude/commands/skills/ (reference materials)
Formulas → ~/.beads/formulas/ (workflow templates)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 17:16:55 -08:00
f472aa9b3d feat(skills): add bd-workflow CLI reference skill
All checks were successful
CI / check (push) Successful in 3m23s
Comprehensive bd CLI reference covering:
- Core commands (create, update, close, show, list)
- Dependency management (bd dep add, bd blocked)
- Formula/molecule workflow (pour, wisp, cook, gates)
- When to use bd vs TodoWrite

Complements existing beads_workflow.md which covers
philosophy and humanlayer integration patterns.

Closes: nixos-configs-6pk

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 17:01:07 -08:00
2e07454ffa fix(dev): update beads flake input with vendorHash override
All checks were successful
CI / check (push) Successful in 4m36s
Temporary workaround for upstream beads vendorHash mismatch.
2026-01-15 16:49:02 -08:00
daf963b290 chore(beads): gitignore sync state files 2026-01-15 16:48:56 -08:00
c3c8688f31 fix(common): make ghostty.terminfo Linux-only
All checks were successful
CI / check (push) Successful in 3m13s
2026-01-15 15:36:03 -08:00
1cee1cd365 Enable mcrcon wrapper in gaming home env
All checks were successful
CI / check (push) Successful in 3m29s
2026-01-14 15:58:27 -08:00
66c27da142 chore(deps): update actions/checkout action to v6
All checks were successful
CI / check (push) Successful in 3m24s
2026-01-14 15:43:36 -08:00
7d6f71f4e4 chore(config): migrate config renovate.json
Some checks failed
CI / check (push) Has been cancelled
CI / check (pull_request) Successful in 3m11s
2026-01-14 23:42:20 +00:00
7091ee3ad5 renovate: add git author
Some checks failed
CI / check (push) Has been cancelled
2026-01-14 15:40:01 -08:00
d78e089695 fix(renovate): Add Gitea workflow detection and prevent dashboard autoclose
All checks were successful
CI / check (push) Successful in 3m3s
2026-01-14 15:26:22 -08:00
28b7a0fda9 feat: Add Renovate configuration for dependency tracking
Some checks failed
CI / check (push) Has been cancelled
2026-01-14 15:12:32 -08:00
b7bccb0b40 feat(parallel_beads): Enhanced validation reporting in PR descriptions
Some checks failed
CI / check (push) Has been cancelled
CI / check (pull_request) Successful in 3m14s
- Added ERROR status for execution failures (command not found, permission error)
- Added status definitions: PASS, FAIL, SKIP, ERROR with clear criteria
- Restructured PR template with three validation sections:
  - Automated Checks: table of executed checks with status
  - Manual Verification Required: unchecked boxes from plan
  - CONTRIBUTING.md Compliance: extracted requirements with verification status
- Added instructions to extract manual verification items from plans
- Enhanced CONTRIBUTING.md extraction to track automated vs manual requirements
- Updated validation summary format to include error count
2026-01-14 15:04:16 -08:00
2d03714934 feat(skills): Add contribution guidelines check to beads skills
All checks were successful
CI / check (push) Successful in 2m57s
2026-01-14 14:26:17 -08:00
3f0e381de2 fix(ci): Add access token for private flake inputs
Some checks failed
CI / check (push) Has been cancelled
2026-01-14 14:25:47 -08:00
1d9fd0aee9 feat(skills): Add batch research+plan skill for multiple beads
Some checks failed
CI / check (push) Has been cancelled
2026-01-14 14:24:53 -08:00
16f6dfcec7 feat(skills): Enforce worktree/branch workflow in parallel_beads
Some checks failed
CI / check (push) Has been cancelled
2026-01-14 14:24:16 -08:00
90ef70eb2e Add mcrcon-rbw wrapper for Minecraft RCON
Some checks failed
CI / check (push) Has been cancelled
Wrapper that auto-authenticates via rbw (Bitwarden) for RCON access.
- Uses minecraft-rcon entry from Bitwarden
- Defaults to 10.0.0.165:25575 (LoadBalancer IP)
- Supports MCRCON_HOST/PORT overrides
- Interactive terminal mode when no args provided

Part of k3s-cluster-config bead k3s-cluster-config-byg
2026-01-14 14:09:45 -08:00
667f5b28dc feat(skills): Close Gitea issues when beads are reconciled
Some checks failed
CI / check (push) Has been cancelled
2026-01-14 13:59:30 -08:00
4bb71d0b7e Remove wixos (WSL) configuration
All checks were successful
CI / check (push) Successful in 3m0s
WSL is no longer used. This removes:
- machines/wixos/ directory and configuration.nix
- nixos-wsl input from flake.nix
- nixosConfigurations.wixos output
- References to wixos in AGENTS.md and .goosehints

Implements bead: nixos-configs-2mk
2026-01-13 18:02:36 -08:00
0bc134f557 fix(mu4e): Configure msmtp to preserve email body content
All checks were successful
CI / check (push) Successful in 6m0s
The mu4e msmtp configuration was causing email bodies to be stripped,
especially for multipart messages from org-msg. This was due to missing
critical msmtp settings.

Changes:
- Add message-sendmail-f-is-evil to prevent -f flag issues
- Add --read-envelope-from to msmtp arguments
- Set both send-mail-function and message-send-mail-function

Fixes: nixos-configs-9l8
2026-01-13 17:48:36 -08:00
1b9df3926e Fix conflicting audio role config: remove pulseaudio, keep pipewire
Some checks failed
CI / check (push) Has been cancelled
Remove services.pulseaudio configuration that conflicted with
services.pipewire. PipeWire replaces PulseAudio and provides
compatibility through pulse.enable.

Also added alsa.enable and alsa.support32Bit for better ALSA support.
2026-01-13 17:48:00 -08:00
bd98793528 feat(roles): Parameterize hardcoded values in printing, nfs-mounts, and virtualisation roles
Some checks failed
CI / check (push) Has been cancelled
- printing role: Add configurable printerName, printerUri, and printerModel options
  to replace hardcoded Brother printer values
- nfs-mounts role: Add configurable server, remotePath, and mountPoint options
  to replace hardcoded NFS server IP (10.0.0.43)
- virtualisation role: Add configurable dockerUsers option as list type
  to replace hardcoded 'johno' docker group membership

All options have sensible defaults matching the original hardcoded values,
ensuring backward compatibility while allowing per-host customization.

Implements bead: nixos-configs-fkt
2026-01-13 17:20:59 -08:00
d78637cf13 feat(home-manager): Add platform compatibility guards to cross-platform roles
Some checks failed
CI / check (push) Has been cancelled
Add lib.optionals pkgs.stdenv.isLinux guards to roles that contain
Linux-only packages or services to prevent build failures on Darwin:

- communication: Guard Electron apps (element-desktop, fluffychat,
  nextcloud-talk-desktop) that don't build on Darwin due to electron
  build-from-source limitations
- kdeconnect: Guard entire config block since services.kdeconnect
  requires D-Bus and systemd (Linux-only)
- sync: Guard syncthingtray package (requires Linux system tray)
- email: Guard systemd.user.services/timers (Darwin uses launchd)
- desktop: Guard Linux-only packages, services, and KDE-specific
  configurations including gnome-keyring, systemd services, and
  XDG mime associations

Implements bead: nixos-configs-tcu
2026-01-13 17:20:01 -08:00
08d16bd2c9 feat(scripts): Add --help flags to all flake apps
Some checks failed
CI / check (push) Has been cancelled
Add consistent --help/-h argument handling to update-doomemacs.sh,
rotate-wallpaper.sh, and upgrade.sh scripts. Each script now displays
usage information and a description of what it does.

update-claude-code already had --help support.
2026-01-13 17:18:46 -08:00
50 changed files with 1974 additions and 327 deletions

5
.beads/.gitignore vendored
View File

@@ -32,6 +32,11 @@ beads.left.meta.json
beads.right.jsonl
beads.right.meta.json
# Sync state (local-only, per-machine)
# These files are machine-specific and should not be shared across clones
.sync.lock
sync_base.jsonl
# NOTE: Do NOT add negation patterns (e.g., !issues.jsonl) here.
# They would override fork protection in .git/info/exclude, allowing
# contributors to accidentally commit upstream issue databases.

View File

@@ -1,4 +0,0 @@
{
"database": "beads.db",
"jsonl_export": "sync_base.jsonl"
}

View File

@@ -10,9 +10,11 @@ jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- uses: https://git.johnogle.info/johno/gitea-actions/nix-setup@main
- uses: https://git.johnogle.info/johno/gitea-actions/nix-setup@v1
- name: Check flake
run: nix flake check
env:
NIX_CONFIG: "access-tokens = git.johnogle.info=${{ secrets.GITEA_ACCESS_TOKEN }}"

5
.gitignore vendored
View File

@@ -1,3 +1,8 @@
result
thoughts
.beads
# Gas Town (added by gt)
.runtime/
.claude/
.logs/

View File

@@ -9,7 +9,7 @@ Directory Structure:
----------------------
• packages/ - Custom Nix packages leveraged across various configurations.
• roles/ - Role-based configurations (e.g., kodi, bluetooth) each with its own module (default.nix) for inclusion in machine setups.
• machines/ - Machine-specific configurations (e.g., nix-book, z790prors, boxy, wixos) including configuration.nix and hardware-configuration.nix tailored for each hardware.
• machines/ - Machine-specific configurations (e.g., nix-book, zix790prors, boxy) including configuration.nix and hardware-configuration.nix tailored for each hardware.
• home/ - Home-manager configurations for personal environments and application settings (e.g., home-nix-book.nix, home-z790prors.nix).
Design Principles:

View File

@@ -14,7 +14,7 @@ This repository uses `beads` for issue tracking and management. Run `bd quicksta
### Flake Structure
- **flake.nix**: Main entry point defining inputs (nixpkgs, home-manager, plasma-manager, etc.) and outputs for multiple NixOS configurations
- **Machines**: `nix-book`, `boxy`, `wixos` (WSL configuration), `zix790prors`, `live-usb`, `johno-macbookpro` (Darwin/macOS)
- **Machines**: `nix-book`, `boxy`, `zix790prors`, `live-usb`, `johno-macbookpro` (Darwin/macOS)
- **Home configurations**: Standalone home-manager configuration for user `johno`
### Directory Structure
@@ -78,7 +78,6 @@ The repository also uses a modular home-manager role system for user-space confi
- **nix-book**: Compact laptop → excludes office/media roles due to SSD space constraints
- **boxy**: Living room media center → optimized for media consumption, excludes sync/office (shared machine)
- **zix790prors**: All-purpose workstation → full desktop experience with all roles enabled
- **wixos**: WSL2 development → full desktop experience, inherits from zix790prors Windows host
- **live-usb**: Temporary environment → only base + desktop roles, no persistent services
- **johno-macbookpro**: macOS work laptop → Darwin-specific configuration with development tools
@@ -111,7 +110,6 @@ darwin-rebuild build --flake .#johno-macbookpro
- `nix-book`: Compact laptop with storage constraints, uses `home/home-laptop-compact.nix`
- `boxy`: Shared living room media center/gaming desktop with AMD GPU, uses `home/home-media-center.nix`
- `zix790prors`: Powerful all-purpose workstation (gaming, 3D modeling, development), dual-boots Windows 11 with shared btrfs /games partition, uses `home/home-desktop.nix`
- `wixos`: WSL2 development environment running in Windows partition of zix790prors, uses `home/home-desktop.nix`
- `live-usb`: Bootable ISO configuration, uses `home/home-live-usb.nix`
- `johno-macbookpro`: macOS work laptop, uses `home/home-darwin-work.nix`

90
flake.lock generated
View File

@@ -8,11 +8,11 @@
]
},
"locked": {
"lastModified": 1767911810,
"narHash": "sha256-0L4ATr01UsmBC0rSW62VIMVVSUihAQu2+ZOoHk9BQnA=",
"lastModified": 1769020852,
"narHash": "sha256-MR6evuoa8w6mjYTesTAa3bsRH+c3IB7EOEDTCjsiAp8=",
"owner": "steveyegge",
"repo": "beads",
"rev": "28ff9fe9919a9665a0f00f5b3fcd084b43fb6cc3",
"rev": "cb46db603d34c0190605eecb8724a6c581119f09",
"type": "github"
},
"original": {
@@ -60,22 +60,6 @@
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1765121682,
"narHash": "sha256-4VBOP18BFeiPkyhy9o4ssBNQEvfvv1kXkasAYd0+rrA=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "65f23138d8d09a92e30f1e5c87611b23ef451bf3",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
@@ -94,6 +78,22 @@
"type": "github"
}
},
"gastown": {
"flake": false,
"locked": {
"lastModified": 1769031452,
"narHash": "sha256-tTvtLvTr38okqbpNnr5exfurI6VkVKNLcnM+A6O7DGY=",
"ref": "refs/heads/main",
"rev": "93e22595cd59802a24253b100dcfae98a6849428",
"revCount": 2938,
"type": "git",
"url": "ssh://git@git.johnogle.info:2222/johno/gastown.git"
},
"original": {
"type": "git",
"url": "ssh://git@git.johnogle.info:2222/johno/gastown.git"
}
},
"google-cookie-retrieval": {
"inputs": {
"nixpkgs": [
@@ -241,38 +241,18 @@
"type": "github"
}
},
"nixos-wsl": {
"inputs": {
"flake-compat": "flake-compat",
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1765841014,
"narHash": "sha256-55V0AJ36V5Egh4kMhWtDh117eE3GOjwq5LhwxDn9eHg=",
"owner": "nix-community",
"repo": "NixOS-WSL",
"rev": "be4af8042e7a61fa12fda58fe9a3b3babdefe17b",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "main",
"repo": "NixOS-WSL",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1765472234,
"narHash": "sha256-9VvC20PJPsleGMewwcWYKGzDIyjckEz8uWmT0vCDYK0=",
"owner": "NixOS",
"lastModified": 1767480499,
"narHash": "sha256-8IQQUorUGiSmFaPnLSo2+T+rjHtiNWc+OAzeHck7N48=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "2fbfb1d73d239d2402a8fe03963e37aab15abe8b",
"rev": "30a3c519afcf3f99e2c6df3b359aec5692054d92",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"owner": "nixos",
"ref": "nixos-25.11",
"repo": "nixpkgs",
"type": "github"
}
@@ -293,22 +273,6 @@
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1767480499,
"narHash": "sha256-8IQQUorUGiSmFaPnLSo2+T+rjHtiNWc+OAzeHck7N48=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "30a3c519afcf3f99e2c6df3b359aec5692054d92",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-25.11",
"repo": "nixpkgs",
"type": "github"
}
},
"plasma-manager": {
"inputs": {
"home-manager": [
@@ -358,14 +322,14 @@
"root": {
"inputs": {
"beads": "beads",
"gastown": "gastown",
"google-cookie-retrieval": "google-cookie-retrieval",
"home-manager": "home-manager",
"home-manager-unstable": "home-manager-unstable",
"jovian": "jovian",
"nix-darwin": "nix-darwin",
"nix-doom-emacs-unstraightened": "nix-doom-emacs-unstraightened",
"nixos-wsl": "nixos-wsl",
"nixpkgs": "nixpkgs_2",
"nixpkgs": "nixpkgs",
"nixpkgs-unstable": "nixpkgs-unstable",
"plasma-manager": "plasma-manager",
"plasma-manager-unstable": "plasma-manager-unstable"

View File

@@ -4,8 +4,7 @@
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11";
nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable";
nixos-wsl.url = "github:nix-community/NixOS-WSL/main";
nix-darwin = {
url = "github:nix-darwin/nix-darwin/nix-darwin-25.11";
inputs.nixpkgs.follows = "nixpkgs";
@@ -48,6 +47,11 @@
inputs.nixpkgs.follows = "nixpkgs-unstable";
};
gastown = {
url = "git+ssh://git@git.johnogle.info:2222/johno/gastown.git";
flake = false; # No flake.nix upstream yet
};
nix-doom-emacs-unstraightened = {
url = "github:marienz/nix-doom-emacs-unstraightened";
# Don't follow nixpkgs to avoid rebuild issues with emacs-overlay
@@ -55,7 +59,7 @@
};
};
outputs = { self, nixpkgs, nixpkgs-unstable, nixos-wsl, ... } @ inputs: let
outputs = { self, nixpkgs, nixpkgs-unstable, ... } @ inputs: let
# Shared overlay function to reduce duplication across module sets
# Parameters:
# unstableOverlays: Additional overlays to apply when importing nixpkgs-unstable
@@ -84,11 +88,21 @@
};
};
# Shared unstable overlays for custom package builds
customUnstableOverlays = [
# Override claude-code in unstable to use our custom GCS-based build
# (needed for corporate networks that block npm registry)
(ufinal: uprev: {
claude-code = uprev.callPackage ./packages/claude-code {};
})
];
nixosModules = [
./roles
inputs.home-manager.nixosModules.home-manager
{
nixpkgs.overlays = [ (mkBaseOverlay {}) ];
nixpkgs.overlays = [ (mkBaseOverlay { unstableOverlays = customUnstableOverlays; }) ];
}
(mkHomeManagerConfig {
sharedModules = [ inputs.plasma-manager.homeModules.plasma-manager ];
@@ -101,7 +115,7 @@
inputs.home-manager-unstable.nixosModules.home-manager
inputs.jovian.nixosModules.jovian
{
nixpkgs.overlays = [ (mkBaseOverlay {}) ];
nixpkgs.overlays = [ (mkBaseOverlay { unstableOverlays = customUnstableOverlays; }) ];
}
(mkHomeManagerConfig {
sharedModules = [ inputs.plasma-manager-unstable.homeModules.plasma-manager ];
@@ -112,17 +126,7 @@
./roles/darwin.nix
inputs.home-manager.darwinModules.home-manager
{
nixpkgs.overlays = [
(mkBaseOverlay {
# Override claude-code in unstable to use our custom GCS-based build
# (needed for corporate networks that block npm registry)
unstableOverlays = [
(ufinal: uprev: {
claude-code = uprev.callPackage ./packages/claude-code {};
})
];
})
];
nixpkgs.overlays = [ (mkBaseOverlay { unstableOverlays = customUnstableOverlays; }) ];
}
(mkHomeManagerConfig { sharedModules = []; })
];
@@ -157,18 +161,6 @@
];
};
nixosConfigurations.wixos = nixpkgs.lib.nixosSystem rec {
system = "x86_64-linux";
modules = nixosModules ++ [
nixos-wsl.nixosModules.default
./machines/wixos/configuration.nix
{
home-manager.users.johno = import ./home/home-desktop.nix;
home-manager.extraSpecialArgs = { inherit system; };
}
];
};
nixosConfigurations.zix790prors = nixpkgs.lib.nixosSystem rec {
system = "x86_64-linux";
modules = nixosModules ++ [

View File

@@ -10,6 +10,7 @@
home.roles = {
"3d-printing".enable = true;
base.enable = true;
gaming.enable = true;
desktop.enable = true;
emacs.enable = true;
email.enable = true;

View File

@@ -12,6 +12,7 @@
home.roles = {
base.enable = true;
desktop.enable = true;
gaming.enable = true;
development.enable = true;
communication.enable = true;
email.enable = true;

View File

@@ -12,6 +12,7 @@
home.roles = {
base.enable = true;
desktop.enable = true;
gaming.enable = true;
media.enable = true;
communication.enable = true;
kdeconnect.enable = true;

View File

@@ -4,6 +4,7 @@ with lib;
let
cfg = config.home.roles.communication;
isLinux = pkgs.stdenv.isLinux;
in
{
options.home.roles.communication = {
@@ -12,14 +13,14 @@ in
config = mkIf cfg.enable {
home.packages = [
# Communication apps
# For logging back into google chat (cross-platform)
globalInputs.google-cookie-retrieval.packages.${system}.default
] ++ optionals isLinux [
# Linux-only communication apps (Electron apps don't build on Darwin)
pkgs.element-desktop
# Re-enabled in 25.11 after security issues were resolved
pkgs.fluffychat
pkgs.nextcloud-talk-desktop
# For logging back into google chat
globalInputs.google-cookie-retrieval.packages.${system}.default
];
};
}

View File

@@ -4,6 +4,7 @@ with lib;
let
cfg = config.home.roles.desktop;
isLinux = pkgs.stdenv.isLinux;
in
{
options.home.roles.desktop = {
@@ -12,61 +13,63 @@ in
config = mkIf cfg.enable {
home.packages = with pkgs; [
# Desktop applications
# Cross-platform desktop applications
bitwarden-desktop
dunst
keepassxc
xdg-utils # XDG utilities for opening files/URLs with default applications
] ++ optionals isLinux [
# Linux-only desktop applications
dunst
unstable.ghostty
# Desktop utilities
# Linux-only desktop utilities
feh # Image viewer and wallpaper setter for X11
rofi # Application launcher for X11
solaar # Logitech management software
waybar
wofi # Application launcher for Wayland
xdg-utils # XDG utilities for opening files/URLs with default applications
# System utilities with GUI components
# Linux-only system utilities with GUI components
(snapcast.override { pulseaudioSupport = true; })
# KDE tiling window management
# KDE tiling window management (Linux-only)
kdePackages.krohnkite # Dynamic tiling extension for KWin 6
# KDE PIM applications for email, calendar, and contacts
# KDE PIM applications for email, calendar, and contacts (Linux-only)
kdePackages.kmail
kdePackages.kmail-account-wizard
kdePackages.kmailtransport
kdePackages.korganizer
kdePackages.kaddressbook
kdePackages.kontact
# KDE System components needed for proper integration
# KDE System components needed for proper integration (Linux-only)
kdePackages.kded
kdePackages.systemsettings
kdePackages.kmenuedit
# Desktop menu support
# Desktop menu support (Linux-only)
kdePackages.plasma-desktop # Contains applications.menu
# KDE Online Accounts support
# KDE Online Accounts support (Linux-only)
kdePackages.kaccounts-integration
kdePackages.kaccounts-providers
kdePackages.signond
# KDE Mapping
# KDE Mapping (Linux-only)
kdePackages.marble # Virtual globe and world atlas
# KDE Productivity
# KDE Productivity (Linux-only)
kdePackages.kate # Advanced text editor with syntax highlighting
kdePackages.okular # Universal document viewer (PDF, ePub, etc.)
kdePackages.spectacle # Screenshot capture utility
kdePackages.filelight # Visual disk usage analyzer
# KDE Multimedia
# KDE Multimedia (Linux-only)
kdePackages.gwenview # Image viewer and basic editor
kdePackages.elisa # Music player
# KDE System Utilities
# KDE System Utilities (Linux-only)
kdePackages.ark # Archive manager (zip, tar, 7z, etc.)
kdePackages.yakuake # Drop-down terminal emulator
];
@@ -77,61 +80,66 @@ in
programs.spotify-player.enable = true;
services.gnome-keyring = {
# Linux-only: GNOME keyring service
services.gnome-keyring = mkIf isLinux {
enable = true;
};
# rbw vault unlock on login and resume from suspend
systemd.user.services.rbw-unlock-on-login = {
Unit = {
Description = "Unlock rbw vault at login";
After = [ "graphical-session.target" ];
# Linux-only: systemd user services for rbw vault unlock
systemd.user.services = mkIf isLinux {
# rbw vault unlock on login
rbw-unlock-on-login = {
Unit = {
Description = "Unlock rbw vault at login";
After = [ "graphical-session.target" ];
};
Service = {
Type = "oneshot";
ExecStart = "${pkgs.rbw}/bin/rbw unlock";
Environment = "RBW_AGENT=${pkgs.rbw}/bin/rbw-agent";
# KillMode = "process" prevents systemd from killing the rbw-agent daemon
# when this oneshot service completes. The agent is spawned by rbw unlock
# and needs to persist after the service exits.
KillMode = "process";
};
Install = {
WantedBy = [ "graphical-session.target" ];
};
};
Service = {
Type = "oneshot";
ExecStart = "${pkgs.rbw}/bin/rbw unlock";
Environment = "RBW_AGENT=${pkgs.rbw}/bin/rbw-agent";
# KillMode = "process" prevents systemd from killing the rbw-agent daemon
# when this oneshot service completes. The agent is spawned by rbw unlock
# and needs to persist after the service exits.
KillMode = "process";
};
Install = {
WantedBy = [ "graphical-session.target" ];
# rbw vault unlock on resume from suspend
rbw-unlock-on-resume = {
Unit = {
Description = "Unlock rbw vault after resume from suspend";
After = [ "suspend.target" ];
};
Service = {
Type = "oneshot";
ExecStart = "${pkgs.rbw}/bin/rbw unlock";
Environment = "RBW_AGENT=${pkgs.rbw}/bin/rbw-agent";
# KillMode = "process" prevents systemd from killing the rbw-agent daemon
# when this oneshot service completes. The agent is spawned by rbw unlock
# and needs to persist after the service exits.
KillMode = "process";
};
Install = {
WantedBy = [ "suspend.target" ];
};
};
};
systemd.user.services.rbw-unlock-on-resume = {
Unit = {
Description = "Unlock rbw vault after resume from suspend";
After = [ "suspend.target" ];
};
Service = {
Type = "oneshot";
ExecStart = "${pkgs.rbw}/bin/rbw unlock";
Environment = "RBW_AGENT=${pkgs.rbw}/bin/rbw-agent";
# KillMode = "process" prevents systemd from killing the rbw-agent daemon
# when this oneshot service completes. The agent is spawned by rbw unlock
# and needs to persist after the service exits.
KillMode = "process";
};
Install = {
WantedBy = [ "suspend.target" ];
};
};
# KDE environment variables for proper integration
home.sessionVariables = {
# Linux-only: KDE environment variables for proper integration
home.sessionVariables = mkIf isLinux {
QT_QPA_PLATFORMTHEME = "kde";
KDE_SESSION_VERSION = "6";
};
xdg = {
enable = true;
# Ensure desktop files are made available for discovery
desktopEntries = {}; # This creates the desktop files directory structure
mimeApps = {
enable = true;
associations.added = {
@@ -141,13 +149,14 @@ in
"x-scheme-handler/https" = "firefox.desktop";
};
defaultApplications = {
# Web browsers
# Web browsers (cross-platform)
"text/html" = "firefox.desktop";
"x-scheme-handler/http" = "firefox.desktop";
"x-scheme-handler/https" = "firefox.desktop";
"x-scheme-handler/about" = "firefox.desktop";
"x-scheme-handler/unknown" = "firefox.desktop";
} // optionalAttrs isLinux {
# Linux-only: KDE application associations
# Documents
"application/pdf" = "okular.desktop";
"text/plain" = "kate.desktop";
@@ -155,7 +164,7 @@ in
"text/x-c" = "kate.desktop";
"text/x-python" = "kate.desktop";
"application/x-shellscript" = "kate.desktop";
# Images
"image/png" = "gwenview.desktop";
"image/jpeg" = "gwenview.desktop";
@@ -164,25 +173,25 @@ in
"image/bmp" = "gwenview.desktop";
"image/tiff" = "gwenview.desktop";
"image/webp" = "gwenview.desktop";
# Archives
"application/zip" = "ark.desktop";
"application/x-tar" = "ark.desktop";
"application/x-compressed-tar" = "ark.desktop";
"application/x-7z-compressed" = "ark.desktop";
"application/x-rar" = "ark.desktop";
# Audio
"audio/mpeg" = "elisa.desktop";
"audio/mp4" = "elisa.desktop";
"audio/flac" = "elisa.desktop";
"audio/ogg" = "elisa.desktop";
"audio/wav" = "elisa.desktop";
# Email
"message/rfc822" = "kmail.desktop";
"x-scheme-handler/mailto" = "kmail.desktop";
# Calendar
"text/calendar" = "korganizer.desktop";
"application/x-vnd.akonadi.calendar.event" = "korganizer.desktop";
@@ -190,9 +199,11 @@ in
};
};
# Fix for KDE applications.menu file issue on Plasma 6
# Linux-only: Fix for KDE applications.menu file issue on Plasma 6
# KDE still looks for applications.menu but Plasma 6 renamed it to plasma-applications.menu
xdg.configFile."menus/applications.menu".source = "${pkgs.kdePackages.plasma-workspace}/etc/xdg/menus/plasma-applications.menu";
xdg.configFile."menus/applications.menu" = mkIf isLinux {
source = "${pkgs.kdePackages.plasma-workspace}/etc/xdg/menus/plasma-applications.menu";
};
# Note: modules must be imported at top-level home config
};

View File

@@ -0,0 +1,317 @@
---
description: Batch research and planning for multiple beads with interactive question review
model: opus
---
# Beads Batch Research+Plan
This skill automates the common workflow of:
1. Running /beads_research in parallel for multiple beads
2. Presenting open questions interactively for user input (bead-by-bead)
3. Running /beads_plan for all researched beads (plus any spawned from splits)
## When to Use
- You have multiple beads ready for work
- You want to research and plan them efficiently before implementation
- You prefer to batch your question-answering rather than context-switching between skills
## Phase 1: Selection
1. **Get ready beads**: Run `bd ready --limit=20` to list beads with no blockers
2. **Filter already-researched beads**:
For each ready bead, check if it already has research:
```bash
ls thoughts/beads-{bead-id}/research.md 2>/dev/null
```
Categorize beads:
- **Needs research**: No `research.md` exists
- **Has research, needs plan**: `research.md` exists but no `plan.md`
- **Already planned**: Both `research.md` and `plan.md` exist
3. **Present selection**:
```
Ready beads available for batch research+plan:
NEEDS RESEARCH:
- {bead-id}: {title} (type: {type})
- ...
HAS RESEARCH (plan only):
- {bead-id}: {title} (type: {type})
- ...
ALREADY PLANNED (skip):
- {bead-id}: {title}
Which beads would you like to process?
```
4. **Use AskUserQuestion** with `multiSelect: true`:
- Include bead ID and title for each option
- Separate options by category
- Allow selection across categories
## Phase 2: Parallel Research
For each selected bead that NEEDS RESEARCH, launch a research subagent.
### Subagent Instructions Template
```
Research bead [BEAD_ID]: [BEAD_TITLE]
1. **Load bead context**:
```bash
bd show [BEAD_ID]
```
2. **Create artifact directory**:
```bash
mkdir -p thoughts/beads-[BEAD_ID]
```
3. **Conduct research** following beads_research.md patterns:
- Analyze and decompose the research question
- Spawn parallel sub-agent tasks (codebase-locator, codebase-analyzer, etc.)
- Synthesize findings
4. **Write research document** to `thoughts/beads-[BEAD_ID]/research.md`:
- Include frontmatter with metadata
- Document findings with file:line references
- **CRITICAL**: Include "## Open Questions" section listing any unresolved items
5. **Return summary**:
- Research status (complete/partial)
- Number of open questions
- Key findings summary (2-3 bullet points)
- List of open questions verbatim
```
### Launching Subagents
Use `subagent_type: "opus"` for research subagents (matches beads_research model setting).
Launch ALL research subagents in a single message for parallel execution:
```
<Task calls for each selected bead needing research - all in one message>
```
### Collecting Results
Wait for ALL research subagents to complete. Collect:
- Bead ID
- Research status
- Open questions list
- Any errors encountered
## Phase 3: Interactive Question Review
Present each bead's open questions sequentially for user input.
### For Each Bead (in order):
1. **Present research summary**:
```
## Bead {N}/{total}: {bead-id} - {title}
Research complete. Key findings:
- {finding 1}
- {finding 2}
Open questions requiring your input:
1. {question 1}
2. {question 2}
Additionally:
- Should this bead be split into multiple beads? (y/n)
- If split, describe the split:
```
2. **Collect user responses**:
- Answers to open questions
- Split decision (yes/no)
- If split: new bead titles and how to divide the work
3. **Handle splits**:
If user indicates a split:
```bash
# Create new beads for split work
bd create --title="{split title 1}" --type={type} --priority={priority} \
--description="{description based on user input}"
# Update original bead if scope narrowed
bd update {original-bead-id} --description="{updated description}"
```
Track new bead IDs for inclusion in planning phase.
4. **Update research document**:
Append user answers to `thoughts/beads-{id}/research.md`:
```markdown
## User Clarifications [{timestamp}]
Q: {question 1}
A: {user answer 1}
Q: {question 2}
A: {user answer 2}
## Bead Splits
{If split: description of split and new bead IDs}
```
### Progress Tracking
After each bead's questions are answered, confirm before moving to next:
```
Questions answered for {bead-id}. {N-1} beads remaining.
Continue to next bead? (y/n)
```
### Beads with No Questions
If a bead's research had no open questions:
```
## Bead {N}/{total}: {bead-id} - {title}
Research complete with no open questions.
Key findings:
- {finding 1}
- {finding 2}
Should this bead be split? (y/n)
```
## Phase 4: Parallel Planning
After all questions answered, launch planning subagents for all beads.
### Beads to Plan
Include:
- Original beads that were researched
- Beads that had existing research (from selection phase)
- New beads spawned from splits
### Subagent Instructions Template
```
Create implementation plan for bead [BEAD_ID]: [BEAD_TITLE]
1. **Load context**:
```bash
bd show [BEAD_ID]
```
2. **Read research** (it exists and has user clarifications):
Read `thoughts/beads-[BEAD_ID]/research.md` FULLY
3. **Create plan** following beads_plan.md patterns:
- Context gathering via sub-agents
- Design approach based on research findings and user clarifications
- **Skip interactive questions** - they were already answered in research review
4. **Write plan** to `thoughts/beads-[BEAD_ID]/plan.md`:
- Full plan structure with phases
- Success criteria (automated and manual)
- References to research document
5. **Update bead**:
```bash
bd update [BEAD_ID] --notes="Plan created: thoughts/beads-[BEAD_ID]/plan.md"
```
6. **Return summary**:
- Plan status (complete/failed)
- Number of phases
- Estimated complexity (small/medium/large)
- Any issues encountered
```
### Launching Subagents
Use `subagent_type: "opus"` for planning subagents (matches beads_plan model setting).
Launch ALL planning subagents in a single message:
```
<Task calls for each bead to plan - all in one message>
```
### Handling Beads Without Research
For beads that had existing research but user didn't review questions:
- Planning subagent reads existing research
- If research has unresolved open questions, subagent should flag this in its return
## Phase 5: Summary
After all planning completes, present final summary.
### Summary Format
```
## Batch Research+Plan Complete
### Successfully Processed:
| Bead | Title | Research | Plan | Phases | Complexity |
|------|-------|----------|------|--------|------------|
| {id} | {title} | Complete | Complete | 3 | medium |
| {id} | {title} | Complete | Complete | 2 | small |
### New Beads (from splits):
| Bead | Title | Parent | Status |
|------|-------|--------|--------|
| {new-id} | {title} | {parent-id} | Planned |
### Failed:
| Bead | Title | Phase Failed | Error |
|------|-------|--------------|-------|
| {id} | {title} | Research | Timeout |
### Next Steps:
1. Review plans at `thoughts/beads-{id}/plan.md`
2. Run `/parallel_beads` to implement all planned beads
3. Or run `/beads_implement {id}` for individual implementation
### Artifacts Created:
- Research: thoughts/beads-{id}/research.md (x{N} files)
- Plans: thoughts/beads-{id}/plan.md (x{N} files)
```
## Error Handling
### Research Subagent Failure
- Log the failure with bead ID and error
- Continue with other beads
- Exclude failed beads from question review and planning
- Report in final summary
### Planning Subagent Failure
- Log the failure with bead ID and error
- Research still valid - can retry planning manually
- Report in final summary
### User Cancellation During Question Review
- Save progress to bead notes
- Report which beads were completed
- User can resume with remaining beads in new session
### Split Bead Creation Failure
- Report error but continue with original bead
- User can manually create split beads later
## Resource Limits
- Maximum concurrent research subagents: 5
- Maximum concurrent planning subagents: 5
- If more beads selected, process in batches
## Notes
- This skill is designed for the "research+plan before implementation" workflow
- Pairs well with `/parallel_beads` for subsequent implementation
- Run `/reconcile_beads` after implementation PRs merge

View File

@@ -54,6 +54,8 @@ When this command is invoked:
- Read `thoughts/beads-{bead-id}/plan.md` FULLY
- Check for any existing checkmarks (- [x]) indicating partial progress
- Read any research at `thoughts/beads-{bead-id}/research.md`
- If plan's Success Criteria references contribution guidelines (e.g., "Per CONTRIBUTING.md:"),
verify the original CONTRIBUTING.md still exists and requirements are current
5. **Mark bead in progress** (if not already):
```bash
@@ -127,6 +129,10 @@ All phases completed and automated verification passed:
- {List manual verification items from plan}
Let me know when manual testing is complete so I can close the bead.
**Contribution guidelines compliance:**
- {List any contribution guideline requirements that were part of Success Criteria}
- {Note if any requirements could not be automated and need manual review}
```
**STOP HERE and wait for user confirmation.**

View File

@@ -51,13 +51,32 @@ When this command is invoked:
- Any linked tickets or docs
- Use Read tool WITHOUT limit/offset
2. **Spawn initial research tasks**:
2. **Check for contribution guidelines**:
```bash
# Check standard locations for contribution guidelines
for f in CONTRIBUTING.md .github/CONTRIBUTING.md docs/CONTRIBUTING.md; do
if [ -f "$f" ]; then
echo "Found: $f"
break
fi
done
```
If found:
- Read the file fully
- Extract actionable requirements (testing, code style, documentation, PR conventions)
- These requirements MUST be incorporated into the plan's Success Criteria
If not found, note "No contribution guidelines found" and proceed.
3. **Spawn initial research tasks**:
- **codebase-locator**: Find all files related to the task
- **codebase-analyzer**: Understand current implementation
- **codebase-pattern-finder**: Find similar features to model after
- **thoughts-locator**: Find any existing plans or decisions
3. **Read all files identified by research**:
4. **Read all files identified by research**:
- Read them FULLY into main context
- Cross-reference with requirements
@@ -273,6 +292,12 @@ Always separate into two categories:
- Performance under real conditions
- Edge cases hard to automate
**From Contribution Guidelines** (if CONTRIBUTING.md exists):
- Include any testing requirements specified in guidelines
- Include any code style/linting requirements
- Include any documentation requirements
- Reference the guideline: "Per CONTRIBUTING.md: {requirement}"
## Example Invocation
```

View File

@@ -51,6 +51,18 @@ When this command is invoked:
- Use the Read tool WITHOUT limit/offset parameters
- Read these files yourself in the main context before spawning sub-tasks
### Step 1.5: Check for contribution guidelines
Before spawning sub-agents, check if the repository has contribution guidelines:
```bash
for f in CONTRIBUTING.md .github/CONTRIBUTING.md docs/CONTRIBUTING.md; do
if [ -f "$f" ]; then echo "Found: $f"; break; fi
done
```
If found, read the file and note key requirements. These should be included in the research document under a "## Contribution Guidelines" section if relevant to the research question.
### Step 2: Analyze and decompose the research question
- Break down the query into composable research areas
- Identify specific components, patterns, or concepts to investigate
@@ -143,6 +155,10 @@ status: complete
## Architecture Documentation
{Current patterns, conventions found in codebase}
## Contribution Guidelines
{If CONTRIBUTING.md exists, summarize key requirements relevant to the research topic}
{If no guidelines found, omit this section}
## Historical Context (from thoughts/)
{Relevant insights from thoughts/ with references}

View File

@@ -42,7 +42,46 @@ AskUserQuestion with:
- options from filtered bd ready output
```
## Phase 2: Parallel Implementation
## Phase 2: Worktree Setup
Before launching implementation subagents, create worktrees for all selected beads:
1. **Get repository name**:
```bash
REPO_NAME=$(git remote get-url origin | sed 's|.*/||' | sed 's/\.git$//')
```
2. **For each selected bead**, create its worktree:
```bash
BEAD_ID="[bead-id]"
# Check if worktree already exists
if [ -d "$HOME/wt/${REPO_NAME}/${BEAD_ID}" ]; then
echo "Worktree already exists: ~/wt/${REPO_NAME}/${BEAD_ID}"
# Ask user: remove and recreate, or skip this bead?
else
git worktree add -b "bead/${BEAD_ID}" "$HOME/wt/${REPO_NAME}/${BEAD_ID}"
fi
```
3. **Track created worktrees**:
Maintain a list of (bead_id, worktree_path) pairs for use in subagent instructions.
4. **Report status**:
```
Created worktrees:
- nixos-configs-abc → ~/wt/nixos-configs/nixos-configs-abc (branch: bead/nixos-configs-abc)
- nixos-configs-xyz → ~/wt/nixos-configs/nixos-configs-xyz (branch: bead/nixos-configs-xyz)
Skipped (existing worktree):
- nixos-configs-123 → Ask user for resolution
```
**Note**: If a worktree or branch already exists, ask the user before proceeding:
- Remove existing worktree and branch, then recreate
- Skip this bead
- Use existing worktree as-is (risky - branch may have diverged)
## Phase 3: Parallel Implementation
For each selected bead, launch a subagent using the Task tool. All subagents should be launched in parallel (single message with multiple Task tool calls).
@@ -53,50 +92,92 @@ Each implementation subagent should receive these instructions:
```
Work on bead [BEAD_ID]: [BEAD_TITLE]
1. **Create worktree**:
- Branch name: `bead/[BEAD_ID]`
- Worktree path: `~/wt/[REPO_NAME]/[BEAD_ID]`
- Command: `git worktree add -b bead/[BEAD_ID] ~/wt/[REPO_NAME]/[BEAD_ID]`
Worktree path: [WORKTREE_PATH]
2. **Review the bead requirements**:
## CRITICAL: Branch Verification (MUST DO FIRST)
1. **Navigate to worktree**:
```bash
cd [WORKTREE_PATH]
```
2. **Verify branch** (MANDATORY before ANY modifications):
```bash
CURRENT_BRANCH=$(git branch --show-current)
echo "Current branch: $CURRENT_BRANCH"
pwd
```
**ABORT CONDITIONS** - If ANY of these are true, STOP IMMEDIATELY:
- Branch is `main` or `master`
- Branch does not match `bead/[BEAD_ID]`
If you detect any abort condition:
```
ABORTING: Branch verification failed.
Expected branch: bead/[BEAD_ID]
Actual branch: [CURRENT_BRANCH]
Working directory: [pwd output]
DO NOT PROCEED. Report this error to the orchestrator.
```
## After Verification Passes
3. **Review the bead requirements**:
- Run `bd show [BEAD_ID]` to understand the acceptance criteria
- Note any external issue references (GitHub issues, Linear tickets, etc.)
3. **Extract validation criteria**:
4. **Extract validation criteria**:
- Check for a plan: `thoughts/beads-[BEAD_ID]/plan.md`
- If plan exists:
- Read the plan and find the "Automated Verification" section
- Extract each verification command (lines starting with `- [ ]` followed by a command)
- Example: `- [ ] Tests pass: \`make test\`` → extract `make test`
- Note any "Per CONTRIBUTING.md:" requirements for additional validation
- Also read the "Manual Verification" section from the plan if present
- Save manual verification items for inclusion in the PR description (they won't be executed)
- If no plan exists, use best-effort validation:
- Check if `Makefile` exists → try `make test` and `make lint`
- Check if `flake.nix` exists → try `nix flake check`
- Check if `package.json` exists → try `npm test`
- **Check for CONTRIBUTING.md** → read and extract testing/linting requirements
- Track which requirements can be automated vs need manual review
- Automated: commands that can be run (e.g., "run `make test`")
- Manual: qualitative checks (e.g., "ensure documentation is updated")
- If none found, note "No validation criteria found"
4. **Implement the changes**:
5. **Implement the changes**:
- Work in the worktree directory
- Complete all acceptance criteria listed in the bead
After implementation, run validation:
- Execute each validation command from step 3
- Execute each validation command from step 4
- Track results in this format:
```
VALIDATION_RESULTS:
- make test: PASS
- make lint: FAIL (exit code 1: src/foo.ts:23 - missing semicolon)
- nix flake check: SKIP (command not found)
- nix flake check: SKIP (not applicable - no flake.nix)
- cargo test: ERROR (command not found)
```
**Status definitions:**
- **PASS**: Check executed successfully with no issues
- **FAIL**: Check executed but found issues that need attention
- **SKIP**: Check not applicable to this project (e.g., no Makefile for `make test`)
- **ERROR**: Check could not execute (missing tool, permission error, command not found)
- If any validation fails:
- Continue with PR creation (don't block)
- Document failures in bead notes: `bd update [BEAD_ID] --notes="Validation failures: [list]"`
5. **Commit and push**:
6. **Commit and push**:
- Stage all changes: `git add -A`
- Create a descriptive commit message
- Push the branch: `git push -u origin bead/[BEAD_ID]`
6. **Create a PR**:
7. **Create a PR**:
- Detect hosting provider from origin URL: `git remote get-url origin`
- If URL contains `github.com`, use `gh`; otherwise use `tea` (Gitea/Forgejo)
- PR title: "[BEAD_ID] [BEAD_TITLE]"
@@ -119,14 +200,27 @@ Work on bead [BEAD_ID]: [BEAD_TITLE]
## Changes
- [List of changes made]
## Validation
[Include validation results from step 4]
## Validation Steps Completed
### Automated Checks
| Check | Status | Details |
|-------|--------|---------|
| make test | PASS | |
| make lint | FAIL | src/foo.ts:23 - missing semicolon |
| nix flake check | SKIP | command not found |
| nix flake check | SKIP | not applicable - no flake.nix |
| cargo test | ERROR | command not found |
### Manual Verification Required
[If plan has Manual Verification items, list them as unchecked boxes:]
- [ ] Verify UI changes match design mockups
- [ ] Test on mobile viewport sizes
[If no manual verification items: "None specified in plan."]
### CONTRIBUTING.md Compliance
[If CONTRIBUTING.md requirements were extracted:]
- [x] Tests pass (verified via `make test`)
- [ ] Documentation updated (needs manual review)
[If no CONTRIBUTING.md: "No contribution guidelines found."]
EOF
)"
```
@@ -146,44 +240,66 @@ Work on bead [BEAD_ID]: [BEAD_TITLE]
## Changes
- [List of changes made]
## Validation
[Include validation results from step 4]
## Validation Steps Completed
### Automated Checks
| Check | Status | Details |
|-------|--------|---------|
| make test | PASS | |
| make lint | FAIL | src/foo.ts:23 - missing semicolon |
| nix flake check | SKIP | command not found |"
| nix flake check | SKIP | not applicable - no flake.nix |
| cargo test | ERROR | command not found |
### Manual Verification Required
[If plan has Manual Verification items, list them as unchecked boxes:]
- [ ] Verify UI changes match design mockups
- [ ] Test on mobile viewport sizes
[If no manual verification items: None specified in plan.]
### CONTRIBUTING.md Compliance
[If CONTRIBUTING.md requirements were extracted:]
- [x] Tests pass (verified via make test)
- [ ] Documentation updated (needs manual review)
[If no CONTRIBUTING.md: No contribution guidelines found.]"
```
7. **Update bead status**:
8. **Update bead status**:
- Mark the bead as "in_review": `bd update [BEAD_ID] --status=in_review`
- Add the PR URL to the bead notes: `bd update [BEAD_ID] --notes="$(bd show [BEAD_ID] --json | jq -r '.notes')
PR: [PR_URL]"`
8. **Report results**:
9. **Report results**:
- Return:
- PR URL
- Bead ID
- Implementation status (success/failure/blocked)
- Validation summary: `X passed, Y failed, Z skipped`
- List of any validation failures with details
- Validation summary: `X passed, Y failed, Z skipped, W errors`
- List of any validation failures or errors with details
- If blocked or unable to complete, explain what's blocking progress
- If validation failed, include the specific failures so the main agent can summarize them for the user
```
### Launching Subagents
For each bead, substitute into the template:
- `[BEAD_ID]` - the bead ID
- `[BEAD_TITLE]` - the bead title
- `[WORKTREE_PATH]` - the worktree path created in Phase 2
Use `subagent_type: "general-purpose"` for implementation subagents. Launch all selected beads' subagents in a single message for parallel execution:
```
<Task calls for each selected bead - all in one message>
```
**Important**: The worktree paths were created in Phase 2. Use the exact paths that were created, e.g.:
- `~/wt/nixos-configs/nixos-configs-abc`
- `~/wt/nixos-configs/nixos-configs-xyz`
Collect results from all subagents before proceeding.
## Phase 3: Parallel Review
## Phase 4: Parallel Review
After all implementation subagents complete, launch review subagents for each PR.
@@ -218,7 +334,7 @@ Review PR for bead [BEAD_ID]
Launch all review subagents in parallel.
## Phase 4: Cleanup and Summary
## Phase 5: Cleanup and Summary
After reviews complete:
@@ -264,9 +380,21 @@ Example output:
## Error Handling
- **Worktree creation failures** (Phase 2):
- If `git worktree add` fails (branch exists, path exists), prompt user:
- Remove existing and retry
- Skip this bead
- Use existing (with warning about potential divergence)
- Do NOT proceed to subagent launch until worktree is confirmed
- **Branch verification failures** (subagent reports):
- If subagent reports it's on `main` or `master`, do NOT retry
- Mark bead as failed with reason "Branch verification failed"
- Continue with other beads but flag this as a critical issue
- Investigation required: the worktree may have been corrupted or not created properly
- **Subagent failures**: If a subagent fails or times out, note it in the summary but continue with other beads
- **PR creation failures**: Report the error but continue with reviews of successful PRs
- **Worktree conflicts**: If a worktree already exists, ask the user if they want to remove it or skip that bead
## Resource Limits

View File

@@ -4,12 +4,13 @@ description: Reconcile beads with merged PRs and close completed beads
# Reconcile Beads Workflow
This skill reconciles beads that are in `in_review` status with their corresponding PRs. If a PR has been merged, the bead is closed.
This skill reconciles beads that are in `in_review` status with their corresponding PRs. If a PR has been merged, the bead is closed and any linked Gitea issue is also closed.
## Prerequisites
- Custom status `in_review` must be configured: `bd config set status.custom "in_review"`
- Beads in `in_review` status should have a PR URL in their notes
- `tea` CLI must be configured for closing Gitea issues
## Workflow
@@ -52,6 +53,34 @@ If the PR is merged:
bd close [BEAD_ID] --reason="PR merged: [PR_URL]"
```
### Step 3.1: Close corresponding Gitea issue (if any)
After closing a bead, check if it has a linked Gitea issue:
1. **Check for Gitea issue URL in bead notes**:
Look for the pattern `Gitea issue: <URL>` in the notes. Extract the URL.
2. **Extract issue number from URL**:
```bash
# Example: https://git.johnogle.info/johno/nixos-configs/issues/16 -> 16
echo "$GITEA_URL" | grep -oP '/issues/\K\d+'
```
3. **Close the Gitea issue**:
```bash
tea issues close [ISSUE_NUMBER]
```
4. **Handle errors gracefully**:
- If issue is already closed: Log warning, continue
- If issue not found: Log warning, continue
- If `tea` fails: Log error, continue with other beads
Example warning output:
```
Warning: Could not close Gitea issue #16: issue already closed
```
### Step 4: Report summary
Present results:
@@ -60,10 +89,17 @@ Present results:
## Beads Reconciliation Summary
### Closed (PR Merged)
| Bead | PR | Title |
|------|-----|-------|
| beads-abc | #123 | Feature X |
| beads-xyz | #456 | Bug fix Y |
| Bead | PR | Gitea Issue | Title |
|------|-----|-------------|-------|
| beads-abc | #123 | #16 closed | Feature X |
| beads-xyz | #456 | (none) | Bug fix Y |
### Gitea Issues Closed
| Issue | Bead | Status |
|-------|------|--------|
| #16 | beads-abc | Closed successfully |
| #17 | beads-def | Already closed (skipped) |
| #99 | beads-ghi | Error: issue not found |
### Still in Review
| Bead | PR | Status | Title |
@@ -80,9 +116,14 @@ Present results:
- **Missing PR URL**: Skip the bead and report it
- **PR not found**: Report the error but continue with other beads
- **API errors**: Report and continue
- **Gitea issue already closed**: Log warning, continue (not an error)
- **Gitea issue not found**: Log warning, continue (issue may have been deleted)
- **No Gitea issue linked**: Normal case, no action needed
- **tea command fails**: Log error with output, continue with other beads
## Notes
- This skill complements `/parallel_beads` which sets beads to `in_review` status
- Run this skill periodically or after merging PRs to keep beads in sync
- Beads with closed (but not merged) PRs are not automatically closed - they may need rework
- Gitea issues are only closed for beads that have a `Gitea issue: <URL>` in their notes

View File

@@ -5,6 +5,29 @@ with lib;
let
cfg = config.home.roles.development;
# FIXME: Temporary override for upstream beads vendorHash mismatch
# Remove after upstream fix: https://github.com/steveyegge/beads/issues/XXX
beadsPackage = globalInputs.beads.packages.${system}.default.overrideAttrs (old: {
vendorHash = "sha256-YU+bRLVlWtHzJ1QPzcKJ70f+ynp8lMoIeFlm+29BNPE=";
});
# Gastown - multi-agent workspace manager (no upstream flake.nix yet)
# Source is tracked via flake input for renovate updates
gastownPackage = pkgs.buildGoModule {
pname = "gastown";
version = "unstable-${builtins.substring 0 8 globalInputs.gastown.rev or "unknown"}";
src = globalInputs.gastown;
vendorHash = "sha256-ripY9vrYgVW8bngAyMLh0LkU/Xx1UUaLgmAA7/EmWQU=";
subPackages = [ "cmd/gt" ];
doCheck = false;
meta = with lib; {
description = "Gas Town - multi-agent workspace manager by Steve Yegge";
homepage = "https://github.com/steveyegge/gastown";
license = licenses.mit;
mainProgram = "gt";
};
};
# Fetch the claude-plugins repository (for humanlayer commands/agents)
# Update the rev to get newer versions of the commands
claudePluginsRepo = builtins.fetchGit {
@@ -37,10 +60,12 @@ in
config = mkIf cfg.enable {
home.packages = [
globalInputs.beads.packages.${system}.default
beadsPackage
gastownPackage
pkgs.unstable.claude-code
pkgs.unstable.claude-code-router
pkgs.unstable.codex
pkgs.sqlite
# Custom packages
pkgs.custom.tea-rbw
@@ -84,8 +109,8 @@ in
fi
done
# Copy local skills from this repo (with retry for race conditions with running Claude)
for file in ${./skills}/*.md; do
# Copy local commands from this repo (with retry for race conditions with running Claude)
for file in ${./commands}/*.md; do
if [ -f "$file" ]; then
filename=$(basename "$file" .md)
dest="$HOME/.claude/commands/''${filename}.md"
@@ -98,11 +123,36 @@ in
fi
done
$DRY_RUN_CMD echo "Claude Code humanlayer commands and agents installed successfully${
if cfg.allowArbitraryClaudeCodeModelSelection
then " (model specifications preserved)"
else " (model selection removed)"
} + local skills"
# Copy local skills (reference materials) to skills subdirectory
mkdir -p ~/.claude/commands/skills
for file in ${./skills}/*.md; do
if [ -f "$file" ]; then
filename=$(basename "$file" .md)
dest="$HOME/.claude/commands/skills/''${filename}.md"
rm -f "$dest" 2>/dev/null || true
if ! cp "$file" "$dest" 2>/dev/null; then
sleep 0.5
cp "$file" "$dest" || echo "Warning: Failed to copy $filename.md to skills"
fi
fi
done
# Copy micro-skills (compact reusable knowledge referenced by formulas)
for file in ${./skills/micro}/*.md; do
if [ -f "$file" ]; then
cp "$file" "$HOME/.claude/commands/skills/$(basename "$file")"
fi
done
# Install beads formulas to user-level formula directory
mkdir -p ~/.beads/formulas
for file in ${./formulas}/*.formula.toml; do
if [ -f "$file" ]; then
cp "$file" "$HOME/.beads/formulas/$(basename "$file")"
fi
done
$DRY_RUN_CMD echo "Claude Code plugins installed: humanlayer commands/agents + local commands + local skills + formulas"
'';
# Set up beads Claude Code integration (hooks for SessionStart/PreCompact)
@@ -110,11 +160,51 @@ in
home.activation.claudeCodeBeadsSetup = lib.hm.dag.entryAfter ["writeBoundary" "claudeCodeCommands"] ''
# Run bd setup claude to install hooks into ~/.claude/settings.json
# This is idempotent - safe to run multiple times
${globalInputs.beads.packages.${system}.default}/bin/bd setup claude 2>/dev/null || true
${beadsPackage}/bin/bd setup claude 2>/dev/null || true
$DRY_RUN_CMD echo "Claude Code beads integration configured (hooks installed)"
'';
# Beads timer gate checker (Linux only - uses systemd)
# Runs every 5 minutes to auto-resolve expired timer gates across all beads projects
# This enables self-scheduling molecules (watchers, patrols, etc.)
systemd.user.services.beads-gate-check = lib.mkIf pkgs.stdenv.isLinux {
Unit = {
Description = "Check and resolve expired beads timer gates";
};
Service = {
Type = "oneshot";
# Check gates in all workspaces that have running daemons
ExecStart = pkgs.writeShellScript "beads-gate-check-all" ''
# Get list of workspaces from daemon registry
workspaces=$(${beadsPackage}/bin/bd daemon list --json 2>/dev/null | ${pkgs.jq}/bin/jq -r '.[].workspace // empty' 2>/dev/null)
if [ -z "$workspaces" ]; then
exit 0 # No beads workspaces, nothing to do
fi
for ws in $workspaces; do
if [ -d "$ws" ]; then
cd "$ws" && ${beadsPackage}/bin/bd gate check --type=timer --quiet 2>/dev/null || true
fi
done
'';
};
};
systemd.user.timers.beads-gate-check = lib.mkIf pkgs.stdenv.isLinux {
Unit = {
Description = "Periodic beads timer gate check";
};
Timer = {
OnBootSec = "5min";
OnUnitActiveSec = "5min";
};
Install = {
WantedBy = [ "timers.target" ];
};
};
# Note: modules must be imported at top-level home config
};
}

View File

@@ -0,0 +1,115 @@
# Quick Fix Formula
#
# Streamlined workflow for well-understood bugs and small fixes.
# Skips the deep research and planning phases of RPI - get in, fix, get out.
#
# Use when:
# - Bug is well-understood (you know what's broken)
# - Fix is straightforward (no architectural decisions)
# - Change is small (< 100 lines)
#
# Use RPI instead when:
# - Root cause is unclear
# - Multiple approaches possible
# - Significant design decisions needed
formula = "quick-fix"
description = """
Streamlined workflow for bugs and small fixes.
A faster alternative to RPI for well-understood issues:
1. Quick investigation to confirm understanding
2. Implement the fix
3. Verify with tests
4. Commit and close
No human gates - designed for quick turnaround on obvious fixes.
"""
version = 1
type = "workflow"
# === Variables ===
[vars.title]
required = true
description = "Brief description of the bug/fix"
[vars.bead_id]
description = "Existing bead ID (creates new if not provided)"
[vars.test_cmd]
default = "make test"
description = "Command to verify the fix"
# === Steps ===
[[steps]]
id = "investigate"
title = "Investigate: {{title}}"
description = """
Quick investigation to confirm understanding of the bug.
Goals:
- Locate the problematic code
- Confirm root cause matches expectations
- Identify files that need changes
This is NOT deep research - spend 5-10 minutes max.
If the bug is more complex than expected, pivot to RPI workflow.
Output: Mental model of what to fix (no artifact needed).
"""
[[steps]]
id = "fix"
title = "Fix: {{title}}"
needs = ["investigate"]
description = """
Implement the fix.
Guidelines:
- Make minimal changes to fix the issue
- Follow existing code patterns
- Add/update tests if appropriate
- Keep changes focused (no drive-by refactors)
If the fix grows beyond expectations, pause and consider:
- Should this be an RPI workflow instead?
- Should we split into multiple changes?
"""
[[steps]]
id = "verify"
title = "Verify fix"
needs = ["fix"]
description = """
Verify the fix works correctly.
Run: {{test_cmd}}
Also check:
- Bug is actually fixed (manual verification)
- No obvious regressions introduced
- Code compiles/builds cleanly
If tests fail, iterate on the fix step.
"""
[[steps]]
id = "commit"
title = "Commit and close"
needs = ["verify"]
description = """
Commit the fix and close the bead.
Actions:
1. Stage changes: git add -A
2. Commit with descriptive message: git commit -m "fix: {{title}}"
3. Push to remote: git push
4. Close the bead: bd close {{bead_id}}
Commit message should explain:
- What was broken
- How it was fixed
- Any relevant context
"""

View File

@@ -0,0 +1,124 @@
# RPI Formula - Research -> Plan -> Implement
#
# Universal workflow for feature development with human gates.
formula = "rpi"
description = """
Research -> Plan -> Implement workflow.
Usage:
bd pour rpi --var title="Add user preferences"
bd pour rpi --var title="Auth" --var bead_id="project-abc" --var test_cmd="nix flake check"
"""
version = 1
type = "workflow"
# ─── Variables ───
[vars.title]
required = true
description = "What are we building?"
[vars.bead_id]
description = "Existing bead ID (creates new if not provided)"
[vars.test_cmd]
default = "make test"
description = "Command to run tests"
[vars.lint_cmd]
default = "make lint"
description = "Command to run linting"
# ─── Research Phase ───
[[steps]]
id = "research"
title = "Research: {{title}}"
skill = "research-agents"
description = """
Conduct comprehensive codebase research.
Goals:
- Understand current implementation
- Identify patterns to follow
- Find relevant files and dependencies
- Document key discoveries
Output: thoughts/beads-{{bead_id}}/research.md
"""
# ─── Planning Phase ───
[[steps]]
id = "plan"
title = "Plan: {{title}}"
needs = ["research"]
type = "human"
skill = "planning"
description = """
Create detailed implementation plan based on research.
Goals:
- Present understanding and clarify requirements
- Propose design options with tradeoffs
- Define phases with success criteria
- Identify what we're NOT doing
Output: thoughts/beads-{{bead_id}}/plan.md
"""
[steps.gate]
type = "human"
reason = "Plan approval before implementation"
# ─── Implementation Phase ───
[[steps]]
id = "implement"
title = "Implement: {{title}}"
needs = ["plan"]
description = """
Execute the approved plan phase by phase.
For each phase:
1. Make the changes
2. Run verification: {{test_cmd}}, {{lint_cmd}}
3. Update plan checkboxes for resumability
Stop and ask if encountering unexpected issues.
"""
# ─── Verification Phase ───
[[steps]]
id = "verify"
title = "Manual verification"
needs = ["implement"]
type = "human"
description = """
Human confirms implementation works correctly.
Check: feature works, edge cases handled, no regressions.
Tests: {{test_cmd}} | Lint: {{lint_cmd}}
"""
[steps.gate]
type = "human"
reason = "Confirm implementation is correct"
# ─── Completion ───
[[steps]]
id = "complete"
title = "Close bead"
needs = ["verify"]
skill = "artifact-format"
description = """
Mark work as complete.
Actions:
- bd update {{bead_id}} --notes="Implementation complete"
- bd close {{bead_id}} --reason="Completed: {{title}}"
- bd sync && git push
"""

View File

@@ -0,0 +1,230 @@
---
description: How to use the bd (beads) CLI for issue tracking, dependencies, and workflow orchestration
---
# BD Workflow
The `bd` CLI is a git-backed issue tracker with first-class dependency support. Use it for multi-session work, blocking relationships, and persistent memory across conversation compaction.
## When to Use BD vs TodoWrite
| Use BD | Use TodoWrite |
|--------|---------------|
| Work spans multiple sessions | Single-session tasks |
| Dependencies between tasks | Independent subtasks |
| Need audit trail in git | Ephemeral tracking |
| Cross-repo coordination | Local project only |
| Resuming after compaction | Simple task lists |
## Core Commands
### Creating Issues
```bash
bd create "Issue title" # Basic task
bd create "Bug title" --type=bug --priority=1 # P1 bug
bd create "Feature" --type=feature -d "Details" # With description
bd q "Quick capture" # Output only ID
```
### Managing Issues
```bash
bd show <id> # View issue details
bd show <id> --children # View children of epic
bd list # List open issues (default 50)
bd list --all # Include closed
bd list -s in_progress # Filter by status
bd list -t bug -p 0 # P0 bugs
bd list --pretty # Tree format
```
### Updating Issues
```bash
bd update <id> --status=in_progress # Start work
bd update <id> --status=blocked # Mark blocked
bd update <id> --claim # Claim atomically
bd update <id> --add-label=urgent # Add label
bd update <id> -d "New description" # Update description
```
### Closing Issues
```bash
bd close <id> # Close issue
bd close <id> --continue # Auto-advance to next step
bd close <id> --suggest-next # Show newly unblocked
```
## Finding Work
```bash
bd ready # Ready issues (no blockers)
bd ready --mol <mol-id> # Ready steps in molecule
bd ready -n 5 # Limit to 5
bd ready --assignee me # Assigned to me
bd blocked # Show blocked issues
bd blocked --parent <id> # Blocked within epic
```
## Dependency Management
### Creating Dependencies
```bash
bd dep <blocker> --blocks <blocked> # A blocks B
bd dep add <blocked> <blocker> # Same as above
bd dep relate <id1> <id2> # Bidirectional link
```
### Viewing Dependencies
```bash
bd dep list <id> # Show dependencies
bd dep tree <id> # Dependency tree
bd dep cycles # Detect cycles
```
### Removing Dependencies
```bash
bd dep remove <blocked> <blocker> # Remove dependency
bd dep unrelate <id1> <id2> # Remove relation
```
## Sync Workflow
BD syncs issues via git. The daemon handles this automatically, but manual sync is available:
```bash
bd sync # Full sync (pull, merge, push)
bd sync --flush-only # Export to JSONL only
bd sync --import-only # Import from JSONL only
bd sync --status # Show sync branch diff
bd sync --squash # Accumulate without commit
```
## Formula and Molecule Workflow
Formulas are reusable workflow templates. Molecules are instantiated workflows.
### Formulas
```bash
bd formula list # List available formulas
bd formula list --type=workflow # Filter by type
bd formula show <name> # Show formula details
bd cook <formula> # Compile to proto (stdout)
bd cook <formula> --var name=auth # With variable substitution
bd cook <formula> --dry-run # Preview steps
bd cook <formula> --persist # Save to database
```
### Molecules: Pour vs Wisp
| pour (persistent) | wisp (ephemeral) |
|-------------------|------------------|
| Feature implementations | Release workflows |
| Multi-session work | Patrol cycles |
| Audit trail needed | Health checks |
| Git-synced | Local only |
```bash
# Persistent molecule (liquid phase)
bd mol pour <proto> --var name=auth
# Ephemeral molecule (vapor phase)
bd mol wisp <proto> --var version=1.0
bd mol wisp list # List wisps
bd mol wisp gc # Garbage collect
```
### Tracking Molecule Progress
```bash
bd mol show <mol-id> # Show structure
bd mol show <mol-id> --parallel # Parallelizable steps
bd mol current # Where am I?
bd mol current <mol-id> # Status for molecule
bd mol progress <mol-id> # Progress summary + ETA
```
### Molecule Lifecycle
```bash
bd mol squash <mol-id> # Condense to digest
bd mol burn <mol-id> # Delete wisp
bd mol distill <epic-id> # Extract formula from epic
```
## Gates and Human Checkpoints
Gates are async wait conditions that block workflow steps:
| Gate Type | Wait Condition |
|-----------|---------------|
| human | Manual `bd close` |
| timer | Timeout expires |
| gh:run | GitHub workflow completes |
| gh:pr | PR merges |
| bead | Cross-rig bead closes |
```bash
bd gate list # Show open gates
bd gate list --all # Include closed
bd gate check # Evaluate all gates
bd gate check --type=bead # Check bead gates only
bd gate resolve <id> # Close manually
```
## Common Patterns
### Starting Work on a Bead
```bash
bd update <id> --status=in_progress
# ... do work ...
bd close <id>
```
### Creating Related Issues
```bash
bd create "Main task" --deps "blocks:<other-id>"
bd dep add <new-id> <blocker-id>
```
### Working Through a Molecule
```bash
bd mol pour my-workflow --var name=feature
bd ready --mol <mol-id> # Find next step
bd update <step-id> --claim # Claim step
# ... do work ...
bd close <step-id> --continue # Close and advance
```
### Quick Status Check
```bash
bd ready -n 3 # Top 3 ready items
bd list -s in_progress # What's in flight?
bd blocked # What's stuck?
```
## Useful Flags
| Flag | Effect |
|------|--------|
| `--json` | JSON output for scripting |
| `--quiet` | Suppress non-essential output |
| `--dry-run` | Preview without executing |
| `--pretty` | Tree format display |
## Integration Notes
- BD auto-syncs via daemon (check with `bd info`)
- Issues stored in `.beads/` directory
- JSONL files sync through git
- Use `bd doctor` if something seems wrong

View File

@@ -0,0 +1,123 @@
---
description: How to structure research and plan artifacts in thoughts/
---
# Artifact Format
Standardized format for thoughts/ artifacts. All beads-related artifacts should follow these conventions for consistency and machine parseability.
## Frontmatter (Required)
Every artifact MUST include YAML frontmatter:
```yaml
---
date: 2026-01-15T10:00:00-08:00 # ISO 8601 with timezone
bead_id: project-abc # Bead identifier
bead_title: "Title of the bead" # Human-readable title
author: claude # Who created this
git_commit: abc123def # Commit hash at creation
branch: main # Branch name
repository: repo-name # Repository name
status: draft|complete # Artifact status
---
```
### Gathering Metadata
```bash
git rev-parse HEAD # Current commit
git branch --show-current # Current branch
basename $(git rev-parse --show-toplevel) # Repo name
date -Iseconds # ISO timestamp
```
## Research Artifact Structure
Location: `thoughts/beads-{bead-id}/research.md`
```markdown
# Research: {bead title}
**Bead**: {bead-id}
**Date**: {timestamp}
**Git Commit**: {commit hash}
## Research Question
{Original question from bead description}
## Summary
{2-3 sentence overview answering the research question}
## Key Discoveries
- {Finding with file:line reference}
- {Pattern or convention found}
- {Architectural decision documented}
## Architecture
{Current patterns and conventions in the codebase}
## Code References
- `path/to/file.py:123` - Description of relevance
- `another/file.ts:45-67` - Description of relevance
## Open Questions
{Areas needing further investigation or human clarification}
```
## Plan Artifact Structure
Location: `thoughts/beads-{bead-id}/plan.md`
```markdown
# {Title} Implementation Plan
## Overview
{What we're implementing and why - 1-2 sentences}
## Current State
{What exists now, key constraints discovered}
### Key Discoveries
- {Finding with file:line reference}
- {Pattern to follow}
## Desired End State
{Specification of what success looks like}
## What We're NOT Doing
{Explicitly list out-of-scope items}
## Phase 1: {Descriptive Name}
### Overview
{What this phase accomplishes}
### Changes
- [ ] {Specific change with file path}
- [ ] {Another change}
### Success Criteria
#### Automated
- [ ] Tests pass: `{test command}`
- [ ] Lint passes: `{lint command}`
#### Manual
- [ ] {Human verification step}
## Phase 2: {Descriptive Name}
{Repeat structure...}
## References
- Bead: {bead-id}
- Research: `thoughts/beads-{bead-id}/research.md`
```
## Key Principles
1. **Always include file:line references** - Makes artifacts actionable
2. **Separate automated vs manual verification** - Enables agent autonomy
3. **Use checkboxes for phases** - Enables resumability after interruption
4. **Keep frontmatter machine-parseable** - Enables tooling integration
5. **Link related artifacts** - Research links to plan, plan links to bead

View File

@@ -0,0 +1,121 @@
---
description: How to create effective implementation plans with phased delivery and clear success criteria
---
# Planning
Create implementation plans that enable incremental, verifiable progress.
## Core Principles
1. **Incremental delivery**: Each phase should produce working, testable changes
2. **Clear checkpoints**: Success criteria that can be verified without ambiguity
3. **Buy-in before detail**: Confirm understanding and approach before writing specifics
4. **Explicit scope**: State what we're NOT doing to prevent scope creep
## Plan Document Structure
```markdown
# {Feature} Implementation Plan
## Overview
{1-2 sentences: what we're building and why}
## Current State Analysis
{What exists now, key constraints, file:line references}
## Desired End State
{Specification of outcome and how to verify it}
## What We're NOT Doing
{Explicit out-of-scope items}
## Phase 1: {Descriptive Name}
### Overview
{What this phase accomplishes - should be independently valuable}
### Changes Required
{Specific files and modifications with code snippets}
### Success Criteria
#### Automated Verification
- [ ] Tests pass: `{test command}`
- [ ] Lint passes: `{lint command}`
#### Manual Verification
- [ ] {Human-observable outcome}
## Testing Strategy
{Unit tests, integration tests, manual testing steps}
## References
{Links to research, related files, similar implementations}
```
## Phase Design
Good phases are:
- **Self-contained**: Completable in one session
- **Testable**: Has clear pass/fail criteria
- **Reversible**: Can be rolled back if needed
- **Incremental**: Builds on previous phases without requiring all phases
Bad phases are:
- "Refactor everything" (too broad)
- "Add helper function" (too granular)
- Phases that only work if ALL phases complete
## Success Criteria Guidelines
**Automated Verification** (agent-runnable):
- Test commands: `make test`, `npm test`, `nix flake check`
- Lint/format: `make lint`, `cargo fmt --check`
- Type checking: `make typecheck`, `tsc --noEmit`
- Build verification: `make build`, `nix build`
**Manual Verification** (requires human):
- UI/UX functionality and appearance
- Performance under realistic conditions
- Edge cases hard to automate
- Integration with external systems
**From Contribution Guidelines** (if CONTRIBUTING.md exists):
- Include any testing requirements specified
- Reference the guideline: "Per CONTRIBUTING.md: {requirement}"
## Presenting Understanding
Before writing the plan, confirm alignment:
```
Based on the requirements and my research, I understand we need to [summary].
I've found that:
- [Current implementation detail with file:line]
- [Relevant pattern or constraint]
- [Potential complexity identified]
Questions my research couldn't answer:
- [Specific technical question requiring judgment]
```
Only ask questions you genuinely cannot answer through code investigation.
## Design Options Pattern
When multiple approaches exist:
```
**Design Options:**
1. [Option A] - [1-sentence description]
- Pro: [benefit]
- Con: [drawback]
2. [Option B] - [1-sentence description]
- Pro: [benefit]
- Con: [drawback]
Which approach aligns best with [relevant consideration]?
```
Get buy-in on approach before detailing phases.

View File

@@ -0,0 +1,68 @@
---
description: How to write comprehensive PR descriptions that help reviewers understand changes
---
# PR Description
Write PR descriptions that help reviewers understand what changed and why.
## Structure
Use this standard structure for PR descriptions:
```markdown
## Summary
<1-3 bullet points of what changed and why>
## Context
<Why this change was needed - the problem being solved>
<Link to related issues/tickets>
## Changes
<Detailed breakdown by area/component>
- Area 1: What changed and why
- Area 2: What changed and why
## Testing
<How this was verified>
- Automated: Tests added/updated, CI status
- Manual: Steps to verify functionality
## Screenshots (if UI changes)
<Before/after screenshots if applicable>
```
## Guidelines
### Lead with WHY, not WHAT
- The diff shows WHAT changed - your description explains WHY
- Start with the problem being solved
- Explain the approach chosen and alternatives considered
### Link to context
- Reference related issues: `Fixes #123` or `Relates to #456`
- Link to design docs or discussions
- Mention dependent PRs if any
### Call out review areas
- Highlight areas needing careful review
- Note any tricky or non-obvious code
- Point out architectural decisions
### Note breaking changes prominently
- Use a dedicated "Breaking Changes" section if applicable
- Explain migration path for consumers
- List any deprecations
### Be scannable
- Use bullet points over paragraphs
- Keep sections focused and concise
- Put the most important info first
## Anti-patterns to Avoid
- Empty descriptions or just "fixes bug"
- Repeating the commit messages verbatim
- Including irrelevant implementation details
- Missing context on why the change was made
- Forgetting to mention breaking changes

View File

@@ -0,0 +1,49 @@
---
description: How to spawn and coordinate research sub-agents
---
# Research Agents
Use parallel sub-agents for efficient codebase research.
## Available Agents
| Agent | Purpose |
|-------|---------|
| codebase-locator | Find WHERE files and components live |
| codebase-analyzer | Understand HOW specific code works |
| codebase-pattern-finder | Find examples of existing patterns |
| thoughts-locator | Discover relevant documents in thoughts/ |
## Spawning Protocol
1. **Decompose** - Break the research question into 3-5 specific questions
2. **Spawn parallel** - Use one Task call with multiple agents
3. **Be specific** - Include directories and file patterns in prompts
4. **Wait for all** - Do not synthesize until ALL agents complete
5. **Synthesize** - Combine findings into coherent summary with file:line references
## Example
```
Task(codebase-locator, "Find all files related to authentication in src/")
Task(codebase-analyzer, "Explain how JWT tokens are validated in src/auth/")
Task(codebase-pattern-finder, "Find examples of middleware patterns in src/")
Task(thoughts-locator, "Find documents about auth design decisions in thoughts/")
```
## Key Principles
- **Parallel when different** - Run agents in parallel when searching for different things
- **WHAT not HOW** - Each agent knows its job; tell it what you need, not how to search
- **Document, don't evaluate** - Agents should describe what exists, not critique it
- **Specific directories** - Always scope searches to relevant directories
- **File references** - Include specific file:line references in synthesis
## Agent Prompts
When spawning agents, include:
- The specific question or goal
- Relevant directories to search
- Reminder to document (not evaluate) what they find
- Request for file:line references in findings

View File

@@ -225,11 +225,16 @@
mu4e-headers-time-format "%H:%M")
;; Sending mail via msmtp
(setq message-send-mail-function 'message-send-mail-with-sendmail
sendmail-program (executable-find "msmtp")
message-sendmail-envelope-from 'header
mail-envelope-from 'header
mail-specify-envelope-from t))
;; NOTE: message-sendmail-f-is-evil and --read-envelope-from are required
;; to prevent msmtp from stripping the email body when processing headers.
;; Without these, multipart messages (especially from org-msg) may arrive
;; with empty bodies.
(setq sendmail-program (executable-find "msmtp")
send-mail-function #'message-send-mail-with-sendmail
message-send-mail-function #'message-send-mail-with-sendmail
message-sendmail-f-is-evil t
message-sendmail-extra-arguments '("--read-envelope-from")
message-sendmail-envelope-from 'header))
;; Whenever you reconfigure a package, make sure to wrap your config in an
;; `after!' block, otherwise Doom's defaults may override your settings. E.g.

View File

@@ -4,6 +4,7 @@ with lib;
let
cfg = config.home.roles.email;
isLinux = pkgs.stdenv.isLinux;
in
{
options.home.roles.email = {
@@ -89,34 +90,38 @@ in
account default : proton
'';
# Systemd service for mail sync
systemd.user.services.mbsync = {
Unit = {
Description = "Mailbox synchronization service";
After = [ "network-online.target" ];
Wants = [ "network-online.target" ];
};
Service = {
Type = "oneshot";
ExecStart = "${pkgs.bash}/bin/bash -c 'mkdir -p ~/Mail && ${pkgs.isync}/bin/mbsync -a && (${pkgs.mu}/bin/mu info >/dev/null 2>&1 || ${pkgs.mu}/bin/mu init --maildir ~/Mail --personal-address=john@ogle.fyi) && ${pkgs.mu}/bin/mu index'";
Environment = "PATH=${pkgs.rbw}/bin:${pkgs.coreutils}/bin";
StandardOutput = "journal";
StandardError = "journal";
# Linux-only: Systemd service for mail sync (Darwin uses launchd instead)
systemd.user.services = mkIf isLinux {
mbsync = {
Unit = {
Description = "Mailbox synchronization service";
After = [ "network-online.target" ];
Wants = [ "network-online.target" ];
};
Service = {
Type = "oneshot";
ExecStart = "${pkgs.bash}/bin/bash -c 'mkdir -p ~/Mail && ${pkgs.isync}/bin/mbsync -a && (${pkgs.mu}/bin/mu info >/dev/null 2>&1 || ${pkgs.mu}/bin/mu init --maildir ~/Mail --personal-address=john@ogle.fyi) && ${pkgs.mu}/bin/mu index'";
Environment = "PATH=${pkgs.rbw}/bin:${pkgs.coreutils}/bin";
StandardOutput = "journal";
StandardError = "journal";
};
};
};
# Systemd timer for automatic sync
systemd.user.timers.mbsync = {
Unit = {
Description = "Mailbox synchronization timer";
};
Timer = {
OnBootSec = "2min";
OnUnitActiveSec = "5min";
Unit = "mbsync.service";
};
Install = {
WantedBy = [ "timers.target" ];
# Linux-only: Systemd timer for automatic sync
systemd.user.timers = mkIf isLinux {
mbsync = {
Unit = {
Description = "Mailbox synchronization timer";
};
Timer = {
OnBootSec = "2min";
OnUnitActiveSec = "5min";
Unit = "mbsync.service";
};
Install = {
WantedBy = [ "timers.target" ];
};
};
};
};

View File

@@ -12,9 +12,7 @@ in
config = mkIf cfg.enable {
home.packages = with pkgs; [
# Gaming applications would go here
# This role is created for future expansion
# moonlight-qt is currently in media role but could be moved here
custom.mcrcon-rbw
];
};
}

View File

@@ -4,13 +4,15 @@ with lib;
let
cfg = config.home.roles.kdeconnect;
isLinux = pkgs.stdenv.isLinux;
in
{
options.home.roles.kdeconnect = {
enable = mkEnableOption "Enable KDE Connect for device integration";
};
config = mkIf cfg.enable {
# KDE Connect services are Linux-only (requires D-Bus and systemd)
config = mkIf (cfg.enable && isLinux) {
services.kdeconnect = {
enable = true;
indicator = true;

View File

@@ -4,6 +4,7 @@ with lib;
let
cfg = config.home.roles.sync;
isLinux = pkgs.stdenv.isLinux;
in
{
options.home.roles.sync = {
@@ -11,9 +12,10 @@ in
};
config = mkIf cfg.enable {
home.packages = with pkgs; [
# Linux-only: syncthingtray requires system tray support
home.packages = optionals isLinux (with pkgs; [
syncthingtray
];
]);
services.syncthing = {
enable = true;

View File

@@ -1,56 +0,0 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page, on
# https://search.nixos.org/options and in the NixOS manual (`nixos-help`).
# NixOS-WSL specific options are documented on the NixOS-WSL repository:
# https://github.com/nix-community/NixOS-WSL
{ config, lib, pkgs, ... }:
{
imports = [
];
roles = {
audio.enable = true;
desktop = {
enable = true;
wayland = true;
};
nvidia = {
enable = true;
package = "latest";
graphics.extraPackages = with pkgs; [
mesa
libvdpau-va-gl
libva-vdpau-driver
];
};
users.enable = true;
};
networking.hostName = "wixos";
wsl.enable = true;
wsl.defaultUser = "johno";
wsl.startMenuLaunchers = true;
wsl.useWindowsDriver = true;
wsl.wslConf.network.hostname = "wixos";
wsl.wslConf.user.default = "johno";
# WSL-specific environment variables for graphics
environment.sessionVariables = {
LD_LIBRARY_PATH = [
"/usr/lib/wsl/lib"
"/run/opengl-driver/lib"
];
};
# This value determines the NixOS release from which the default
# settings for stateful data, like file locations and database versions
# on your system were taken. It's perfectly fine and recommended to leave
# this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "24.05"; # Did you read the comment?
}

View File

@@ -1,28 +1,29 @@
{ lib
, stdenv
, fetchurl
, autoPatchelfHook
, patchelf
, glibc
}:
let
version = "2.0.76";
version = "2.1.12";
srcs = {
aarch64-darwin = {
url = "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/${version}/darwin-arm64/claude";
sha256 = "b76f6d4d09233e67295897b0a1ed2e22d7afa406431529d8b1b532b63b8cbcbd";
sha256 = "40be59519a84bd35eb1111aa46f72aa6b3443866d3f6336252a198fdcaefbbe5";
};
x86_64-darwin = {
url = "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/${version}/darwin-x64/claude";
sha256 = "9d94582f0af5d2201f1c907bf24ff8d216104b897ee0b24795a6c081f40e08d7";
sha256 = "0eee4b46c91749480bf856f88e49b15a3e944faa9d346679c5f0c0d7fa6f2f54";
};
x86_64-linux = {
url = "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/${version}/linux-x64/claude";
sha256 = "5dcdb480f91ba0df0bc8bd6aff148d3dfd3883f0899eeb5b9427a8b0abe7a687";
sha256 = "3fe979215489dc1b31463fadf95ed2d2d5473a9969447bb7a46431f4578847d4";
};
aarch64-linux = {
url = "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/${version}/linux-arm64/claude";
sha256 = "f64a994c8e5bfb84d7242cebbec75d6919db2ee46d50b8fc7a88d5066db193f9";
sha256 = "e214b1d3b5afd4cd2de9177359001d41a3eb98cb1e3665fe97edc592f5aa132f";
};
};
@@ -38,8 +39,14 @@ in stdenv.mkDerivation {
dontUnpack = true;
dontBuild = true;
# Bun standalone binaries have JS code appended after the ELF sections
# stripping/patching would remove or corrupt this appended data
dontStrip = true;
dontPatchELF = true;
nativeBuildInputs = lib.optionals stdenv.isLinux [ autoPatchelfHook ];
# Don't use autoPatchelfHook - it rewrites the ELF and strips the appended
# bun bundle (the JS code is appended after the ELF sections)
nativeBuildInputs = lib.optionals stdenv.isLinux [ patchelf ];
installPhase = ''
runHook preInstall
@@ -49,6 +56,14 @@ in stdenv.mkDerivation {
runHook postInstall
'';
# Manually patch the interpreter for bun standalone binaries
# patchelf --set-interpreter modifies in-place without rewriting the entire ELF,
# preserving the appended JS bundle that bun needs at runtime
postFixup = lib.optionalString stdenv.isLinux ''
interpreter="${glibc}/lib/${if stdenv.hostPlatform.system == "aarch64-linux" then "ld-linux-aarch64.so.1" else "ld-linux-x86-64.so.2"}"
patchelf --set-interpreter "$interpreter" $out/bin/claude
'';
meta = with lib; {
description = "Terminal-based AI coding assistant from Anthropic";
homepage = "https://www.anthropic.com/claude-code";

View File

@@ -3,4 +3,5 @@
tea-rbw = pkgs.callPackage ./tea-rbw {};
app-launcher-server = pkgs.callPackage ./app-launcher-server {};
claude-code = pkgs.callPackage ./claude-code {};
mcrcon-rbw = pkgs.callPackage ./mcrcon-rbw {};
}

View File

@@ -0,0 +1,40 @@
{ pkgs, ... }:
pkgs.writeShellScriptBin "mcrcon" ''
set -euo pipefail
# Configuration - can be overridden with environment variables
MINECRAFT_RCON_HOST="''${MCRCON_HOST:-10.0.0.165}"
MINECRAFT_RCON_PORT="''${MCRCON_PORT:-25575}"
RBW_ENTRY="minecraft-rcon"
# Check if rbw is available
if ! command -v rbw &> /dev/null; then
echo "Error: rbw is not available. Please ensure rbw is installed and configured."
exit 1
fi
# Retrieve password from Bitwarden
if ! MCRCON_PASS=$(rbw get "$RBW_ENTRY" 2>/dev/null); then
echo "Error: Failed to retrieve RCON password from rbw entry '$RBW_ENTRY'"
echo "Please ensure the entry exists in Bitwarden and rbw is synced."
echo ""
echo "To create the entry:"
echo " 1. Add 'minecraft-rcon' to Bitwarden with the RCON password"
echo " 2. Run 'rbw sync' to refresh the local cache"
exit 1
fi
# Export for mcrcon
export MCRCON_HOST="$MINECRAFT_RCON_HOST"
export MCRCON_PORT="$MINECRAFT_RCON_PORT"
export MCRCON_PASS
# If no arguments provided, start interactive terminal mode
if [[ $# -eq 0 ]]; then
exec ${pkgs.mcrcon}/bin/mcrcon -t
fi
# Execute mcrcon with all provided arguments
exec ${pkgs.mcrcon}/bin/mcrcon "$@"
''

90
renovate.json Normal file
View File

@@ -0,0 +1,90 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"timezone": "America/Los_Angeles",
"gitAuthor": "Renovate Bot <renovate@ogle.fyi>",
"nix": {
"enabled": true
},
"github-actions": {
"managerFilePatterns": [
"/.gitea/workflows/.+\\.ya?ml$/"
]
},
"lockFileMaintenance": {
"enabled": true,
"schedule": [
"before 5am on monday"
]
},
"dependencyDashboard": true,
"dependencyDashboardAutoclose": false,
"dependencyDashboardTitle": "NixOS Configs Dependency Dashboard",
"packageRules": [
{
"description": "Group all GitHub Actions updates",
"matchManagers": [
"github-actions"
],
"groupName": "github-actions"
},
{
"description": "Group stable NixOS ecosystem inputs",
"matchManagers": [
"nix"
],
"groupName": "nix-stable-ecosystem",
"matchPackageNames": [
"/^nixpkgs$/",
"/^home-manager$/",
"/^nix-darwin$/"
]
},
{
"description": "Group unstable NixOS ecosystem inputs",
"matchManagers": [
"nix"
],
"groupName": "nix-unstable-ecosystem",
"matchPackageNames": [
"/nixpkgs-unstable/",
"/home-manager-unstable/"
]
},
{
"description": "Ignore private Gitea inputs (handle separately)",
"matchManagers": [
"nix"
],
"enabled": false,
"matchPackageNames": [
"/google-cookie-retrieval/"
]
},
{
"description": "Gastown is under active development - check for updates daily",
"matchManagers": [
"nix"
],
"matchPackageNames": [
"/gastown/"
],
"schedule": [
"before 6am every day"
],
"automerge": false
},
{
"description": "Beads is under active development - check for updates daily",
"matchManagers": [
"nix"
],
"matchPackageNames": [
"/beads/"
],
"schedule": [
"before 6am every day"
],
"automerge": false
}
]
}

View File

@@ -21,6 +21,8 @@ in
services.pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
};

View File

@@ -8,11 +8,12 @@
environment.systemPackages = with pkgs; [
git
glances
ghostty.terminfo # So tmux works when SSH'ing from ghostty
pciutils
tree
usbutils
vim
] ++ lib.optionals pkgs.stdenv.isLinux [
ghostty.terminfo # So tmux works when SSH'ing from ghostty
];
nix = {

View File

@@ -8,6 +8,21 @@ in
{
options.roles.nfs-mounts = {
enable = mkEnableOption "Enable default NFS mounts";
server = mkOption {
type = types.str;
default = "10.0.0.43";
description = "IP address or hostname of the NFS server";
};
remotePath = mkOption {
type = types.str;
default = "/media";
description = "Remote path to mount from the NFS server";
};
mountPoint = mkOption {
type = types.str;
default = "/media";
description = "Local mount point for the NFS share";
};
# TODO: implement requireMount
requireMount = mkOption {
type = types.bool;
@@ -18,8 +33,8 @@ in
config = mkIf cfg.enable
{
fileSystems."/media" = {
device = "10.0.0.43:/media";
fileSystems.${cfg.mountPoint} = {
device = "${cfg.server}:${cfg.remotePath}";
fsType = "nfs";
options = [
"defaults"

View File

@@ -8,6 +8,21 @@ in
{
options.roles.printing = {
enable = mkEnableOption "Enable default printing setup";
printerName = mkOption {
type = types.str;
default = "MFC-L8900CDW_series";
description = "Name for the default printer";
};
printerUri = mkOption {
type = types.str;
default = "ipp://brother.oglehome/ipp/print";
description = "Device URI for the default printer (e.g., ipp://hostname/ipp/print)";
};
printerModel = mkOption {
type = types.str;
default = "everywhere";
description = "PPD model for the printer (use 'everywhere' for driverless IPP)";
};
};
config = mkIf cfg.enable
@@ -21,11 +36,11 @@ in
};
hardware.printers.ensurePrinters = [{
name = "MFC-L8900CDW_series";
deviceUri = "ipp://brother.oglehome/ipp/print";
model = "everywhere";
name = cfg.printerName;
deviceUri = cfg.printerUri;
model = cfg.printerModel;
}];
hardware.printers.ensureDefaultPrinter = "MFC-L8900CDW_series";
hardware.printers.ensureDefaultPrinter = cfg.printerName;
# Fix ensure-printers service to wait for network availability
systemd.services.ensure-printers = {

View File

@@ -8,6 +8,11 @@ in
{
options.roles.virtualisation = {
enable = mkEnableOption "Enable virtualisation";
dockerUsers = mkOption {
type = types.listOf types.str;
default = [ "johno" ];
description = "List of users to add to the docker group";
};
};
config = mkIf cfg.enable
@@ -15,6 +20,6 @@ in
virtualisation.libvirtd.enable = true;
programs.virt-manager.enable = true;
virtualisation.docker.enable = true;
users.extraGroups.docker.members = [ "johno" ];
users.extraGroups.docker.members = cfg.dockerUsers;
};
}

View File

@@ -1,6 +1,30 @@
#!/usr/bin/env bash
set -euo pipefail
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
--help|-h)
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Rotate to the next wallpaper in the configured list."
echo ""
echo "This script increments the currentIndex in home/wallpapers/default.nix,"
echo "cycling through available wallpapers. Rebuild your system to apply"
echo "the new wallpaper."
echo ""
echo "Options:"
echo " --help, -h Show this help message"
exit 0
;;
*)
echo "Unknown option: $1"
echo "Use --help for usage information"
exit 1
;;
esac
done
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'

View File

@@ -1,6 +1,30 @@
#!/usr/bin/env bash
set -euo pipefail
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
--help|-h)
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Update Doom Emacs to the latest commit from the doomemacs repository."
echo ""
echo "This script fetches the latest commit SHA from the default branch,"
echo "updates the rev and sha256 in home/roles/emacs/default.nix, and"
echo "prepares the configuration for a system rebuild."
echo ""
echo "Options:"
echo " --help, -h Show this help message"
exit 0
;;
*)
echo "Unknown option: $1"
echo "Use --help for usage information"
exit 1
;;
esac
done
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'

View File

@@ -1,6 +1,35 @@
#!/usr/bin/env bash
set -euo pipefail
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
--help|-h)
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Perform a major upgrade of the NixOS configuration."
echo ""
echo "This script runs the following steps:"
echo " 1. Update all flake inputs (nix flake update)"
echo " 2. Update Doom Emacs to the latest commit"
echo " 3. Update Claude Code to the latest version"
echo " 4. Rotate to the next wallpaper"
echo ""
echo "After completion, review changes with 'git diff' and rebuild"
echo "your system with 'sudo nixos-rebuild switch --flake .'"
echo ""
echo "Options:"
echo " --help, -h Show this help message"
exit 0
;;
*)
echo "Unknown option: $1"
echo "Use --help for usage information"
exit 1
;;
esac
done
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'