Compare commits

...

97 Commits

Author SHA1 Message Date
0f1a585b39 bd daemon sync: 2026-01-10 20:10:24 2026-01-10 20:10:24 -08:00
21f1d7c814 bd daemon sync: 2026-01-10 20:10:09 2026-01-10 20:10:09 -08:00
a97c5400ac bd daemon sync: 2026-01-10 20:09:39 2026-01-10 20:09:39 -08:00
5ea26ce2b2 bd daemon sync: 2026-01-10 19:31:19 2026-01-10 19:31:19 -08:00
c295041902 bd daemon sync: 2026-01-10 19:13:59 2026-01-10 19:13:59 -08:00
574dc1d4e1 bd daemon sync: 2026-01-10 19:13:54 2026-01-10 19:13:54 -08:00
9dc8b6de6e bd daemon sync: 2026-01-10 19:13:42 2026-01-10 19:13:42 -08:00
416da275dd bd daemon sync: 2026-01-10 19:13:20 2026-01-10 19:13:20 -08:00
dafc1808de bd daemon sync: 2026-01-10 19:13:14 2026-01-10 19:13:14 -08:00
0c3d9a2df9 bd daemon sync: 2026-01-10 19:13:13 2026-01-10 19:13:13 -08:00
652c1c8722 bd daemon sync: 2026-01-10 19:13:12 2026-01-10 19:13:12 -08:00
ea9b093aff bd daemon sync: 2026-01-10 19:13:04 2026-01-10 19:13:04 -08:00
d963595dfb bd daemon sync: 2026-01-10 19:13:04 2026-01-10 19:13:04 -08:00
de40a3f8b3 bd daemon sync: 2026-01-10 19:13:03 2026-01-10 19:13:03 -08:00
04401d75b0 bd daemon sync: 2026-01-10 19:13:02 2026-01-10 19:13:02 -08:00
94d767edc3 bd daemon sync: 2026-01-10 19:12:51 2026-01-10 19:12:51 -08:00
950ddef305 bd daemon sync: 2026-01-10 14:19:55 2026-01-10 14:19:55 -08:00
2bad594287 bd daemon sync: 2026-01-10 14:19:54 2026-01-10 14:19:54 -08:00
e59c4b00ec bd daemon sync: 2026-01-10 14:19:53 2026-01-10 14:19:53 -08:00
f917dbf0e6 bd daemon sync: 2026-01-10 14:19:52 2026-01-10 14:19:52 -08:00
077d4bb147 bd daemon sync: 2026-01-10 14:18:41 2026-01-10 14:18:41 -08:00
5888e274e6 bd daemon sync: 2026-01-10 14:18:40 2026-01-10 14:18:40 -08:00
6544899d34 bd daemon sync: 2026-01-10 14:18:39 2026-01-10 14:18:39 -08:00
dc803e6aad bd daemon sync: 2026-01-10 14:18:38 2026-01-10 14:18:38 -08:00
b9a1b3d26b bd daemon sync: 2026-01-10 14:18:37 2026-01-10 14:18:37 -08:00
50f916cf2e bd daemon sync: 2026-01-10 13:13:20 2026-01-10 13:13:20 -08:00
74a2bb6a16 bd daemon sync: 2026-01-10 13:13:11 2026-01-10 13:13:11 -08:00
f611a2c39f bd daemon sync: 2026-01-10 13:12:07 2026-01-10 13:12:07 -08:00
1f4ba6a80f bd daemon sync: 2026-01-10 13:11:54 2026-01-10 13:11:54 -08:00
2cc9b1c491 bd daemon sync: 2026-01-10 13:11:47 2026-01-10 13:11:47 -08:00
197191ce4a bd daemon sync: 2026-01-10 13:11:37 2026-01-10 13:11:37 -08:00
25fb086142 bd daemon sync: 2026-01-10 13:11:30 2026-01-10 13:11:30 -08:00
056925dd72 bd daemon sync: 2026-01-10 13:11:23 2026-01-10 13:11:23 -08:00
47aa5fd454 bd daemon sync: 2026-01-10 13:11:18 2026-01-10 13:11:18 -08:00
b1d82da740 bd daemon sync: 2026-01-10 13:11:13 2026-01-10 13:11:13 -08:00
602d3067f0 bd daemon sync: 2026-01-10 13:11:11 2026-01-10 13:11:11 -08:00
5b492046e6 bd daemon sync: 2026-01-10 13:10:25 2026-01-10 13:10:25 -08:00
dd660d65ba bd daemon sync: 2026-01-10 13:10:14 2026-01-10 13:10:14 -08:00
d03a935912 bd daemon sync: 2026-01-10 13:09:54 2026-01-10 13:09:54 -08:00
3f7a909b0a bd daemon sync: 2026-01-10 13:09:48 2026-01-10 13:09:48 -08:00
5a705803e5 bd daemon sync: 2026-01-10 13:08:53 2026-01-10 13:08:53 -08:00
db0f78bd4a bd daemon sync: 2026-01-10 13:08:42 2026-01-10 13:08:42 -08:00
81ef9def29 bd daemon sync: 2026-01-10 13:06:15 2026-01-10 13:06:15 -08:00
4784190104 bd daemon sync: 2026-01-10 13:06:05 2026-01-10 13:06:05 -08:00
791be65d8d bd daemon sync: 2026-01-10 12:53:10 2026-01-10 12:53:10 -08:00
c6d7399d64 bd daemon sync: 2026-01-10 12:53:10 2026-01-10 12:53:10 -08:00
908183f53e bd daemon sync: 2026-01-10 12:52:19 2026-01-10 12:52:19 -08:00
83f4dc268c bd daemon sync: 2026-01-10 12:50:58 2026-01-10 12:50:58 -08:00
6a6d0e7726 bd daemon sync: 2026-01-10 12:50:57 2026-01-10 12:50:57 -08:00
14c80ae448 bd daemon sync: 2026-01-10 12:50:55 2026-01-10 12:50:55 -08:00
3f607a91ec bd daemon sync: 2026-01-10 12:48:28 2026-01-10 12:48:28 -08:00
e46eb093fe bd daemon sync: 2026-01-10 12:47:50 2026-01-10 12:47:50 -08:00
349ae65ff2 bd daemon sync: 2026-01-10 12:47:30 2026-01-10 12:47:30 -08:00
57252c9ba2 bd daemon sync: 2026-01-10 12:43:48 2026-01-10 12:43:48 -08:00
85cccf0dc9 bd daemon sync: 2026-01-10 12:39:40 2026-01-10 12:39:40 -08:00
c642619bae bd daemon sync: 2026-01-10 12:39:23 2026-01-10 12:39:23 -08:00
3e9111b670 bd daemon sync: 2026-01-10 12:29:29 2026-01-10 12:29:29 -08:00
206b23bfa2 bd daemon sync: 2026-01-10 12:28:20 2026-01-10 12:28:20 -08:00
cba4f78ebc bd daemon sync: 2026-01-10 12:27:40 2026-01-10 12:27:40 -08:00
8bc654f39a bd daemon sync: 2026-01-10 12:27:39 2026-01-10 12:27:39 -08:00
5057266b7a bd daemon sync: 2026-01-10 11:29:32 2026-01-10 11:29:32 -08:00
02529be730 bd daemon sync: 2026-01-10 11:29:19 2026-01-10 11:29:19 -08:00
a6f7026b16 bd daemon sync: 2026-01-10 11:16:24 2026-01-10 11:16:24 -08:00
6d17a62a13 bd daemon sync: 2026-01-10 11:16:17 2026-01-10 11:16:17 -08:00
855f777824 bd daemon sync: 2026-01-10 10:48:49 2026-01-10 10:48:49 -08:00
ccab26f6e7 bd daemon sync: 2026-01-10 10:47:39 2026-01-10 10:47:39 -08:00
20536548a0 bd daemon sync: 2026-01-10 10:47:20 2026-01-10 10:47:20 -08:00
5a42ccda98 bd daemon sync: 2026-01-10 10:47:07 2026-01-10 10:47:07 -08:00
090882595b bd daemon sync: 2026-01-10 09:10:22 2026-01-10 09:10:22 -08:00
2c08b31bb9 bd daemon sync: 2026-01-09 12:47:21 2026-01-09 12:47:21 -08:00
84f5f87027 bd daemon sync: 2026-01-09 12:47:08 2026-01-09 12:47:08 -08:00
ac01548e89 chore(beads): commit untracked JSONL files
Auto-committed by bd doctor --fix
2026-01-09 11:22:13 -08:00
bb7f79843b bd sync: 2026-01-09 11:22:07 2026-01-09 11:22:07 -08:00
c1d6663a36 bd init 2026-01-09 11:21:49 -08:00
3cf4403ffa Add perles TUI package for Beads issue tracking
Adds a custom Nix package for perles, a terminal user interface for the
Beads issue tracking system with BQL query language support.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 11:20:02 -08:00
4e6123de9a Simplify beads integration to use bd setup claude
Replace complex marketplace plugin installation with simple 'bd setup claude'
which installs hooks into ~/.claude/settings.json. This is the recommended
approach for Claude Code (CLI + hooks) vs the MCP server approach.
2026-01-08 19:28:17 -08:00
19ee298b71 Add beads Claude plugin installation via home-manager
- Add beadsRepo reference from flake input
- Add activation script to install beads as marketplace plugin
- Updates known_marketplaces.json and config.json declaratively
2026-01-08 19:21:58 -08:00
537f7831a7 Fix claude-code-ide keybinds and consolidate settings
Move keybinding to :init block so SPC o c works before first invocation.
Add :commands for proper autoloading. Migrate customizations from
custom.el to config.el.
2026-01-05 21:11:58 -08:00
bf0d16fe1a Add Mod+Shift+Return keybinding to open browser window in i3/sway 2026-01-05 21:07:11 -08:00
858b6009ae Style blocked org-agenda tasks in purple instead of grey 2026-01-05 19:48:47 -08:00
40b323dcfd Revert "Use direct hibernate on nix-book lid close"
This reverts commit 2c70504c43.
2026-01-05 09:00:48 -08:00
60bd89b02c Make Sent folder pull-only in mbsync config
Split mbsync channel into two: proton-main for bidirectional sync
(excluding Sent) and proton-sent for pull-only sync. This avoids
"far side refuses to store" errors from Proton Bridge rejecting
uploaded sent messages.
2026-01-05 09:00:08 -08:00
5a5de7353b Ensure Mail directory exists before mbsync runs 2026-01-04 17:23:32 -08:00
e25aa7acab Update flake inputs, doom emacs, and claude-code 2026-01-04 17:12:35 -08:00
4a284de8a1 Add wallpaper rotation system with upgrade workflow
- Add home/wallpapers/default.nix with per-wallpaper scaling options
- Add 5 new Metroid-themed wallpapers to the rotation
- Update i3+sway and plasma-manager to use wallpaper module
- Add scripts/rotate-wallpaper.sh to cycle through wallpapers
- Add scripts/upgrade.sh to chain: flake update, doom, claude-code, wallpaper
- Add flake apps: rotate-wallpaper, update-claude-code, upgrade
- Fix claude-code update.sh to use REPO_ROOT for flake app compatibility

