Compare commits

..

28 Commits

Author SHA1 Message Date
58d7493c1b Pin perles package to specific commit for reproducibility
Replace rev = "main" with the specific commit hash 64eba96c0a9b663ef3a206c8f07b71ab34f46df4
to ensure reproducible builds. Using branch names as revisions can cause
unexpected changes when the upstream branch advances.
2026-01-10 11:00:33 -08:00
009b84656f [john-endesktop] Update migration plan with completed pre-migration items 2026-01-10 10:49:04 -08:00
ef4e4509d3 [john-endesktop] Remove swap 2026-01-10 09:43:22 -08:00
cd6b528692 [john-endesktop] Update with actual disk ids 2026-01-10 09:34:28 -08:00
3914b54c73 actually actually finish for real? 2026-01-09 11:24:52 -08:00
9aa74258f9 actually finish beads-sync migration 2026-01-09 11:23:46 -08:00
64dda20aa4 finish migration to beads-sync 2026-01-09 11:22:58 -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
32 changed files with 649 additions and 92 deletions

39
.beads/.gitignore vendored Normal file
View File

@@ -0,0 +1,39 @@
# SQLite databases
*.db
*.db?*
*.db-journal
*.db-wal
*.db-shm
# Daemon runtime files
daemon.lock
daemon.log
daemon.pid
bd.sock
sync-state.json
last-touched
# Local version tracking (prevents upgrade notification spam after git ops)
.local_version
# Legacy database files
db.sqlite
bd.db
# Worktree redirect file (contains relative path to main repo's .beads/)
# Must not be committed as paths would be wrong in other clones
redirect
# Merge artifacts (temporary files from 3-way merge)
beads.base.jsonl
beads.base.meta.json
beads.left.jsonl
beads.left.meta.json
beads.right.jsonl
beads.right.meta.json
# 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.
# The JSONL files (issues.jsonl, interactions.jsonl) and config files
# are tracked by git by default since no pattern above ignores them.

0
.beads/.sync.lock Normal file
View File

81
.beads/README.md Normal file
View File