Run `nix run .#upgrade` for full system update with wallpaper rotation.
2026-01-04 17:12:27 -08:00
7be694ef66 [doom] Increase default font size 2026-01-04 13:38:56 -08:00
0ccfc30c73 Add personal address to mu init for mu4e integration 2026-01-04 13:36:56 -08:00
dab96a1c50 Replace notmuch with mu4e for email
mu4e's refile moves messages between IMAP folders, enabling
cross-device sync via mbsync. notmuch tags are local-only.

- Switch from notmuch to mu/mu4e packages
- Auto-initialize mu database on first sync
- Configure mu4e with folder shortcuts and refile to Archive
- Add NixOS load-path for mu4e elisp files
2026-01-04 12:59:35 -08:00
7898def044 Fix notmuch inbox tag to match IMAP INBOX folder
Previously, the notmuch config applied the "inbox" tag to all new
messages regardless of which IMAP folder they were in. This caused
tag:inbox to return all 22k+ messages instead of just those in INBOX.

Changes:
- Use temporary "new" tag instead of "inbox" for newly indexed messages
- Add post-new hook that applies tags based on maildir folder location
- inbox tag now only applies to messages in INBOX folder
- Also adds sent, draft, spam, deleted, and archive tags based on folder
2026-01-04 12:23:39 -08:00
4ce48313f6 Update nixpkgs-unstable to fix tree-sitter-razor
tree-sitter-razor was marked as broken in the previous lock, causing
nix flake check to fail on nix-deck. The grammar has been fixed upstream.
2026-01-04 12:03:19 -08:00
2c70504c43 Use direct hibernate on nix-book lid close
S3 deep sleep is broken on 12th Gen Intel Alder Lake. Switch from
suspend-then-hibernate to direct hibernate on all lid close events.
2026-01-04 12:03:10 -08:00
a22c7fec28 Add Tea CLI documentation for Gitea issue tracking 2026-01-04 11:08:32 -08:00
ef3e9b8c82 Implement volume control for boxy via Home Assistant
Add remote volume control for the living room media center (boxy) that
controls the Denon AVR through Home Assistant instead of local audio.

- Create plasma-manager-kodi role with custom KDE hotkeys for volume
  up/down/mute that execute shell scripts
- Scripts retrieve HA token from KDE Wallet and send API requests to
  control media_player.denon_avr_s970h_2
- Add retry logic (3 attempts) and error notifications
- Enable KDE Wallet PAM integration for automatic wallet unlock
- Configure KDE settings: Breeze Dark theme, disable screen locking,
  empty session restore
- Add kconfig package for debugging tools
2026-01-03 17:11:43 -08:00
0590dad71e [gaming] Add yarg 2026-01-02 13:43:00 -08:00
c81594af01 Add suspend-then-hibernate power management for nix-book 2025-12-30 00:29:24 -08:00
6f999882d3 Reorder migration steps to export ZFS pools before shutdown 2025-12-30 00:29:21 -08:00
8bb20bf05e Add NixOS configuration for john-endesktop ZFS/NFS server
Create configuration to migrate john-endesktop from Arch Linux to NixOS while
maintaining existing ZFS pools (media JBOD and swarmvols mirror) and NFS
exports for k3s cluster.

Configuration includes:
- ZFS support with automatic pool import
- NFS server exporting both pools to 10.0.0.0/24
- Correct ZFS hostid (007f0101) to resolve hostid warnings
- Btrfs root filesystem on nvme0n1p5 (810GB)
- Comprehensive migration plan with rollback procedures

The migration is designed to be safe with Arch Linux remaining bootable
as a fallback until NixOS is verified stable.
2025-12-29 23:50:36 -08:00
35 changed files with 1344 additions and 83 deletions

View File

34
.beads/issues.jsonl Normal file

File diff suppressed because one or more lines are too long

4
.beads/metadata.json Normal file
View File

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

29
.beads/sync_base.jsonl Normal file

File diff suppressed because one or more lines are too long

View File

@@ -172,6 +172,58 @@ Creates an ISO suitable for Ventoy and other USB boot tools in `./result/iso/`.
- **Garbage collection**: Automatic, deletes older than 10 days - **Garbage collection**: Automatic, deletes older than 10 days
- **Unfree packages**: Allowed globally - **Unfree packages**: Allowed globally
## Issue Tracking (Gitea)
**Tea CLI for Gitea:**
```bash
# Note: When using tea CLI, you must specify --repo johno/nixos-configs
# The CLI doesn't automatically detect the repo from git remote
# List all issues (open by default)
tea issues --repo johno/nixos-configs
# List closed issues
tea issues --repo johno/nixos-configs --state closed
# View specific issue
tea issue --repo johno/nixos-configs 2
# Create new issue
tea issues create --repo johno/nixos-configs --title "Issue title" --body "Description"
# Add comment to issue
tea comment --repo johno/nixos-configs 2 "Comment text"
# Close issue (note: 'issues' is plural, issue number comes last)
tea issues close --repo johno/nixos-configs 2
```
## Important Notes ## Important Notes
- **Sudo access**: Claude Code does not have sudo access. Ask the user to run elevated commands like `sudo nixos-rebuild switch` - **Sudo access**: Claude Code does not have sudo access. Ask the user to run elevated commands like `sudo nixos-rebuild switch`
## Landing the Plane (Session Completion)
**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds.
**MANDATORY WORKFLOW:**
1. **File issues for remaining work** - Create issues for anything that needs follow-up
2. **Run quality gates** (if code changed) - Tests, linters, builds
3. **Update issue status** - Close finished work, update in-progress items
4. **PUSH TO REMOTE** - This is MANDATORY:
```bash
git pull --rebase
bd sync
git push
git status # MUST show "up to date with origin"
```
5. **Clean up** - Clear stashes, prune remote branches
6. **Verify** - All changes committed AND pushed
7. **Hand off** - Provide context for next session
**CRITICAL RULES:**
- Work is NOT complete until `git push` succeeds
- NEVER stop before pushing - that leaves work stranded locally
- NEVER say "ready to push when you are" - YOU must push
- If push fails, resolve and retry until it succeeds

85
flake.lock generated
View File

@@ -1,5 +1,26 @@
{ {
"nodes": { "nodes": {
"beads": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": [
"nixpkgs-unstable"
]
},
"locked": {
"lastModified": 1767911810,
"narHash": "sha256-0L4ATr01UsmBC0rSW62VIMVVSUihAQu2+ZOoHk9BQnA=",
"owner": "steveyegge",
"repo": "beads",
"rev": "28ff9fe9919a9665a0f00f5b3fcd084b43fb6cc3",
"type": "github"
},
"original": {
"owner": "steveyegge",
"repo": "beads",
"type": "github"
}
},
"flake-compat": { "flake-compat": {
"flake": false, "flake": false,
"locked": { "locked": {
@@ -16,6 +37,24 @@
"type": "github" "type": "github"
} }
}, },
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"google-cookie-retrieval": { "google-cookie-retrieval": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@@ -43,11 +82,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1766292113, "lastModified": 1767514898,
"narHash": "sha256-sWTtmkQujRpjWYCnZc8LWdDiCzrRlSBPrGovkZpLkBI=", "narHash": "sha256-ONYqnKrPzfKEEPChoJ9qPcfvBqW9ZgieDKD7UezWPg4=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "fdec8815a86db36f42fc9c8cb2931cd8485f5aed", "rev": "7a06e8a2f844e128d3b210a000a62716b6040b7f",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -64,11 +103,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1766282146, "lastModified": 1767556355,
"narHash": "sha256-0V/nKU93KdYGi+5LB/MVo355obBJw/2z9b2xS3bPJxY=", "narHash": "sha256-RDTUBDQBi9D4eD9iJQWtUDN/13MDLX+KmE+TwwNUp2s=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "61fcc9de76b88e55578eb5d79fc80f2b236df707", "rev": "f894bc4ffde179d178d8deb374fcf9855d1a82b7",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -86,11 +125,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1766225187, "lastModified": 1767082077,
"narHash": "sha256-6hcaU8qtmixsaEUbjPiOFd5aJPZxAIBokl5d7dkab3k=", "narHash": "sha256-2tL1mRb9uFJThUNfuDm/ehrnPvImL/QDtCxfn71IEz4=",
"owner": "Jovian-Experiments", "owner": "Jovian-Experiments",
"repo": "Jovian-NixOS", "repo": "Jovian-NixOS",
"rev": "bb53a85db9210204a98f771f10f1f5b4e06ccb2d", "rev": "efd4b22e6fdc6d7fb4e186ae333a4b74e03da440",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -180,11 +219,11 @@
}, },
"nixpkgs-unstable": { "nixpkgs-unstable": {
"locked": { "locked": {
"lastModified": 1766070988, "lastModified": 1767379071,
"narHash": "sha256-G/WVghka6c4bAzMhTwT2vjLccg/awmHkdKSd2JrycLc=", "narHash": "sha256-EgE0pxsrW9jp9YFMkHL9JMXxcqi/OoumPJYwf+Okucw=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "c6245e83d836d0433170a16eb185cefe0572f8b8", "rev": "fb7944c166a3b630f177938e478f0378e64ce108",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -196,11 +235,11 @@
}, },
"nixpkgs_2": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1766201043, "lastModified": 1767480499,
"narHash": "sha256-eplAP+rorKKd0gNjV3rA6+0WMzb1X1i16F5m5pASnjA=", "narHash": "sha256-8IQQUorUGiSmFaPnLSo2+T+rjHtiNWc+OAzeHck7N48=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "b3aad468604d3e488d627c0b43984eb60e75e782", "rev": "30a3c519afcf3f99e2c6df3b359aec5692054d92",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -258,6 +297,7 @@
}, },
"root": { "root": {
"inputs": { "inputs": {
"beads": "beads",
"google-cookie-retrieval": "google-cookie-retrieval", "google-cookie-retrieval": "google-cookie-retrieval",
"home-manager": "home-manager", "home-manager": "home-manager",
"home-manager-unstable": "home-manager-unstable", "home-manager-unstable": "home-manager-unstable",
@@ -269,6 +309,21 @@
"plasma-manager": "plasma-manager", "plasma-manager": "plasma-manager",
"plasma-manager-unstable": "plasma-manager-unstable" "plasma-manager-unstable": "plasma-manager-unstable"
} }
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
} }
}, },
"root": "root", "root": "root",

View File

@@ -42,6 +42,11 @@
url = "github:Jovian-Experiments/Jovian-NixOS"; url = "github:Jovian-Experiments/Jovian-NixOS";
inputs.nixpkgs.follows = "nixpkgs-unstable"; inputs.nixpkgs.follows = "nixpkgs-unstable";
}; };
beads = {
url = "github:steveyegge/beads";
inputs.nixpkgs.follows = "nixpkgs-unstable";
};
}; };
outputs = { self, nixpkgs, nixpkgs-unstable, nixos-wsl, ... } @ inputs: let outputs = { self, nixpkgs, nixpkgs-unstable, nixos-wsl, ... } @ inputs: let
@@ -152,9 +157,9 @@
system = "x86_64-linux"; system = "x86_64-linux";
modules = nixosModules ++ [ modules = nixosModules ++ [
./machines/boxy/configuration.nix ./machines/boxy/configuration.nix
inputs.home-manager.nixosModules.home-manager
{ {
home-manager.users.johno = import ./home/home-media-center.nix; home-manager.users.johno = import ./home/home-media-center.nix;
home-manager.users.kodi = import ./home/home-kodi.nix;
home-manager.extraSpecialArgs = { inherit system; }; home-manager.extraSpecialArgs = { inherit system; };
} }
]; ];
@@ -209,6 +214,15 @@
]; ];
}; };
# ZFS/NFS server configuration
nixosConfigurations.john-endesktop = nixpkgs.lib.nixosSystem rec {
system = "x86_64-linux";
modules = nixosModules ++ [
./machines/john-endesktop/configuration.nix
# Minimal server - no home-manager needed
];
};
# Darwin/macOS configurations # Darwin/macOS configurations
darwinConfigurations."blkfv4yf49kt7" = inputs.nix-darwin.lib.darwinSystem rec { darwinConfigurations."blkfv4yf49kt7" = inputs.nix-darwin.lib.darwinSystem rec {
system = "aarch64-darwin"; system = "aarch64-darwin";
@@ -225,15 +239,44 @@
apps = nixpkgs.lib.genAttrs [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" ] (system: apps = nixpkgs.lib.genAttrs [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" ] (system:
let let
pkgs = import nixpkgs { inherit system; }; pkgs = import nixpkgs { inherit system; };
commonDeps = [ pkgs.curl pkgs.jq pkgs.nix pkgs.git pkgs.gnused pkgs.gnugrep pkgs.coreutils pkgs.gawk ];
update-doomemacs = pkgs.writeShellScriptBin "update-doomemacs" '' update-doomemacs = pkgs.writeShellScriptBin "update-doomemacs" ''
export PATH="${pkgs.lib.makeBinPath [ pkgs.curl pkgs.jq pkgs.nix pkgs.git pkgs.gnused pkgs.gnugrep pkgs.coreutils ]}:$PATH" export PATH="${pkgs.lib.makeBinPath commonDeps}:$PATH"
${builtins.readFile ./scripts/update-doomemacs.sh} ${builtins.readFile ./scripts/update-doomemacs.sh}
''; '';
update-claude-code = pkgs.writeShellScriptBin "update-claude-code" ''
export PATH="${pkgs.lib.makeBinPath commonDeps}:$PATH"
${builtins.readFile ./packages/claude-code/update.sh}
'';
rotate-wallpaper = pkgs.writeShellScriptBin "rotate-wallpaper" ''
export PATH="${pkgs.lib.makeBinPath commonDeps}:$PATH"
${builtins.readFile ./scripts/rotate-wallpaper.sh}
'';
upgrade = pkgs.writeShellScriptBin "upgrade" ''
export PATH="${pkgs.lib.makeBinPath commonDeps}:$PATH"
${builtins.readFile ./scripts/upgrade.sh}
'';
in { in {
update-doomemacs = { update-doomemacs = {
type = "app"; type = "app";
program = "${update-doomemacs}/bin/update-doomemacs"; program = "${update-doomemacs}/bin/update-doomemacs";
}; };
update-claude-code = {
type = "app";
program = "${update-claude-code}/bin/update-claude-code";
};
rotate-wallpaper = {
type = "app";
program = "${rotate-wallpaper}/bin/rotate-wallpaper";
};
upgrade = {
type = "app";
program = "${upgrade}/bin/upgrade";
};
} }
); );
}; };

28
home/home-kodi.nix Normal file
View File

@@ -0,0 +1,28 @@
{ pkgs, globalInputs, system, ... }:
{
# Home Manager configuration for kodi user on boxy
# Focused on media center volume control via Home Assistant
home.username = "kodi";
home.homeDirectory = "/home/kodi";
home.stateVersion = "24.05";
# Enable minimal roles for kodi user
home.roles = {
base.enable = true;
plasma-manager-kodi.enable = true;
};
home.packages = with pkgs; [
kdePackages.kconfig
];
targets.genericLinux.enable = true;
home.sessionVariables = {};
home.sessionPath = [];
imports = [
./roles
];
}

View File

@@ -15,6 +15,7 @@
./launchers ./launchers
./media ./media
./office ./office
./plasma-manager-kodi
./sync ./sync
./tmux ./tmux
./emacs ./emacs

View File