@@ -0,0 +1,81 @@
# Beads - AI-Native Issue Tracking
Welcome to Beads! This repository uses **Beads** for issue tracking - a modern, AI-native tool designed to live directly in your codebase alongside your code.
## What is Beads?
Beads is issue tracking that lives in your repo, making it perfect for AI coding agents and developers who want their issues close to their code. No web UI required - everything works through the CLI and integrates seamlessly with git.
**Learn more:** [github.com/steveyegge/beads](https://github.com/steveyegge/beads)
## Quick Start
### Essential Commands
```bash
# Create new issues
bd create "Add user authentication"
# View all issues
bd list
# View issue details
bd show <issue-id>
# Update issue status
bd update <issue-id> --status in_progress
bd update <issue-id> --status done
# Sync with git remote
bd sync
```
### Working with Issues
Issues in Beads are:
- **Git-native**: Stored in `.beads/issues.jsonl` and synced like code
- **AI-friendly**: CLI-first design works perfectly with AI coding agents
- **Branch-aware**: Issues can follow your branch workflow
- **Always in sync**: Auto-syncs with your commits
## Why Beads?
**AI-Native Design**
- Built specifically for AI-assisted development workflows
- CLI-first interface works seamlessly with AI coding agents
- No context switching to web UIs
🚀 **Developer Focused**
- Issues live in your repo, right next to your code
- Works offline, syncs when you push
- Fast, lightweight, and stays out of your way
🔧 **Git Integration**
- Automatic sync with git commits
- Branch-aware issue tracking
- Intelligent JSONL merge resolution
## Get Started with Beads
Try Beads in your own projects:
```bash
# Install Beads
curl -sSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash
# Initialize in your repo
bd init
# Create your first issue
bd create "Try out Beads"
```
## Learn More
- **Documentation**: [github.com/steveyegge/beads/docs](https://github.com/steveyegge/beads/tree/main/docs)
- **Quick Start Guide**: Run `bd quickstart`
- **Examples**: [github.com/steveyegge/beads/examples](https://github.com/steveyegge/beads/tree/main/examples)
---
*Beads: Issue tracking that moves at the speed of thought*

62
.beads/config.yaml Normal file
View File

@@ -0,0 +1,62 @@
# Beads Configuration File
# This file configures default behavior for all bd commands in this repository
# All settings can also be set via environment variables (BD_* prefix)
# or overridden with command-line flags
# Issue prefix for this repository (used by bd init)
# If not set, bd init will auto-detect from directory name
# Example: issue-prefix: "myproject" creates issues like "myproject-1", "myproject-2", etc.
# issue-prefix: ""
# Use no-db mode: load from JSONL, no SQLite, write back after each command
# When true, bd will use .beads/issues.jsonl as the source of truth
# instead of SQLite database
# no-db: false
# Disable daemon for RPC communication (forces direct database access)
# no-daemon: false
# Disable auto-flush of database to JSONL after mutations
# no-auto-flush: false
# Disable auto-import from JSONL when it's newer than database
# no-auto-import: false
# Enable JSON output by default
# json: false
# Default actor for audit trails (overridden by BD_ACTOR or --actor)
# actor: ""
# Path to database (overridden by BEADS_DB or --db)
# db: ""
# Auto-start daemon if not running (can also use BEADS_AUTO_START_DAEMON)
# auto-start-daemon: true
# Debounce interval for auto-flush (can also use BEADS_FLUSH_DEBOUNCE)
# flush-debounce: "5s"
# Git branch for beads commits (bd sync will commit to this branch)
# IMPORTANT: Set this for team projects so all clones use the same sync branch.
# This setting persists across clones (unlike database config which is gitignored).
# Can also use BEADS_SYNC_BRANCH env var for local override.
# If not set, bd sync will require you to run 'bd config set sync.branch <branch>'.
sync-branch: "beads-sync"
# Multi-repo configuration (experimental - bd-307)
# Allows hydrating from multiple repositories and routing writes to the correct JSONL
# repos:
# primary: "." # Primary repo (where this database lives)
# additional: # Additional repos to hydrate from (read-only)
# - ~/beads-planning # Personal planning repo
# - ~/work-planning # Work planning repo
# Integration settings (access with 'bd config get/set')
# These are stored in the database, not in this file:
# - jira.url
# - jira.project
# - linear.url
# - linear.api-key
# - github.org
# - github.repo

View File

4
.beads/metadata.json Normal file
View File

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

0
.beads/sync_base.jsonl Normal file
View File

3
.gitattributes vendored Normal file
View File

@@ -0,0 +1,3 @@
# Use bd merge for beads JSONL files
.beads/issues.jsonl merge=beads

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
@@ -234,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";
};
} }
); );
}; };

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))))
;; User identity (after! mu4e
user-mail-address "john@ogle.fyi" ;; User identity
user-full-name "John Ogle" (setq user-mail-address "john@ogle.fyi"
user-full-name "John Ogle")
;; Sending mail via msmtp ;; Maildir location (no account prefix - single account)
message-send-mail-function 'message-send-mail-with-sendmail (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
(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

@@ -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

@@ -170,6 +170,7 @@ This document outlines the plan to migrate the john-endesktop server from Arch L
```bash ```bash
blkid /dev/nvme0n1p5 blkid /dev/nvme0n1p5
# Note the UUID for updating hardware-configuration.nix # Note the UUID for updating hardware-configuration.nix
/dev/nvme0n1p5: LABEL="nixos" UUID="5f4ad025-bfab-4aed-a933-6638348059e5" UUID_SUB="4734d820-7b8a-4b7f-853a-026021c1d204" BLOCK_SIZE="4096" TYPE="btrfs" PARTLABEL="data" PARTUUID="9ea025df-cdb7-48fd-b5d4-37cd5d8588eb"
``` ```
8. **Copy your NixOS configuration to the server** 8. **Copy your NixOS configuration to the server**
@@ -388,11 +389,11 @@ After successful migration and 24-48 hours of stable operation:
Pre-migration: Pre-migration:
- [x] nvme0n1p5 removal from media pool complete - [x] nvme0n1p5 removal from media pool complete
- [ ] Recent backup verified (< 24 hours) - [x] Recent backup verified (< 24 hours)
- [ ] Maintenance window scheduled - [x] Maintenance window scheduled
- [ ] NixOS ISO downloaded - [x] NixOS ISO downloaded
- [ ] Bootable USB created - [x] Bootable USB created
- [ ] NixOS config builds successfully - [x] NixOS config builds successfully
During migration: During migration:
- [ ] ZFS pools exported - [ ] ZFS pools exported

View File

@@ -18,12 +18,29 @@
# File systems - these will need to be updated after installation # File systems - these will need to be updated after installation
# The nvme0n1p5 partition will be formatted as btrfs for NixOS root # The nvme0n1p5 partition will be formatted as btrfs for NixOS root
fileSystems."/" = { fileSystems."/" = {
# Update this device path after installation device = "/dev/disk/by-uuid/5f4ad025-bfab-4aed-a933-6638348059e5";
device = "/dev/disk/by-uuid/CHANGE-THIS-TO-YOUR-UUID";
fsType = "btrfs"; fsType = "btrfs";
options = [ "subvol=@" "compress=zstd" "noatime" ]; options = [ "subvol=@" "compress=zstd" "noatime" ];
}; };
fileSystems."/home" = {
device = "/dev/disk/by-uuid/5f4ad025-bfab-4aed-a933-6638348059e5";
fsType = "btrfs";
options = [ "subvol=@home" "compress=zstd" "noatime" ];
};
fileSystems."/nix" = {
device = "/dev/disk/by-uuid/5f4ad025-bfab-4aed-a933-6638348059e5";
fsType = "btrfs";
options = [ "subvol=@nix" "compress=zstd" "noatime" ];
};
fileSystems."/var/log" = {
device = "/dev/disk/by-uuid/5f4ad025-bfab-4aed-a933-6638348059e5";
fsType = "btrfs";
options = [ "subvol=@log" "compress=zstd" "noatime" ];
};
fileSystems."/boot" = { fileSystems."/boot" = {
# This should match your current EFI partition # This should match your current EFI partition
device = "/dev/disk/by-uuid/F5C6-D570"; device = "/dev/disk/by-uuid/F5C6-D570";
@@ -35,10 +52,8 @@
# The pools should be imported automatically via boot.zfs.extraPools # The pools should be imported automatically via boot.zfs.extraPools
# /media and /swarmvols will be mounted by ZFS # /media and /swarmvols will be mounted by ZFS
# Swap - using ZFS zvol # No swap needed - 23GB RAM is sufficient for this NFS/ZFS server
swapDevices = [ swapDevices = [ ];
{ device = "/dev/zvol/media/swap"; }
];
# CPU microcode # CPU microcode
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;

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 = "64eba96c0a9b663ef3a206c8f07b71ab34f46df4";
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

@@ -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'"