@@ -5,7 +5,7 @@ with lib;
let let
cfg = config.home.roles.development; cfg = config.home.roles.development;
# Fetch the claude-plugins repository # Fetch the claude-plugins repository (for humanlayer commands/agents)
# Update the rev to get newer versions of the commands # Update the rev to get newer versions of the commands
claudePluginsRepo = builtins.fetchGit { claudePluginsRepo = builtins.fetchGit {
url = "https://github.com/jeffh/claude-plugins.git"; url = "https://github.com/jeffh/claude-plugins.git";
@@ -14,6 +14,7 @@ let
rev = "5e3e4d937162185b6d78c62022cbfd1c8ad42c4c"; rev = "5e3e4d937162185b6d78c62022cbfd1c8ad42c4c";
ref = "main"; ref = "main";
}; };
in in
{ {
options.home.roles.development = { options.home.roles.development = {
@@ -36,12 +37,14 @@ in
config = mkIf cfg.enable { config = mkIf cfg.enable {
home.packages = [ home.packages = [
globalInputs.beads.packages.${system}.default
pkgs.unstable.claude-code pkgs.unstable.claude-code
pkgs.unstable.claude-code-router pkgs.unstable.claude-code-router
pkgs.unstable.codex pkgs.unstable.codex
# Custom packages # Custom packages
pkgs.custom.tea-rbw pkgs.custom.tea-rbw
pkgs.custom.perles
]; ];
# Install Claude Code humanlayer command and agent plugins # Install Claude Code humanlayer command and agent plugins
@@ -89,6 +92,16 @@ in
}" }"
''; '';
# Set up beads Claude Code integration (hooks for SessionStart/PreCompact)
# This uses the CLI + hooks approach which is recommended over MCP for Claude Code
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
$DRY_RUN_CMD echo "Claude Code beads integration configured (hooks installed)"
'';
# Note: modules must be imported at top-level home config # Note: modules must be imported at top-level home config
}; };
} }

View File

@@ -8,8 +8,8 @@ let
doomEmacs = pkgs.fetchFromGitHub { doomEmacs = pkgs.fetchFromGitHub {
owner = "doomemacs"; owner = "doomemacs";
repo = "doomemacs"; repo = "doomemacs";
rev = "762f47805ac2a6411e11747f86f7c19a03da326e"; rev = "38d94da67dc84897a4318714dcc48494c016d8c4";
sha256 = "sha256-0w0eXGB2cgxu/hr5wTiJSZDJw0NF+fZvLbzEylH5URU="; sha256 = "sha256-Uc6qONH3jjUVDgW+pPBCGC7mh88ZY05u1y37fQrsxq0=";
}; };
# Shared emacs packages # Shared emacs packages

View File

@@ -28,7 +28,7 @@
;; up, `M-x eval-region' to execute elisp code, and 'M-x doom/reload-font' to ;; up, `M-x eval-region' to execute elisp code, and 'M-x doom/reload-font' to
;; refresh your font settings. If Emacs still can't find your font, it likely ;; refresh your font settings. If Emacs still can't find your font, it likely
;; wasn't installed correctly. Font issues are rarely Doom issues! ;; wasn't installed correctly. Font issues are rarely Doom issues!
(setq doom-font (font-spec :family "Fira Code")) (setq doom-font (font-spec :family "Fira Code" :size 16))
;; Auto-install nerd-icons fonts if they're missing ;; Auto-install nerd-icons fonts if they're missing
(defun my/ensure-nerd-icons-fonts () (defun my/ensure-nerd-icons-fonts ()
@@ -71,7 +71,10 @@
org-journal-file-format "%Y-%m-%d.org" org-journal-file-format "%Y-%m-%d.org"
org-capture-templates org-capture-templates
'(("t" "Todo" entry (file+headline "~/org/todo.org" "Inbox") '(("t" "Todo" entry (file+headline "~/org/todo.org" "Inbox")
"* TODO %? \n %i \n%a" :prepend t)))) "* TODO %? \n %i \n%a" :prepend t)))
;; Make blocked tasks more visible in agenda (they have subtasks to do!)
(custom-set-faces!
'(org-agenda-dimmed-todo-face :foreground "#bb9af7" :weight normal)))
(map! :after org-agenda (map! :after org-agenda
:map org-agenda-mode-map :map org-agenda-mode-map
@@ -145,12 +148,24 @@
:args (list '(:name "dirpath" :type "string" :description "Directory path to list")))) :args (list '(:name "dirpath" :type "string" :description "Directory path to list"))))
(use-package! claude-code-ide (use-package! claude-code-ide
:defer t :commands (claude-code-ide-menu claude-code-ide-open-here)
:config :init
(claude-code-ide-emacs-tools-setup)
(map! :leader (map! :leader
(:prefix ("o" . "open") (:prefix ("o" . "open")
:desc "Claude Code IDE" "c" #'claude-code-ide-menu))) :desc "Claude Code IDE" "c" #'claude-code-ide-menu))
:config
(claude-code-ide-emacs-tools-setup)
(setq claude-code-ide-cli-path "claude"
claude-code-ide-cli-extra-flags "--dangerously-skip-permissions"
claude-code-ide-focus-claude-after-ediff t
claude-code-ide-focus-on-open t
claude-code-ide-show-claude-window-in-ediff t
claude-code-ide-switch-tab-on-ediff t
claude-code-ide-use-ide-diff t
claude-code-ide-use-side-window t
claude-code-ide-window-height 20
claude-code-ide-window-side 'right
claude-code-ide-window-width 90))
(after! gptel (after! gptel
(require 'gptel-tool-library) (require 'gptel-tool-library)
@@ -159,31 +174,48 @@
(dolist (module '("bbdb" "buffer" "elisp" "emacs" "gnus" "os" "search-and-replace" "url")) (dolist (module '("bbdb" "buffer" "elisp" "emacs" "gnus" "os" "search-and-replace" "url"))
(gptel-tool-library-load-module module))) (gptel-tool-library-load-module module)))
;; Notmuch email configuration ;; mu4e email configuration
(after! notmuch ;; Add NixOS mu4e to load-path (installed via mu.mu4e package)
(setq notmuch-search-oldest-first nil (when-let ((mu-path (executable-find "mu")))
notmuch-show-logo nil (add-to-list 'load-path
notmuch-fcc-dirs "proton/Sent" (expand-file-name "../share/emacs/site-lisp/mu4e"
(file-name-directory mu-path))))
(after! mu4e
;; User identity ;; User identity
user-mail-address "john@ogle.fyi" (setq user-mail-address "john@ogle.fyi"
user-full-name "John Ogle" user-full-name "John Ogle")
;; Maildir location (no account prefix - single account)
(setq mu4e-maildir "~/Mail"
mu4e-attachment-dir "~/Downloads")
;; Folder config (matches ~/Mail/INBOX, ~/Mail/Sent, etc.)
(setq mu4e-sent-folder "/Sent"
mu4e-drafts-folder "/Drafts"
mu4e-trash-folder "/Trash"
mu4e-refile-folder "/Archive")
;; Shortcuts for common folders
(setq mu4e-maildir-shortcuts
'((:maildir "/INBOX" :key ?i)
(:maildir "/Archive" :key ?a)
(:maildir "/Sent" :key ?s)
(:maildir "/Trash" :key ?t)))
;; Behavior settings
(setq mu4e-get-mail-command "mbsync -a"
mu4e-update-interval 300 ; 5 minutes (matches systemd timer)
mu4e-change-filenames-when-moving t ; required for mbsync
mu4e-headers-date-format "%Y-%m-%d"
mu4e-headers-time-format "%H:%M")
;; Sending mail via msmtp ;; Sending mail via msmtp
message-send-mail-function 'message-send-mail-with-sendmail (setq message-send-mail-function 'message-send-mail-with-sendmail
sendmail-program (executable-find "msmtp") sendmail-program (executable-find "msmtp")
message-sendmail-envelope-from 'header message-sendmail-envelope-from 'header
mail-envelope-from 'header mail-envelope-from 'header
mail-specify-envelope-from t mail-specify-envelope-from t))
;; Saved searches for quick access
notmuch-saved-searches
'((:name "inbox" :query "tag:inbox" :key "i")
(:name "unread" :query "tag:unread" :key "u")
(:name "flagged" :query "tag:flagged" :key "f")
(:name "sent" :query "tag:sent" :key "t")
(:name "drafts" :query "tag:draft" :key "d")
(:name "all" :query "*" :key "a"))))
;; Whenever you reconfigure a package, make sure to wrap your config in an ;; 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. ;; `after!' block, otherwise Doom's defaults may override your settings. E.g.

View File

@@ -176,8 +176,8 @@
;;zig ; C, but simpler ;;zig ; C, but simpler
:email :email
;;(mu4e +org +gmail) (mu4e +org)
notmuch ;;notmuch
;;(wanderlust +gmail) ;;(wanderlust +gmail)
:app :app

View File

@@ -7,14 +7,15 @@ let
in in
{ {
options.home.roles.email = { options.home.roles.email = {
enable = mkEnableOption "Enable email with notmuch, mbsync, and msmtp"; enable = mkEnableOption "Enable email with mu4e, mbsync, and msmtp";
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
home.packages = with pkgs; [ home.packages = with pkgs; [
isync # provides mbsync for IMAP sync isync # provides mbsync for IMAP sync
msmtp # for SMTP sending msmtp # for SMTP sending
notmuch # email indexing and search mu # email indexer for mu4e
mu.mu4e # mu4e elisp files for Emacs
openssl # for certificate management openssl # for certificate management
]; ];
@@ -42,34 +43,28 @@ in
Inbox ~/Mail/INBOX Inbox ~/Mail/INBOX
SubFolders Verbatim SubFolders Verbatim
# Channel Configuration - Sync All # Channel Configuration - Main (excludes Sent)
Channel proton Channel proton-main
Far :proton-remote: Far :proton-remote:
Near :proton-local: Near :proton-local:
Patterns * Patterns * !Sent
Create Both Create Both
Expunge Both Expunge Both
SyncState * SyncState *
'';
# Notmuch configuration # Channel Configuration - Sent (pull only)
home.file.".notmuch-config".text = '' Channel proton-sent
[database] Far :proton-remote:Sent
path=${config.home.homeDirectory}/Mail Near :proton-local:Sent
Create Near
Expunge Near
Sync Pull
SyncState *
[user] # Group both channels
name=John Ogle Group proton
primary_email=john@ogle.fyi Channel proton-main
Channel proton-sent
[new]
tags=unread;inbox;
ignore=
[search]
exclude_tags=deleted;spam;
[maildir]
synchronize_flags=true
''; '';
# msmtp configuration # msmtp configuration
@@ -103,7 +98,7 @@ in
}; };
Service = { Service = {
Type = "oneshot"; Type = "oneshot";
ExecStart = "${pkgs.bash}/bin/bash -c '${pkgs.isync}/bin/mbsync -a && ${pkgs.notmuch}/bin/notmuch new'"; 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"; Environment = "PATH=${pkgs.rbw}/bin:${pkgs.coreutils}/bin";
StandardOutput = "journal"; StandardOutput = "journal";
StandardError = "journal"; StandardError = "journal";

View File

@@ -4,6 +4,8 @@ with lib;
let let
cfg = config.home.roles.i3_sway; cfg = config.home.roles.i3_sway;
wallpaperConfig = import ../../wallpapers;
currentWallpaper = builtins.elemAt wallpaperConfig.wallpapers wallpaperConfig.currentIndex;
shared_config = recursiveUpdate rec { shared_config = recursiveUpdate rec {
modifier = "Mod4"; modifier = "Mod4";
@@ -12,6 +14,7 @@ let
keybindings = { keybindings = {
"${shared_config.modifier}+Return" = "exec ${terminal}"; "${shared_config.modifier}+Return" = "exec ${terminal}";
"${shared_config.modifier}+Shift+Return" = "exec ${cfg.browser}";
"${shared_config.modifier}+Shift+q" = "kill"; "${shared_config.modifier}+Shift+q" = "kill";
"${shared_config.modifier}+a" = "focus parent"; "${shared_config.modifier}+a" = "focus parent";
@@ -96,6 +99,12 @@ in {
options.home.roles.i3_sway = { options.home.roles.i3_sway = {
enable = mkEnableOption "i3 and Sway tiling window managers with waybar and rofi"; enable = mkEnableOption "i3 and Sway tiling window managers with waybar and rofi";
browser = mkOption {
type = types.str;
default = "firefox --new-window";
description = "Browser to use for new window keybinding";
};
extraSharedConfig = mkOption { extraSharedConfig = mkOption {
type = types.attrs; type = types.attrs;
default = {}; default = {};
@@ -281,7 +290,7 @@ in {
} }
# Set wallpaper with feh # Set wallpaper with feh
{ {
command = "feh --bg-scale ${../../wallpapers/metroid-samus-returns-kz-3440x1440.jpg}"; command = "feh ${currentWallpaper.feh} ${currentWallpaper.file}";
always = false; always = false;
notification = false; notification = false;
} }
@@ -314,7 +323,7 @@ in {
}; };
output = { output = {
"*" = { "*" = {
bg = "${../../wallpapers/metroid-samus-returns-kz-3440x1440.jpg} fill"; bg = "${currentWallpaper.file} ${currentWallpaper.sway}";
}; };
}; };
startup = [ startup = [

View File

@@ -0,0 +1,199 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.home.roles.plasma-manager-kodi;
# Define the volume control scripts as derivations
volumeUpScript = pkgs.writeShellScript "avr-volume-up" ''
#!/usr/bin/env bash
# Configuration
HA_URL="https://home-assistant.johnogle.info"
ENTITY_ID="media_player.denon_avr_s970h_2"
MAX_RETRIES=3
# Read token from KDE Wallet and strip whitespace
TOKEN=$(${pkgs.kdePackages.kwallet}/bin/kwallet-query -r ha_avr_token kdewallet -f Passwords 2>/dev/null | tr -d '[:space:]')
if [ -z "$TOKEN" ]; then
${pkgs.libnotify}/bin/notify-send -u critical "Volume Control Error" "Failed to retrieve Home Assistant token from KDE Wallet"
exit 1
fi
# Send volume up command with retry logic
for i in $(seq 1 $MAX_RETRIES); do
RESPONSE=$(${pkgs.curl}/bin/curl -s -w "\n%{http_code}" -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"entity_id\": \"$ENTITY_ID\"}" \
"$HA_URL/api/services/media_player/volume_up" 2>&1)
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
if [ "$HTTP_CODE" = "200" ]; then
exit 0
fi
# Wait before retry (except on last attempt)
if [ $i -lt $MAX_RETRIES ]; then
sleep 0.5
fi
done
# All retries failed
${pkgs.libnotify}/bin/notify-send -u critical "Volume Control Error" "Failed to increase volume after $MAX_RETRIES attempts"
exit 1
'';
volumeDownScript = pkgs.writeShellScript "avr-volume-down" ''
#!/usr/bin/env bash
# Configuration
HA_URL="https://home-assistant.johnogle.info"
ENTITY_ID="media_player.denon_avr_s970h_2"
MAX_RETRIES=3
# Read token from KDE Wallet and strip whitespace
TOKEN=$(${pkgs.kdePackages.kwallet}/bin/kwallet-query -r ha_avr_token kdewallet -f Passwords 2>/dev/null | tr -d '[:space:]')
if [ -z "$TOKEN" ]; then
${pkgs.libnotify}/bin/notify-send -u critical "Volume Control Error" "Failed to retrieve Home Assistant token from KDE Wallet"
exit 1
fi
# Send volume down command with retry logic
for i in $(seq 1 $MAX_RETRIES); do
RESPONSE=$(${pkgs.curl}/bin/curl -s -w "\n%{http_code}" -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"entity_id\": \"$ENTITY_ID\"}" \
"$HA_URL/api/services/media_player/volume_down" 2>&1)
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
if [ "$HTTP_CODE" = "200" ]; then
exit 0
fi
# Wait before retry (except on last attempt)
if [ $i -lt $MAX_RETRIES ]; then
sleep 0.5
fi
done
# All retries failed
${pkgs.libnotify}/bin/notify-send -u critical "Volume Control Error" "Failed to decrease volume after $MAX_RETRIES attempts"
exit 1
'';
volumeMuteScript = pkgs.writeShellScript "avr-volume-mute" ''
#!/usr/bin/env bash
# Configuration
HA_URL="https://home-assistant.johnogle.info"
ENTITY_ID="media_player.denon_avr_s970h_2"
MAX_RETRIES=3
# Read token from KDE Wallet and strip whitespace
TOKEN=$(${pkgs.kdePackages.kwallet}/bin/kwallet-query -r ha_avr_token kdewallet -f Passwords 2>/dev/null | tr -d '[:space:]')
if [ -z "$TOKEN" ]; then
${pkgs.libnotify}/bin/notify-send -u critical "Volume Control Error" "Failed to retrieve Home Assistant token from KDE Wallet"
exit 1
fi
# Get current mute state
STATE_RESPONSE=$(${pkgs.curl}/bin/curl -s -H "Authorization: Bearer $TOKEN" \
"$HA_URL/api/states/$ENTITY_ID")
CURRENT_MUTE=$(echo "$STATE_RESPONSE" | ${pkgs.jq}/bin/jq -r '.attributes.is_volume_muted // false')
# Toggle: if currently muted (true), unmute (false), and vice versa
if [ "$CURRENT_MUTE" = "true" ]; then
NEW_MUTE="false"
NOTIFY_MSG="Unmuted"
else
NEW_MUTE="true"
NOTIFY_MSG="Muted"
fi
# Send mute toggle command with retry logic
for i in $(seq 1 $MAX_RETRIES); do
RESPONSE=$(${pkgs.curl}/bin/curl -s -w "\n%{http_code}" -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"entity_id\": \"$ENTITY_ID\", \"is_volume_muted\": $NEW_MUTE}" \
"$HA_URL/api/services/media_player/volume_mute" 2>&1)
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
if [ "$HTTP_CODE" = "200" ]; then
exit 0
fi
# Wait before retry (except on last attempt)
if [ $i -lt $MAX_RETRIES ]; then
sleep 0.5
fi
done
# All retries failed
${pkgs.libnotify}/bin/notify-send -u critical "Volume Control Error" "Failed to toggle mute after $MAX_RETRIES attempts"
exit 1
'';
in
{
options.home.roles.plasma-manager-kodi = {
enable = mkEnableOption "KDE Plasma volume control for kodi user via Home Assistant";
};
config = mkIf cfg.enable {
programs.plasma = {
enable = true;
overrideConfig = true;
# Disable default kmix volume shortcuts to prevent conflicts
shortcuts.kmix = {
"increase_volume" = "none";
"decrease_volume" = "none";
"mute" = "none";
};
# Define custom volume control commands with key bindings
hotkeys.commands = {
"volume-up-avr" = {
name = "Volume Up AVR";
key = "Volume Up";
command = toString volumeUpScript;
};
"volume-down-avr" = {
name = "Volume Down AVR";
key = "Volume Down";
command = toString volumeDownScript;
};
"volume-mute-avr" = {
name = "Mute Toggle AVR";
key = "Volume Mute";
command = toString volumeMuteScript;
};
};
# KDE Settings customization
configFile = {
# Session restore settings
"ksmserverrc"."General"."loginMode" = "emptySession";
# Screen locking settings
"kscreenlockerrc"."Daemon"."Autolock" = false;
"kscreenlockerrc"."Daemon"."LockOnResume" = false;
# Theme settings
"kdeglobals"."KDE"."LookAndFeelPackage" = "org.kde.breezedark.desktop";
};
};
};
}

View File

@@ -4,6 +4,8 @@ with lib;
let let
cfg = config.home.roles.plasma-manager; cfg = config.home.roles.plasma-manager;
wallpaperConfig = import ../../wallpapers;
currentWallpaper = builtins.elemAt wallpaperConfig.wallpapers wallpaperConfig.currentIndex;
in in
{ {
options.home.roles.plasma-manager = { options.home.roles.plasma-manager = {
@@ -181,7 +183,7 @@ in
plasma-localerc.Formats.LANG = "en_US.UTF-8"; plasma-localerc.Formats.LANG = "en_US.UTF-8";
# Set wallpaper for all desktops # Set wallpaper for all desktops
plasmarc.Wallpapers.usersWallpapers = "${../../wallpapers/metroid-samus-returns-kz-3440x1440.jpg}"; plasmarc.Wallpapers.usersWallpapers = "${currentWallpaper.file}";
}; };
}; };
}; };

View File

@@ -0,0 +1,45 @@
# Wallpaper rotation system
# The currentIndex is incremented by `nix run .#rotate-wallpaper`
# and gets committed as part of `nix run .#upgrade`
{
currentIndex = 1; # Index into wallpapers list
wallpapers = [
{
name = "metroid-samus-returns";
file = ./metroid-samus-returns-kz-3440x1440.jpg;
sway = "fill";
feh = "--bg-fill";
}
{
name = "metroid3_map";
file = ./metroid3_map.gif;
sway = "fit";
feh = "--bg-max";
}
{
name = "super-metroid-gunship-cavern";
file = ./super-metroid-gunship-cavern.jpg;
sway = "fit";
feh = "--bg-max";
}
{
name = "super-metroid-samus-statue";
file = ./super-metroid-samus-statue.png;
sway = "fit";
feh = "--bg-max";
}
{
name = "metroid-samus-action-4k";
file = ./metroid-samus-action-4k.jpg;
sway = "fit";
feh = "--bg-max";
}
{
name = "metroid-creature-minimalist";
file = ./metroid-creature-minimalist.jpg;
sway = "fit";
feh = "--bg-max";
}
];
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 MiB

View File

@@ -26,11 +26,20 @@ with lib;
enable = true; enable = true;
autologin = true; autologin = true;
wayland = true; wayland = true;
jellyfinScaleFactor = 2.5; jellyfinScaleFactor = 1.0;
}; };
nfs-mounts.enable = true;
users.enable = true; users.enable = true;
}; };
# Enable KDE Wallet PAM integration for auto-unlock
security.pam.services.sddm = {
kwallet = {
enable = true;
package = pkgs.kdePackages.kwallet-pam;
};
};
# Use the systemd-boot EFI boot loader. # Use the systemd-boot EFI boot loader.
boot.loader.systemd-boot.enable = true; boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true; boot.loader.efi.canTouchEfiVariables = true;

View File

@@ -0,0 +1,423 @@
# Migration Plan: Arch Linux to NixOS on john-endesktop (ZFS/NFS Server)
## Overview
This document outlines the plan to migrate the john-endesktop server from Arch Linux to NixOS while maintaining the existing ZFS pools and NFS exports that serve your k3s cluster.
## Current System State
### Hardware
- **Boot disk**: nvme0n1
- nvme0n1p3: 1000M EFI partition (UUID: F5C6-D570)
- nvme0n1p4: 120GB ext4 / (current Arch root)
- nvme0n1p5: 810GB - **Target for NixOS** (being removed from media pool)
- **Network**: enp0s31f6 @ 10.0.0.43/24 (DHCP)
### ZFS Pools
- **media**: ~3.5TB JBOD pool (2 drives after nvme0n1p5 removal)
- wwn-0x50014ee2ba653d70-part2
- ata-WDC_WD20EZBX-00AYRA0_WD-WX62D627X7Z8-part2
- Contains: /media/media/nix (bind mounted to /nix on Arch)
- NFS: Shared to 10.0.0.0/24 via ZFS sharenfs property
- **swarmvols**: 928GB mirror pool - **PRODUCTION DATA**
- wwn-0x5002538f52707e2d-part2
- wwn-0x5002538f52707e81-part2
- Contains: iocage jails and k3s persistent volumes
- NFS: Shared to 10.0.0.0/24 via ZFS sharenfs property
- Backed up nightly to remote borg
### Services
- NFS server exporting /media and /swarmvols to k3s cluster
- ZFS managing pools with automatic exports via sharenfs property
## Prerequisites
### Before Starting
1. ✅ Ensure nvme0n1p5 removal from media pool is complete
```bash
ssh 10.0.0.43 "zpool status media"
# Should show no "removing" devices
```
2. ✅ Verify recent backups exist
```bash
# Verify swarmvols backup is recent (< 24 hours)
# Check your borg backup system
```
3. ✅ Notify k3s cluster users of planned maintenance window
- NFS shares will be unavailable during migration
- Estimate: 30-60 minutes downtime
4. ✅ Build NixOS configuration from your workstation
```bash
cd ~/nixos-configs
nix build .#nixosConfigurations.john-endesktop.config.system.build.toplevel
```
## Migration Steps
### Phase 1: Prepare NixOS Installation Media
1. **Download NixOS minimal ISO**
```bash
wget https://channels.nixos.org/nixos-25.11/latest-nixos-minimal-x86_64-linux.iso
```
2. **Create bootable USB**
```bash
# Identify USB device (e.g., /dev/sdb)
lsblk
# Write ISO to USB
sudo dd if=latest-nixos-minimal-x86_64-linux.iso of=/dev/sdX bs=4M status=progress
sudo sync
```
### Phase 2: Backup and Shutdown
1. **On the server, verify ZFS pool status**
```bash
ssh 10.0.0.43 "zpool status"
ssh 10.0.0.43 "zfs list"
```
2. **Export ZFS pools cleanly**
```bash
ssh 10.0.0.43 "sudo zpool export media"
ssh 10.0.0.43 "sudo zpool export swarmvols"
```
3. **Shutdown Arch Linux**
```bash
ssh 10.0.0.43 "sudo shutdown -h now"
```
### Phase 3: Install NixOS
1. **Boot from NixOS USB**
- Insert USB drive
- Power on and select USB in boot menu
2. **Connect to network**
```bash
# If DHCP doesn't work automatically:
sudo systemctl start dhcpcd
ip a # Verify you have 10.0.0.43 or another IP
```
3. **Enable SSH for remote installation (recommended)**
```bash
# Set password for nixos user
sudo passwd nixos
# Start SSH
sudo systemctl start sshd
# From your workstation:
ssh nixos@10.0.0.43
```
4. **Partition nvme0n1p5 with btrfs**
```bash
# Verify the device is clear
lsblk
sudo wipefs -a /dev/nvme0n1p5
# Create btrfs filesystem
sudo mkfs.btrfs -L nixos /dev/nvme0n1p5
# Mount and create subvolumes
sudo mount /dev/nvme0n1p5 /mnt
sudo btrfs subvolume create /mnt/@
sudo btrfs subvolume create /mnt/@home
sudo btrfs subvolume create /mnt/@nix
sudo btrfs subvolume create /mnt/@log
sudo umount /mnt
# Mount root subvolume
sudo mount -o subvol=@,compress=zstd,noatime /dev/nvme0n1p5 /mnt
# Create mount points
sudo mkdir -p /mnt/{boot,home,nix,var/log}
# Mount other subvolumes
sudo mount -o subvol=@home,compress=zstd,noatime /dev/nvme0n1p5 /mnt/home
sudo mount -o subvol=@nix,compress=zstd,noatime /dev/nvme0n1p5 /mnt/nix
sudo mount -o subvol=@log,compress=zstd,noatime /dev/nvme0n1p5 /mnt/var/log
# Mount EFI partition
sudo mount /dev/nvme0n1p3 /mnt/boot
```
5. **Import ZFS pools**
```bash
# Import pools (should be visible)
sudo zpool import
# Import with force if needed due to hostid
sudo zpool import -f media
sudo zpool import -f swarmvols
# Verify pools are mounted
zfs list
ls -la /media /swarmvols
```
6. **Generate initial hardware configuration**
```bash
sudo nixos-generate-config --root /mnt
```
7. **Get the new root filesystem UUID**
```bash
blkid /dev/nvme0n1p5
# Note the UUID for updating hardware-configuration.nix
```
8. **Copy your NixOS configuration to the server**
```bash
# From your workstation:
scp -r ~/nixos-configs/machines/john-endesktop/* nixos@10.0.0.43:/tmp/
# On server:
sudo mkdir -p /mnt/etc/nixos
sudo cp /tmp/configuration.nix /mnt/etc/nixos/
sudo cp /tmp/hardware-configuration.nix /mnt/etc/nixos/
# Edit hardware-configuration.nix to update the root filesystem UUID
sudo nano /mnt/etc/nixos/hardware-configuration.nix
# Change: device = "/dev/disk/by-uuid/CHANGE-THIS-TO-YOUR-UUID";
# To: device = "/dev/disk/by-uuid/[UUID from blkid]";
```
9. **Install NixOS**
```bash
sudo nixos-install
# Set root password when prompted
# Set user password
sudo nixos-install --no-root-passwd
```
10. **Reboot into NixOS**
```bash
sudo reboot
# Remove USB drive
```
### Phase 4: Post-Installation Verification
1. **Boot into NixOS and verify system**
```bash
ssh johno@10.0.0.43
# Check NixOS version
nixos-version
# Verify hostname
hostname # Should be: john-endesktop
```
2. **Verify ZFS pools imported correctly**
```bash
zpool status
zpool list
zfs list
# Check for hostid mismatch warnings (should be gone)
# Verify both pools show ONLINE status
```
3. **Verify NFS exports are active**
```bash
sudo exportfs -v
systemctl status nfs-server
# Should see /media and /swarmvols exported to 10.0.0.0/24
```
4. **Test NFS mount from another machine**
```bash
# From a k3s node or your workstation:
sudo mount -t nfs 10.0.0.43:/swarmvols /mnt
ls -la /mnt
sudo umount /mnt
sudo mount -t nfs 10.0.0.43:/media /mnt
ls -la /mnt
sudo umount /mnt
```
5. **Verify ZFS sharenfs properties preserved**
```bash
zfs get sharenfs media
zfs get sharenfs swarmvols
# Should show: sec=sys,mountpoint,no_subtree_check,no_root_squash,rw=@10.0.0.0/24
```
6. **Check swap device**
```bash
swapon --show
free -h
# Should show /dev/zvol/media/swap
```
### Phase 5: Restore k3s Cluster Access
1. **Restart k3s nodes or remount NFS shares**
```bash
# On each k3s node:
sudo systemctl restart k3s # or k3s-agent
```
2. **Verify k3s pods have access to persistent volumes**
```bash
# On k3s master:
kubectl get pv
kubectl get pvc
# Check that volumes are bound and accessible
```
## Rollback Plan
If something goes wrong during migration, you can roll back to Arch Linux:
### Quick Rollback (If NixOS won't boot)
1. **Boot from NixOS USB (or Arch USB)**
2. **Import ZFS pools**
```bash
sudo zpool import -f media
sudo zpool import -f swarmvols
```
3. **Start NFS manually (temporary)**
```bash
sudo mkdir -p /media /swarmvols
sudo systemctl start nfs-server
sudo exportfs -o rw,sync,no_subtree_check,no_root_squash 10.0.0.0/24:/media
sudo exportfs -o rw,sync,no_subtree_check,no_root_squash 10.0.0.0/24:/swarmvols
sudo exportfs -v
```
This will restore k3s cluster access immediately while you diagnose.
4. **Boot back into Arch Linux**
```bash
# Reboot and select nvme0n1p4 (Arch) in GRUB/boot menu
sudo reboot
```
5. **Verify Arch boots and services start**
```bash
ssh johno@10.0.0.43
zpool status
systemctl status nfs-server
```
### Full Rollback (If needed)
1. **Follow Quick Rollback steps above**
2. **Re-add nvme0n1p5 to media pool (if desired)**
```bash
# Only if you want to restore the original configuration
sudo zpool add media /dev/nvme0n1p5
```
3. **Clean up NixOS partition**
```bash
# If you want to reclaim nvme0n1p5 for other uses
sudo wipefs -a /dev/nvme0n1p5
```
## Risk Mitigation
### Data Safety
- ✅ **swarmvols** (production): Mirrored + nightly borg backups
- ⚠️ **media** (important): JBOD - no redundancy, but not catastrophic
- ✅ **NixOS install**: Separate partition, doesn't touch ZFS pools
- ✅ **Arch Linux**: Remains bootable on nvme0n1p4 until verified
### Service Continuity
- Downtime: 30-60 minutes expected
- k3s cluster: Will reconnect automatically when NFS returns
- Rollback time: < 10 minutes to restore Arch
### Testing Approach
1. Test NFS exports from NixOS live environment before installation
2. Test single NFS mount from k3s node before full cluster restart
3. Keep Arch Linux boot option until 24-48 hours of stable NixOS operation
## Post-Migration Tasks
After successful migration and 24-48 hours of stable operation:
1. **Update k3s NFS mounts (if needed)**
- Verify no hardcoded references to old system
2. **Optional: Repurpose Arch partition**
```bash
# After you're confident NixOS is stable
# You can wipe nvme0n1p4 and repurpose it
```
3. **Update documentation**
- Update infrastructure docs with NixOS configuration
- Document any deviations from this plan
4. **Consider setting up NixOS remote deployment**
```bash
# From your workstation:
nixos-rebuild switch --target-host johno@10.0.0.43 --flake .#john-endesktop
```
## Timeline
- **Preparation**: 1-2 hours (testing config build, downloading ISO)
- **Migration window**: 1-2 hours (installation + verification)
- **Verification period**: 24-48 hours (before removing Arch)
- **Total**: ~3 days from start to declaring success
## Emergency Contacts
- Borg backup location: [Document your borg repo location]
- K3s cluster nodes: [Document your k3s nodes]
- Critical services on k3s: [Document what's running that depends on these NFS shares]
## Checklist
Pre-migration:
- [x] nvme0n1p5 removal from media pool complete
- [ ] Recent backup verified (< 24 hours)
- [ ] Maintenance window scheduled
- [ ] NixOS ISO downloaded
- [ ] Bootable USB created
- [ ] NixOS config builds successfully
During migration:
- [ ] ZFS pools exported
- [ ] Arch Linux shutdown cleanly
- [ ] Booted from NixOS USB
- [ ] nvme0n1p5 formatted with btrfs
- [ ] Btrfs subvolumes created
- [ ] ZFS pools imported
- [ ] NixOS installed
- [ ] Root password set
Post-migration:
- [ ] NixOS boots successfully
- [ ] ZFS pools mounted automatically
- [ ] NFS server running
- [ ] NFS exports verified
- [ ] Test mount from k3s node successful
- [ ] k3s cluster reconnected
- [ ] Persistent volumes accessible
- [ ] No hostid warnings in zpool status
- [ ] Arch Linux still bootable (for rollback)
Final verification (after 24-48 hours):
- [ ] All services stable
- [ ] No unexpected issues
- [ ] Performance acceptable
- [ ] Ready to remove Arch partition (optional)
- [ ] Ready to remove /swarmvols/media-backup (optional)

View File

@@ -0,0 +1,112 @@
# NixOS configuration for john-endesktop (ZFS/NFS server)
# Migrated from Arch Linux to provide ZFS pools via NFS to k3s cluster
{ config, lib, pkgs, ... }:
with lib;
{
imports = [
./hardware-configuration.nix
];
# Boot configuration
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
# ZFS support
boot.supportedFilesystems = [ "zfs" ];
boot.zfs.forceImportRoot = false;
boot.zfs.extraPools = [ "media" "swarmvols" ];
# Set ZFS hostid to match current system (from Arch Linux)
# This resolves the hostid mismatch warnings
networking.hostId = "007f0101";
# Hostname
networking.hostName = "john-endesktop";
# Network configuration - using DHCP on enp0s31f6
networking.useDHCP = false;
networking.interfaces.enp0s31f6.useDHCP = true;
# NFS Server configuration
services.nfs.server = {
enable = true;
# NFS protocol versions
# v3 for broader compatibility, v4 for better performance
exports = ''
# These are managed by ZFS sharenfs properties
# but we enable the NFS server here
'';
};
# Enable NFS4 with proper configuration
services.rpcbind.enable = true;
# Firewall configuration for NFS
networking.firewall = {
enable = true;
allowedTCPPorts = [
111 # rpcbind
2049 # nfs
4000 # nfs callback
4001 # nlockmgr
4002 # mountd
20048 # mountd
];
allowedUDPPorts = [
111 # rpcbind
2049 # nfs
4000 # nfs callback
4001 # nlockmgr
4002 # mountd
20048 # mountd
];
# Allow NFS from local network
extraCommands = ''
iptables -A nixos-fw -p tcp -s 10.0.0.0/24 -j ACCEPT
iptables -A nixos-fw -p udp -s 10.0.0.0/24 -j ACCEPT
'';
};
# ZFS maintenance
services.zfs = {
autoScrub = {
enable = true;
interval = "monthly";
};
trim = {
enable = true;
interval = "weekly";
};
};
# Basic system packages
environment.systemPackages = with pkgs; [
vim
git
htop
tmux
zfs
];
# Enable SSH
services.openssh = {
enable = true;
settings = {
PermitRootLogin = "no";
PasswordAuthentication = true;
};
};
# User configuration
roles.users.enable = true;
# Time zone
time.timeZone = "America/Los_Angeles"; # Adjust as needed
# NixOS version
system.stateVersion = "25.11";
}

View File

@@ -0,0 +1,48 @@
# Hardware configuration for john-endesktop
# This file should be regenerated after NixOS installation using:
# nixos-generate-config --show-hardware-config
{ config, lib, pkgs, modulesPath, ... }:
{
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
];
# Boot configuration
boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
# File systems - these will need to be updated after installation
# The nvme0n1p5 partition will be formatted as btrfs for NixOS root
fileSystems."/" = {
# Update this device path after installation
device = "/dev/disk/by-uuid/CHANGE-THIS-TO-YOUR-UUID";
fsType = "btrfs";
options = [ "subvol=@" "compress=zstd" "noatime" ];
};
fileSystems."/boot" = {
# This should match your current EFI partition
device = "/dev/disk/by-uuid/F5C6-D570";
fsType = "vfat";
options = [ "fmask=0022" "dmask=0022" ];
};
# ZFS pools - these are imported by ZFS, not managed by fileSystems
# The pools should be imported automatically via boot.zfs.extraPools
# /media and /swarmvols will be mounted by ZFS
# Swap - using ZFS zvol
swapDevices = [
{ device = "/dev/zvol/media/swap"; }
];
# CPU microcode
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
# Networking
networking.useDHCP = lib.mkDefault true;
}

View File

@@ -39,6 +39,17 @@
boot.loader.efi.canTouchEfiVariables = true; boot.loader.efi.canTouchEfiVariables = true;
boot.initrd.luks.devices."luks-b614167b-9045-4234-a441-ac6f60a96d81".device = "/dev/disk/by-uuid/b614167b-9045-4234-a441-ac6f60a96d81"; boot.initrd.luks.devices."luks-b614167b-9045-4234-a441-ac6f60a96d81".device = "/dev/disk/by-uuid/b614167b-9045-4234-a441-ac6f60a96d81";
services.logind.settings.Login = {
HandleLidSwitch = "suspend-then-hibernate";
HandlePowerKey = "hibernate";
HandlePowerKeyLongPress = "poweroff";
};
systemd.sleep.extraConfig = ''
HibernateDelaySec=30m
SuspendState=mem
'';
networking.hostName = "nix-book"; # Define your hostname. networking.hostName = "nix-book"; # Define your hostname.
# networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant.

View File

@@ -5,24 +5,24 @@
}: }:
let let
version = "2.0.75"; version = "2.0.76";
srcs = { srcs = {
aarch64-darwin = { aarch64-darwin = {
url = "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/${version}/darwin-arm64/claude"; url = "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/${version}/darwin-arm64/claude";
sha256 = "a96eb18218e112486b7ecebd1551d927ffb310ab5fb06d2e8db25fb31367537e"; sha256 = "b76f6d4d09233e67295897b0a1ed2e22d7afa406431529d8b1b532b63b8cbcbd";
}; };
x86_64-darwin = { x86_64-darwin = {
url = "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/${version}/darwin-x64/claude"; url = "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/${version}/darwin-x64/claude";
sha256 = "e27313053d3268a0bc1e0080f8c2ef7155325f0a95e72971163eef698a71e829"; sha256 = "9d94582f0af5d2201f1c907bf24ff8d216104b897ee0b24795a6c081f40e08d7";
}; };
x86_64-linux = { x86_64-linux = {
url = "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/${version}/linux-x64/claude"; url = "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/${version}/linux-x64/claude";
sha256 = "62160f8766681d8c933e9133398d3dde6ad0df08038881a66eddb993b4b6a33f"; sha256 = "5dcdb480f91ba0df0bc8bd6aff148d3dfd3883f0899eeb5b9427a8b0abe7a687";
}; };
aarch64-linux = { aarch64-linux = {
url = "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/${version}/linux-arm64/claude"; url = "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/${version}/linux-arm64/claude";
sha256 = "681fbd1a84b2de883dc954441693766b43ea4faafb3e72b88c99a33645cd3507"; sha256 = "f64a994c8e5bfb84d7242cebbec75d6919db2ee46d50b8fc7a88d5066db193f9";
}; };
}; };

View File

@@ -33,7 +33,8 @@ YELLOW='\033[1;33m'
NC='\033[0m' # No Color NC='\033[0m' # No Color
CASK_URL="https://raw.githubusercontent.com/Homebrew/homebrew-cask/HEAD/Casks/c/claude-code.rb" CASK_URL="https://raw.githubusercontent.com/Homebrew/homebrew-cask/HEAD/Casks/c/claude-code.rb"
NIX_FILE="$(dirname "$0")/default.nix" REPO_ROOT="${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"
NIX_FILE="$REPO_ROOT/packages/claude-code/default.nix"
echo "Fetching latest claude-code version from Homebrew cask..." echo "Fetching latest claude-code version from Homebrew cask..."

View File

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

View File

@@ -0,0 +1,26 @@
{ lib, buildGoModule, fetchFromGitHub }:
buildGoModule rec {
pname = "perles";
version = "unstable-2025-01-09";
src = fetchFromGitHub {
owner = "zjrosen";
repo = "perles";
rev = "main";
hash = "sha256-JgRayb4+mJ1r0AtdnQfqAw2+QRte+licsfZOaRgYqcs=";
};
vendorHash = "sha256-R7UWTdBuPteneRqxrWK51nqLtZwDsqQoMAcohN4fyak=";
# Tests require a real git repository context
doCheck = false;
meta = with lib; {
description = "A TUI for the Beads issue tracking system with BQL query language";
homepage = "https://github.com/zjrosen/perles";
license = licenses.mit;
maintainers = [ ];
mainProgram = "perles";
};
}

View File

@@ -22,6 +22,8 @@ in
# indiviudal cores # indiviudal cores
#retroarch-full #retroarch-full
ryubing ryubing
yarg
]; ];
programs.steam = { programs.steam = {

View File

@@ -0,0 +1,41 @@
#!/usr/bin/env bash
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Configuration
REPO_ROOT="${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"
WALLPAPER_FILE="$REPO_ROOT/home/wallpapers/default.nix"
echo -e "${GREEN}Rotating wallpaper...${NC}"
# Check if file exists
if [[ ! -f "$WALLPAPER_FILE" ]]; then
echo -e "${RED}Error: $WALLPAPER_FILE not found${NC}"
exit 1
fi
# Get current index
CURRENT_INDEX=$(grep -oP 'currentIndex = \K\d+' "$WALLPAPER_FILE")
echo -e "Current index: ${YELLOW}$CURRENT_INDEX${NC}"
# Count wallpapers (count occurrences of "name = " in the wallpapers list)
WALLPAPER_COUNT=$(grep -c 'name = "' "$WALLPAPER_FILE")
echo -e "Total wallpapers: ${YELLOW}$WALLPAPER_COUNT${NC}"
# Calculate next index (wrap around)
NEXT_INDEX=$(( (CURRENT_INDEX + 1) % WALLPAPER_COUNT ))
echo -e "Next index: ${YELLOW}$NEXT_INDEX${NC}"
# Update the currentIndex
sed -i "s/currentIndex = $CURRENT_INDEX;/currentIndex = $NEXT_INDEX;/" "$WALLPAPER_FILE"
echo -e "${GREEN}Successfully rotated wallpaper!${NC}"
echo -e " Old index: ${YELLOW}$CURRENT_INDEX${NC}"
echo -e " New index: ${YELLOW}$NEXT_INDEX${NC}"
echo ""
echo "Rebuild your system to apply the new wallpaper."

46
scripts/upgrade.sh Normal file
View File

@@ -0,0 +1,46 @@
#!/usr/bin/env bash
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
REPO_ROOT="${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE} NixOS Configuration Major Upgrade${NC}"
echo -e "${BLUE}========================================${NC}"
echo ""
# Step 1: Update flake inputs
echo -e "${GREEN}[1/4] Updating flake inputs...${NC}"
cd "$REPO_ROOT"
nix flake update
echo ""
# Step 2: Update Doom Emacs
echo -e "${GREEN}[2/4] Updating Doom Emacs...${NC}"
"$REPO_ROOT/scripts/update-doomemacs.sh"
echo ""
# Step 3: Update Claude Code
echo -e "${GREEN}[3/4] Updating Claude Code...${NC}"
"$REPO_ROOT/packages/claude-code/update.sh"
echo ""
# Step 4: Rotate wallpaper
echo -e "${GREEN}[4/4] Rotating wallpaper...${NC}"
"$REPO_ROOT/scripts/rotate-wallpaper.sh"
echo ""
echo -e "${BLUE}========================================${NC}"
echo -e "${GREEN}Upgrade complete!${NC}"
echo -e "${BLUE}========================================${NC}"
echo ""
echo "Next steps:"
echo " 1. Review changes: git diff"
echo " 2. Rebuild system: sudo nixos-rebuild switch --flake ."
echo " 3. If satisfied, commit: git add -A && git commit -m 'chore: Major upgrade'"