157 Commits

Author SHA1 Message Date
35475da5b8 nix-darwin: add claude-code and codex via dedicated flakes
Add flake inputs for codex-cli-nix and claude-code-nix with cachix
caching for pre-built binaries, matching the NixOS setup.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 14:27:52 -08:00
6d283347ee Add Waybar disk list via HM 2026-02-04 12:35:23 -08:00
0d47dba590 chore: bump org-agenda-api input 2026-02-04 12:34:36 -08:00
657a80ac52 waybar: enlarge bar and tighten spacing 2026-02-04 12:33:56 -08:00
b1284f787d rofi-pass: include x11 + wayland deps 2026-02-04 12:15:10 -08:00
de64062078 Enable UWSM for Hyprland and tie Waybar to session 2026-02-04 12:13:15 -08:00
b1c1cf9ddc Add Hyprland workspace swap command 2026-02-04 12:02:00 -08:00
304376397b waybar: use workspace taskbar icons 2026-02-04 11:47:28 -08:00
68f9809798 hypr: fix volume scratchpad matching 2026-02-04 09:24:49 -08:00
71b38811dd Add codex_tmux 2026-02-04 02:49:16 -08:00
3ff056e6d9 codex: allow apps 2026-02-04 02:49:03 -08:00
98c85c5727 Enable frame-mode under Hyprland 2026-02-04 02:48:55 -08:00
3a405c0520 hyprland: restore mod+backslash workspace toggle 2026-02-04 02:47:12 -08:00
65a329258e Add agentic config files 2026-02-04 02:15:59 -08:00
46f16c406c Improve Hyprland scratchpads 2026-02-04 01:41:00 -08:00
b78c7b7f2c Revert "[Emacs] claude-code-ide"
This reverts commit 6dc320ff1c.
2026-02-04 01:31:31 -08:00
9f554b3976 emacs: tangle org-config outputs before load 2026-02-04 01:31:04 -08:00
239013386f Switch back to workspaces 2026-02-04 01:15:49 -08:00
1e3321c2b0 tmux: Remove tmux auto naming 2026-02-04 00:46:02 -08:00
f1142f58a8 tmux: remove prompt from codex session shortcut 2026-02-04 00:36:58 -08:00
2a24fde229 nixos: add ghostty to desktop packages 2026-02-04 00:28:44 -08:00
7f61090a82 tmux: add Codex session shortcut 2026-02-04 00:28:40 -08:00
56c9ddf508 Load org-config preface on direct load 2026-02-04 00:25:49 -08:00
5c3c55c582 waybar: switch to wlr taskbar 2026-02-04 00:18:53 -08:00
b234cbec56 hyprland: configure hyprexpo overview 2026-02-04 00:18:45 -08:00
e3ad0d857e Add shared agent instructions and tmux titling hook 2026-02-04 00:17:56 -08:00
2f2bb59693 org: tangle org-config during export 2026-02-04 00:13:04 -08:00
9b42d002cf docs: drop old githook export notes 2026-02-04 00:12:36 -08:00
9187b7381a docs: remove unused packages from README 2026-02-04 00:11:20 -08:00
0c47603d8d emacs: bind vertico TAB to embark 2026-02-03 23:33:30 -08:00
0aa3dc14f3 rofi: adjust colorful style font 2026-02-03 23:33:26 -08:00
c25da8d505 terminal: switch back to alacritty 2026-02-03 23:33:18 -08:00
389f746a94 hypr: switch to hyprexpo and stabilize waybar 2026-02-03 23:32:47 -08:00
ae5036721a ui: tweak alacritty and rofi sizing 2026-02-03 22:03:37 -08:00
d3259bbb26 hypr: tweak scaling, fullscreen, and scratchpads 2026-02-03 22:03:02 -08:00
d87da32dee terminal: switch to ghostty 2026-02-03 22:01:59 -08:00
b2ff5f1ae5 hypr: add hyprspace overview and waybar config 2026-02-03 22:01:14 -08:00
478ceed777 Ignore generated fontconfig defaults 2026-02-03 20:52:32 -08:00
31b7174624 emacs: ignore elpaca directory 2026-02-03 20:40:28 -08:00
ab8cf11b80 nixpkgs: use emacs30-pgtk 2026-02-03 20:37:05 -08:00
b3b405ec7e keyd: align hyper chord with hyprland 2026-02-03 20:36:58 -08:00
0e16fbaeb0 audio: support Hyprland in toggle_mute_current_window 2026-02-03 20:33:46 -08:00
af9c3299cb hyprland: restore config and drop hyprexpo 2026-02-03 20:33:30 -08:00
b1f578b248 hyprland: drop hyprexpo and update bindings 2026-02-03 20:31:57 -08:00
ebfbca4827 nixos: remove forEachUser helper 2026-02-03 20:30:39 -08:00
8620cc6287 Fix rofi DPI auto-detect 2026-02-03 20:16:02 -08:00
c75d1e59e0 hyprland: update config and workspace script 2026-02-03 20:15:54 -08:00
781c3b8297 picom: use my-picom branch with spring physics and animation fixes
- Point to my-picom branch (clean merge of spring-physics + animation-fixes PRs)
- Includes: spring physics curve, adaptive settling threshold, position detection fix
- Add suppressions to geometry animation to prevent opacity changes from
  interrupting position/scale animations

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 17:20:25 -08:00
5d44ec0aaa Bump org-agenda-api to de1c60b
Includes:
- Mova bump to e9cfb65
- org-window-habit fix for logbook parser reading next entry's LOGBOOK
- fetchYarnDeps hash update for new mova

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 14:37:25 -08:00
f52635d139 taffybar: update submodule to latest
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 20:01:07 -08:00
2bcfa3df1a picom: use spring physics for open/close animations
- Scale: spring with bounce (clamping=false) for a "pop" effect
- Opacity: spring with clamping=true to prevent going above 1 or below 0
- Close uses clamping=true on scale to avoid bounce when closing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 13:21:24 -08:00
dd3931249f picom: slow down spring animations and add debug logging
Spring parameters changed from (250, 20, 1) to (150, 18, 1.5):
- Reduced stiffness: 250 -> 150 (slower oscillation)
- Slightly reduced dampening: 20 -> 18
- Increased mass: 1 -> 1.5 (more "weight", slower motion)

Also added --log-level=debug --log-file to picom service for
monitoring animation triggers.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 13:18:46 -08:00
daf2911540 picom: add scale animation for size changes in geometry trigger
When both size AND position change (common in tiling WMs), picom's
win_position_changed() returns false. Only size_changed is true.
This means the geometry trigger fires but only scale-x/y change,
not offset-x/y.

Added scale-x and scale-y with spring physics to the geometry
animation so windows animate properly when resized.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 13:10:33 -08:00
8bce7b05c6 taffybar: remove crypto price widgets
Remove ICP, BTC, and ETH crypto price widgets and related CMC API key setup.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 12:51:28 -08:00
3e8ff68f15 picom: completely replace home-manager's picom with custom service
Home-manager was concatenating its generated settings with our custom
config. Disable home-manager's picom entirely and create our own
systemd service that uses only our config file.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 12:42:42 -08:00
f22a96e37b picom: disable home-manager settings generation entirely
Set settings = {} to prevent home-manager from generating any picom
config settings that would be appended to our custom config file.
This was causing duplicate/conflicting settings.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 12:39:40 -08:00
8045c4cc9d chore: update org-agenda-api to v4.4.0 (overdue_behavior feature)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 12:37:45 -08:00
ff90c0ab3f picom: update hash for settling threshold fix
Increases settling threshold to 1.0 pixel to more aggressively stop
the spring animation when visually settled, preventing sub-pixel
jitter at the tail end.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 12:32:34 -08:00
baf8b17098 Remove codex PR patch (merged upstream)
PR 483705 has been merged into nixpkgs-unstable.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 10:52:53 -08:00
cd51704a0c Fix appearance setup: enable font and add nerd-icons
- Remove :tangle no from font setting so JetBrainsMono gets applied
- Add nerd-icons package (required by doom-modeline v4+)
- Add :after nerd-icons to doom-modeline for proper load order

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 22:31:48 -08:00
03c8fd52a3 picom: write complete config directly to fix animations syntax
Give up on @include workarounds - libconfig doesn't support ~.
Write the complete picom config directly with correct () list syntax
for animations, using xdg.configFile with force=true to override
home-manager's generated config.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 13:44:15 -08:00
11cbe51ab8 picom: use absolute paths in @include directives
The config files are symlinks to nix store, so relative paths don't
resolve correctly. Try using ~/.config/picom paths.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 13:41:24 -08:00
aacb4e5e99 picom: use @include directive for config composition
picom doesn't support multiple --config flags. Use a wrapper config
with libconfig @include directive to merge the base config and
animations config.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 13:38:47 -08:00
dd3c638461 picom: use %h systemd specifier for home directory
XDG_CONFIG_HOME is not set in the systemd environment, causing the
animations config path to resolve incorrectly.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 13:35:29 -08:00
ba91ff5b82 picom: fix animations config syntax for libconfig
Home-manager generates [] (arrays) but picom needs () (lists) for
the animations setting. Move animations to a separate config file
with correct syntax and override the picom service to load both.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 13:32:50 -08:00
0493a60f95 picom: fix version to match mainline v13
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 13:10:21 -08:00
68d554d2b2 picom: switch to mainline with spring physics animations
Update picom from dccsillag fork to colonelpanic8/picom spring-physics
branch, which adds spring physics animation support to mainline picom.

Spring curve syntax: spring(stiffness, dampening, mass, clamping)
- stiffness: spring constant (higher = faster)
- dampening: resistance (higher = less oscillation)
- mass: inertia (higher = slower)
- clamping: prevent overshoot (false for bounce effects)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 13:07:30 -08:00
5b92b7ee01 Update elpaca migration for current master
- Convert remaining :straight to :ensure (claude-code-ide)
- Update elpaca-installer.el from v0.7 to v0.11
2026-02-01 00:54:25 -08:00
Nicholas Vollmer
0d21252693 fixup use Elpaca commit
ensure vertico-directory :after vertico.
load org config using expand-file-name instead of load-file-name.
Add :ensure nil to subsequent Org use-package declarations.
2026-02-01 00:54:25 -08:00
Nicholas Vollmer
8794829f81 use Elpaca for package management 2026-02-01 00:54:25 -08:00
e12f65de10 Elpaca migration wip 2026-02-01 00:54:25 -08:00
06dde4652d Add extraDomains support and register rbsf.railbird.ai
- org-agenda-api-host now supports extraDomains option for additional
  domain names, each with its own ACME certificate
- Add org-agenda-api.rbsf.railbird.ai as extra domain on railbird-sf

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 22:43:12 -08:00
91db521dfd Update org-api-passwords 2026-01-31 22:30:26 -08:00
9c51555847 nixos: Use codex-cli-nix and claude-code-nix flakes with cachix
Switch from manual version overrides to dedicated flakes:
- github:sadjow/codex-cli-nix for codex
- github:sadjow/claude-code-nix for claude-code

Added cachix substituters and keys for pre-built binaries.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 21:45:25 -08:00
89ce2116cf Update org-agenda-api input to include modular org-window-habit
- org-window-habit refactored from single file to modular structure
- org-agenda-api test linting fixes

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 21:10:29 -08:00
3b7c053575 chore: update org-agenda-api with modular org-window-habit
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 20:35:11 -08:00
865957d9ac Fix org-api-ssh-key secret (was empty) 2026-01-31 20:18:54 -08:00
22360ddeea Add split org-api secrets for auth password and SSH key
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 20:15:48 -08:00
301e2a1479 Split org-api secrets into auth password and SSH key
- Auth password uses env file format for systemd EnvironmentFile
- SSH key is mounted as a file at /secrets/ssh_key in container
- Fixes multi-line SSH key parsing issue in environment files
- Update codex PR patch hash

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 20:14:48 -08:00
34cacdc40d Update org-api-passwords.age with proper env file format
Include AUTH_PASSWORD and GIT_SSH_PRIVATE_KEY for container deployment.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 19:52:02 -08:00
7a1a612397 Use home-manager.sharedModules for shared user config
Replace manual forEachUser pattern with built-in sharedModules for
applying config to all home-manager users. Add automatic garbage
collection of old generations (weekly, older than 7 days) and remove
the now-unnecessary expire-home-manager-generations justfile recipe.

Also update codex PR patch hash (upstream patch was modified).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 19:48:50 -08:00
317019d5bc Keep imalison: prefix for reschedule-past-to-today
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 18:49:52 -08:00
ad5c3fc8ed Re-encrypt org-api-passwords.age with railbird-sf key
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 14:00:31 -08:00
6b1e5a1aec Update org-agenda-api for exposed functions feature 2026-01-31 14:00:03 -08:00
f28a78b053 Add org-reschedule-past-to-today as exposed function
- Rename imalison:reschedule-past-to-today to org-reschedule-past-to-today
- Keep old name as alias for backwards compatibility
- Register function in org-agenda-api-exposed-functions for API access

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 13:59:28 -08:00
c4867e7845 Re-encrypt org-api-passwords.age with railbird-sf key
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 13:56:35 -08:00
c36ae5f4a8 Re-encrypt age secrets with updated keys
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 12:08:15 -08:00
4d8447ccb2 Increase gitea-runner container shared memory to 2GB
The default 64MB shm-size is too small for Metro/Gradle builds.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 11:41:45 -08:00
f241d76734 Fix xmonad greenclip binding and flake submodule issues
- Inline rofi greenclip command in xmonad.hs instead of calling script
- Update xmonad flake.nix to use github sources instead of path:
  (path: inputs don't work with git submodules in nix flakes)
- Update flake.lock with new inputs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 11:41:09 -08:00
bf02a7ee4c Add codex 0.92.0 PR patch and fix deprecation warnings
- Add nixpkgs PR 483705 to bump codex from 0.89.0 to 0.92.0
- Disable overlay version overrides in favor of PR patches
- Replace deprecated pkgs.system with pkgs.stdenv.hostPlatform.system
- Replace deprecated xfce.thunar with thunar

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 00:15:33 -08:00
a716ec1694 Update org-agenda-api to 9f5b9d4 (org-window-habit bump)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 17:59:10 -08:00
e7a455ced9 feat(nixos): add org-agenda-api hosting with nginx + Let's Encrypt
Add NixOS module to host org-agenda-api container on railbird-sf:
- org-agenda-api-host.nix: New module with nginx reverse proxy and ACME
- nginx configured for rbsf.tplinkdns.com with automatic TLS
- Container runs on port 51847 (random high port)
- Supports nix-built container images via imageFile option

Configure railbird-sf to use the new module:
- Build org-agenda-api container from flake
- Pass container to machine config via specialArgs
- Set up agenix secret for container environment

Note: Requires creating secrets file with AUTH_PASSWORD and
GIT_SSH_PRIVATE_KEY environment variables.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 09:40:19 -08:00
53afba8b40 Add org-agenda-api cachix to deploy script
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 08:09:19 -08:00
4d7350b3fe Update org-agenda-api to 9bc594c (mova/org-window-habit bump)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 02:39:51 -08:00
df2c033d0f Switch from clipit/gpaste to greenclip for clipboard management
- Remove clipit config and helper scripts
- Add greenclip service and rofi integration
- Update xmonad keybinding to use rofi_clipboard.sh

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 00:09:48 -08:00
9cdd201c41 Update org-agenda-api to b8c66d0 (mova bump)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 23:47:36 -08:00
50fc48ec36 [NixOS] Add bump-overlay-versions skill to repo
Move skill from global ~/.claude/skills to project-local .claude/skills
so it's version controlled with the dotfiles.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 11:57:11 -08:00
595dc39945 [NixOS] Enable codex override 2026-01-29 11:33:21 -08:00
e1a5d2af5d Update org-agenda-api to 9e85a39 (git identity fix)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 11:32:51 -08:00
fc481ababa Update colonelpanic git user identity
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 11:29:45 -08:00
4c6ff0bd10 Fix tzupdate service failing at boot
The service was failing because network-online.target is reached before
network is actually online (NetworkManager-wait-online is disabled to
avoid boot hangs). Remove the service from multi-user.target.wants and
let only the timer trigger it, which already has a 30s startup delay.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 19:44:25 -08:00
0d13dd022a Update org-agenda-api to aeb59ee (SSH fix)
Includes fix for SSH setup in container startup script.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 14:45:49 -08:00
43e118b3e3 Rename container outputs to {instance}-org-agenda-api
More descriptive naming convention:
- colonelpanic-org-agenda-api
- kat-org-agenda-api

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 14:27:58 -08:00
504ec1a105 Add org-agenda-api container builds and fly.io deployment
Consolidates container builds from colonelpanic-org-agenda-api repo:
- Add org-agenda-api input to nixos flake
- Add container-colonelpanic and container-kat package outputs
- Add org-agenda-api cachix as substituter
- Add org-agenda-api devShell for deployment work

New org-agenda-api directory contains:
- container.nix: Container build logic using mkContainer
- configs/: Instance configs (custom-config.el, fly.toml, secrets)
- deploy.sh: Fly.io deployment script
- secrets.nix: agenix secret declarations

Build with: nix build .#container-colonelpanic
Deploy with: cd org-agenda-api && ./deploy.sh colonelpanic

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 14:24:41 -08:00
ccd63ba066 Add org-agenda-api consolidation design plan
Documents the plan to:
- Move container builds from colonelpanic-org-agenda-api to dotfiles
- Consolidate fly.io deployment into dotfiles/org-agenda-api/
- Add cachix substituter for faster builds
- Keep custom-config.el for container-specific glue only

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 14:17:13 -08:00
96e019310b [NixOS] Add opencode 2026-01-28 11:28:56 -08:00
fc2903eb5d [tmux] Remove session changed hook 2026-01-28 11:28:47 -08:00
71580f3a84 [NixOS] Fix stale hashes and remove claude-code override 2026-01-26 00:51:48 -08:00
f280b91595 feat: add high priority unscheduled agenda view
Adds a new custom agenda view (key "u") that shows high priority (A/B)
items that don't have a scheduled date or deadline. Useful for finding
important tasks that might be falling through the cracks.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 17:54:01 -08:00
d64a97e2c1 [Emacs] Include repeating in agenda again 2026-01-25 12:06:59 -08:00
f692c9f6c4 feat: add standalone agenda views for inbox, next, and wait states
Adds three new org-agenda-custom-commands:
- "i" for Inbox tasks (INBOX state)
- "n" for Next tasks (NEXT state)
- "w" for Waiting tasks (WAIT state)

These were previously only available as part of the composite "M" view.
Now they're exposed as standalone views for the org-agenda-api.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 13:33:45 -08:00
1876c22b46 feat: add inbox capture template
Add a new capture template (key "i") that captures to INBOX state
instead of TODO. This template appears first in the capture list.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 01:12:56 -08:00
aecc7afb4c [NixOS] Add passgen 2026-01-22 01:10:15 -08:00
b9f4a8731e Remove some stuff from biskcomp 2026-01-22 01:01:23 -08:00
180d9e7c50 [NixOS] Add gimp and inskape 2026-01-22 01:01:05 -08:00
b383cd0cd2 [NixOS] Remove railbird and interview 2026-01-22 01:00:50 -08:00
28ead6994d Fix tmux auto-naming for duplicate directory basenames
- Handle duplicate session names by appending -2, -3, etc.
- Add tn function to manually rename current session to cwd basename

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 00:57:59 -08:00
205d9528b3 [Emacs] Make hydra-yank work with non-file buffers
Add imalison:buffer-file-name-or-directory helper that falls back to
default-directory when buffer-file-name is nil. This allows the yank
hydra to work with magit buffers and other buffers associated with a
directory but not visiting a file.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 00:45:30 -08:00
91e36cd0ba [NixOS] Claude code to 2.1.4 2026-01-21 19:36:03 -08:00
f3871b233a Revert "fix: enable org-window-habit in tangled config"
This reverts commit 674b6ca7cb.
2026-01-21 10:14:58 -08:00
674b6ca7cb fix: enable org-window-habit in tangled config
Add :tangle directive to org-window-habit source block so it gets
included in org-config-config.el for the container deployment.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 10:03:28 -08:00
08cf4ae492 Add autorandr profiles for strixi-minaj with BC Alienware monitors
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 13:35:40 -05:00
986966bbc1 Refactor emacs README to use noweb for shared code blocks
Use noweb syntax to share imalison:join-paths and imalison:projects-directory
definitions between the main config and org-config-bootstrap.el.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 13:35:15 -05:00
b3b425833b Add poetry fix and comment out codex override
- Fix poetry pbs-installer version constraint issue with dontCheckRuntimeDeps
- Comment out codex override (using nixpkgs version)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 13:35:03 -05:00
658f424cf8 Enable Nvidia sync mode on strixi-minaj
Switch from offload mode to sync mode for better performance
with external displays.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 13:34:56 -05:00
cc05a1d790 Add Hyprland with hy3 plugin for XMonad-like tiling
Configure Hyprland to use the hy3 plugin for dynamic tiling similar to
XMonad. Uses official Hyprland and hy3 flakes pinned to v0.53.0 for
proper plugin compatibility (nixpkgs packaging had header issues).

Key changes:
- Add hyprland and hy3 flake inputs with version pinning
- Rewrite hyprland.conf with hy3 layout and XMonad-like keybindings
- Add helper scripts for window management (bring, replace, gather, etc.)
- WASD directional navigation using hy3:movefocus/movewindow
- Tab groups, horizontal/vertical splits via hy3:makegroup
- Scratchpads via Hyprland special workspaces

Also removes org-agenda-api flake integration (moved elsewhere).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 13:34:45 -05:00
68b3e5d83c feat: add Next (Scheduled Today) capture template
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 13:21:00 -05:00
c70d6a9e99 Add automatic ID property generation to org capture templates
Use org-id-new to generate UUIDs for new entries, matching the format
used by org-roam. Updates imalison:created-property-string, both
template helper functions, and the habit capture template.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 07:22:27 -05:00
3e805b172e Simplify org-agenda-api.nix to only produce tangled elisp files
Container construction moved to colonelpanic-org-agenda-api repo.
This flake now only exports org-agenda-custom-config (tangled files).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 12:11:59 -05:00
b27ff12180 Update org-agenda-api for LOGBOOK fix
Fixes state change logging (LOGBOOK entries) not being created in
non-interactive contexts.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 02:01:54 -08:00
fb2cc5672c Update org-agenda-api with debug-config endpoint 2026-01-16 01:52:18 -08:00
2291a14e84 [NixOS] Bump cc version 2026-01-16 04:15:41 -05:00
e7ee6c7d3d [NixOS] Add a codex overlay 2026-01-16 04:15:41 -05:00
74d95edcae Update org-agenda-api with agenda date override fix
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 01:07:31 -08:00
4954c40f85 Update org-agenda-api to fix off-by-one date error
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 00:39:22 -08:00
d0c92889ee Update org-agenda-api with field validation 2026-01-15 13:59:23 -08:00
ff3bb1e492 Update org-agenda-api with request logging 2026-01-15 13:37:41 -08:00
94216a3ec0 Update org-agenda-api with title-based fallback matching
Fixes position drift issue where cached positions become stale
after todo updates. API now falls back to title matching.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 13:25:38 -08:00
a848468d09 Fix shared-org-file-p to handle nil shared-org-dir in container
The org-schedule advice calls imalison:shared-org-file-p which uses
file-truename on imalison:shared-org-dir. When this var is nil (as in
the container), it causes 'Wrong type argument: arrayp, nil' error.

Override the function after loading tangled config to check for nil first.
2026-01-15 12:52:49 -08:00
5d73857125 Update org-agenda-api flake input 2026-01-15 12:31:23 -08:00
3f88a30149 Update flake.lock and fix synergy build with GCC 15
- Update flake inputs (home-manager, nix, nixos-wsl, nixpkgs, org-agenda-api)
- Add overlay to fix synergy missing #include <cstdint>

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 08:34:22 -08:00
b81e2699d6 Strip :straight keywords from tangled config for container
straight.el is not available in the minimal container Emacs,
so we need to remove :straight nil and :straight t from
use-package declarations in the tangled config files.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 21:24:08 -08:00
323ffb935e Update org-agenda-api input
Updated to include logging to stderr and debug-on-error for better container debugging.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 15:02:52 -08:00
ec5411df87 Add org-config-bootstrap.el tangle target for container builds
Adds :tangle org-config-bootstrap.el to blocks defining minimal
utilities needed by org-config.el for use in org-agenda-api containers.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 12:42:32 -08:00
6b54747f9a Add missing helper functions for custom agenda views
The org-agenda-custom-commands reference get-date-created-from-agenda-entry
and imalison:compare-int-list, but these were only defined in README.org
(main emacs config), not tangled into org-config.org.

This caused /custom-view?key=r (Recently created) to fail with
"void-function get-date-created-from-agenda-entry".

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 12:32:34 -08:00
76755b24e1 Use org-agenda-api from GitHub instead of local path
- Change org-agenda-api input from path:../dotfiles/emacs.d/straight/repos/org-agenda-api to github:colonelpanic8/org-agenda-api
- Refactor org-agenda package building to separate org-agenda-api.nix file
- Update flake.lock with new input and fix hercules-ci-effects metadata mismatch

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 11:58:32 -08:00
231f84364c Fix org-config-custom.el loading: convert customize format to setq
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 10:05:14 -08:00
535a6c2521 Set imalison:shared-org-dir to nil in container
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 09:58:20 -08:00
7a471048dc Load full tangled org-config for container
- Set imalison:org-dir and imalison:shared-org-dir for container paths
- Load org-config-preface.el, org-config-custom.el, org-config-config.el
- This properly sets org-agenda-files and org-agenda-custom-commands
- Add capture templates for API

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 09:57:17 -08:00
ccc49ce341 Add custom agenda commands and capture templates for org-agenda-api container
- Add simplified org-agenda-custom-commands for API (n, s, i, w, h, M)
- Add org-agenda-api-capture-templates (gtd-todo, scheduled-todo, deadline-todo)
- Templates use INBOX state and include CREATED property

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 09:49:12 -08:00
5304640c79 Update org-api.el to use org-agenda-api package
- Replace custom endpoint code with org-agenda-api require
- Add gtd-todo, scheduled-todo, and tagged-todo capture templates
- Custom commands from init.el will be available via /custom-views

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 09:45:24 -08:00
3e9f67c432 Update org-agenda-api flake input
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 06:57:22 -08:00
3e121b2944 [NixOS] Update flake.lock 2026-01-14 02:02:13 -08:00
7627ae7361 [NixOS] Update how android tools are managed 2026-01-14 02:00:25 -08:00
58f727b65d [Emacs] Log items inthe closed state 2026-01-14 02:00:02 -08:00
57fc6a4d53 Add org-agenda-api customized container package
- Export org-agenda-api-container with org settings baked in
- Tangle org-config.org and convert to setq format
- Container can be used by colonelpanic-org-agenda-api for Fly.io deployment

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 01:44:41 -08:00
444af768fc Migrate gen-gh-pages from Travis CI to GitHub Actions
- Add GitHub Actions workflow using peaceiris/actions-gh-pages
- Update README.org badge and documentation to reference GitHub Actions
- Simplify compile.sh for local use (removes Travis-specific evm setup)
- Mark deploy.sh as deprecated (workflow handles deployment now)
- Remove deploy_key.enc (no longer needed, uses GITHUB_TOKEN)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 23:53:44 -08:00
124 changed files with 5649 additions and 1631 deletions

54
.github/workflows/gh-pages.yml vendored Normal file
View File

@@ -0,0 +1,54 @@
name: Deploy to GitHub Pages
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
build-and-deploy:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Emacs
uses: purcell/setup-emacs@master
with:
version: 29.1
- name: Setup Cask
uses: conao3/setup-cask@master
with:
version: snapshot
- name: Install dependencies
working-directory: gen-gh-pages
run: cask install
- name: Generate HTML
working-directory: gen-gh-pages
run: |
cask exec emacs --script generate-html.el
mv ../dotfiles/emacs.d/README.html ./index.html
- name: Deploy to GitHub Pages
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./gen-gh-pages
publish_branch: gh-pages
user_name: 'github-actions[bot]'
user_email: 'github-actions[bot]@users.noreply.github.com'
commit_message: 'Deploy to GitHub Pages: ${{ github.sha }}'
keep_files: false

1
.gitignore vendored
View File

@@ -25,3 +25,4 @@ gotools
/dotfiles/config/gtk-3.0/colors.css /dotfiles/config/gtk-3.0/colors.css
/dotfiles/emacs.d/.cache/ /dotfiles/emacs.d/.cache/
/dotfiles/config/fontconfig/conf.d/10-hm-fonts.conf /dotfiles/config/fontconfig/conf.d/10-hm-fonts.conf
/dotfiles/config/fontconfig/conf.d/52-hm-default-fonts.conf

View File

@@ -0,0 +1,152 @@
# Org-Agenda-API Consolidation Design
## Overview
Consolidate org-agenda-api container builds and fly.io deployment into the dotfiles repository. This eliminates the separate `colonelpanic-org-agenda-api` repo and provides:
- Container outputs available to NixOS machines directly
- Fly.io deployment from the same repo
- Fewer repos to maintain
- Cachix integration for faster builds
## Directory Structure
```
/home/imalison/dotfiles/
├── nixos/
│ ├── flake.nix # Main flake, adds container output
│ ├── org-agenda-api.nix # Existing tangling module (stays here)
│ └── ...
├── org-agenda-api/
│ ├── container.nix # Container build logic (mkContainer, etc.)
│ ├── configs/
│ │ ├── colonelpanic/
│ │ │ ├── custom-config.el
│ │ │ └── overrides.el (optional)
│ │ └── kat/
│ │ └── custom-config.el
│ ├── fly/
│ │ ├── fly.toml
│ │ ├── deploy.sh
│ │ └── config-{instance}.env
│ └── secrets/
│ ├── secrets.nix # agenix declarations
│ └── *.age # encrypted secrets
└── dotfiles/emacs.d/
└── org-config.org # Source of truth for org config
```
## Flake Integration
The main dotfiles flake at `/home/imalison/dotfiles/nixos/flake.nix` exposes container outputs:
```nix
outputs = inputs @ { self, nixpkgs, flake-utils, ... }:
{
nixosConfigurations = { ... }; # existing
} // flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs { inherit system; };
containerLib = import ../org-agenda-api/container.nix {
inherit pkgs system;
tangledConfig = (import ./org-agenda-api.nix {
inherit pkgs system;
inputs = inputs;
}).org-agenda-custom-config;
};
in {
packages = {
container-colonelpanic = containerLib.mkInstanceContainer "colonelpanic";
container-kat = containerLib.mkInstanceContainer "kat";
};
}
);
```
Build with: `nix build .#container-colonelpanic`
## Custom Elisp & Tangling
Single source of truth: `org-config.org` tangles to elisp files loaded by containers.
**What stays in custom-config.el (container-specific glue):**
- Path overrides (`/data/org` instead of `~/org`)
- Stubs for unavailable packages (`org-bullets-mode` no-op)
- Customize-to-setq format conversion
- Template conversion for org-agenda-api format
- Instance-specific settings
**Audit:** During implementation, verify no actual org logic is duplicated in custom-config.el.
## Cachix Integration
### Phase 1: Use upstream cache as substituter
Add to dotfiles flake's `nixConfig`:
```nix
nixConfig = {
extra-substituters = [
"https://org-agenda-api.cachix.org"
];
extra-trusted-public-keys = [
"org-agenda-api.cachix.org-1:PUBLIC_KEY_HERE"
];
};
```
Benefits:
- `container-base` (~500MB+ dependencies) fetched from cache
- Rebuilds only process the small custom config layer
### Phase 2 (future): Push custom builds
Set up GitHub Action or local push for colonelpanic-specific container builds.
## Fly.io Deployment
**What moves:**
- `fly.toml``dotfiles/org-agenda-api/fly/fly.toml`
- `deploy.sh``dotfiles/org-agenda-api/fly/deploy.sh`
- `configs/*/config.env``dotfiles/org-agenda-api/fly/config-{instance}.env`
- Agenix secrets → `dotfiles/org-agenda-api/secrets/`
**Deploy script changes:**
- Build path: `nix build "../nixos#container-${INSTANCE}"`
- Secrets path adjusts to new location
- Otherwise same logic
## Implementation Phases
### Phase 1: Pull latest & verify current state
- Pull latest changes in org-agenda-api and colonelpanic-org-agenda-api
- Build container, verify it works
- Fix any issues before restructuring
### Phase 2: Create dotfiles structure
- Create `/home/imalison/dotfiles/org-agenda-api/` directory
- Move container.nix logic (adapted from current colonelpanic-org-agenda-api flake)
- Move instance configs (colonelpanic/, kat/)
- Move fly.io deployment files
- Move agenix secrets
### Phase 3: Integrate with dotfiles flake
- Update `/home/imalison/dotfiles/nixos/flake.nix` to expose container outputs
- Add cachix substituter configuration
- Test build from dotfiles: `nix build .#container-colonelpanic`
### Phase 4: Verify deployment
- Test deploy.sh from new location
- Verify fly.io deployment works
- Run the container locally on a NixOS machine
### Phase 5: Audit & cleanup
- Review custom-config.el for any duplicated org logic
- Archive colonelpanic-org-agenda-api repo
- Update any references/documentation
## Repos Affected
- **dotfiles** - Receives container build + fly.io deployment
- **colonelpanic-org-agenda-api** - Becomes obsolete after migration
- **org-agenda-api** (upstream) - No changes, used as flake input

21
dotfiles/agents/AGENTS.md Normal file
View File

@@ -0,0 +1,21 @@
# Agentic Session Preferences
## Tmux session titling
- If the TMUX environment variable is set, treat this chat as the controller for the current tmux session.
- Maintain a session/window/pane title that updates when the task focus changes substantially.
- Prefer automatic titling: infer a concise <task> from the current user request and context without asking.
- Title format: "<project> - <task>".
- <project> is the basename of the current project directory.
- Prefer git repo root basename if available; otherwise use basename of the current working directory.
- <task> is a short, user-friendly description of what we are doing.
- Ask for a short descriptive <task> only when the task is ambiguous or you are not confident in an inferred title.
- When the task changes substantially, update the <task> automatically if clear; otherwise ask for an updated <task>.
- When a title is provided or updated, immediately run this one-liner:
tmux rename-session '<project> - <task>' \; rename-window '<project> - <task>' \; select-pane -T '<project> - <task>'
- Assume you are inside tmux, so do not use -t unless the user asks to target a specific session.
- For Claude Code sessions, a UserPromptSubmit hook will also update titles automatically based on the latest prompt.
## Pane usage
- Do not create extra panes or windows unless the user asks.

View File

@@ -0,0 +1,70 @@
#!/usr/bin/env bash
set -euo pipefail
if [[ -z "${TMUX:-}" ]]; then
exit 0
fi
input=$(cat)
read -r cwd prompt <<'PY' < <(python3 - <<'PY'
import json, os, sys
try:
data = json.load(sys.stdin)
except Exception:
data = {}
cwd = data.get("cwd") or os.getcwd()
prompt = (data.get("prompt") or "").strip()
print(cwd)
print(prompt)
PY
)
if [[ -z "${cwd}" ]]; then
cwd="$PWD"
fi
project_root=$(git -C "$cwd" rev-parse --show-toplevel 2>/dev/null || true)
if [[ -n "$project_root" ]]; then
project=$(basename "$project_root")
else
project=$(basename "$cwd")
fi
prompt_first_line=$(printf '%s' "$prompt" | head -n 1 | tr '\n' ' ' | sed -e 's/[[:space:]]\+/ /g' -e 's/^ *//; s/ *$//')
lower=$(printf '%s' "$prompt_first_line" | tr '[:upper:]' '[:lower:]')
case "$lower" in
""|"ok"|"okay"|"thanks"|"thx"|"cool"|"yep"|"yes"|"no"|"sure"|"done"|"k")
exit 0
;;
esac
task="$prompt_first_line"
if [[ -z "$task" ]]; then
task="work"
fi
# Trim to a reasonable length for tmux status bars.
if [[ ${#task} -gt 60 ]]; then
task="${task:0:57}..."
fi
title="$project - $task"
state_dir="${HOME}/.agents/state"
state_file="$state_dir/tmux-title"
mkdir -p "$state_dir"
if [[ -f "$state_file" ]]; then
last_title=$(cat "$state_file" 2>/dev/null || true)
if [[ "$last_title" == "$title" ]]; then
exit 0
fi
fi
printf '%s' "$title" > "$state_file"
# Update session, window, and pane titles.
tmux rename-session "$title" \; rename-window "$title" \; select-pane -T "$title"

1
dotfiles/claude/CLAUDE.md Symbolic link
View File

@@ -0,0 +1 @@
../agents/AGENTS.md

View File

@@ -0,0 +1,18 @@
{
"enabledPlugins": {
"superpowers@superpowers-marketplace": true,
"agent-browser@agent-browser": true
},
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "~/.agents/hooks/tmux-title.sh"
}
]
}
]
}
}

View File

@@ -0,0 +1,51 @@
{
"permissions": {
"allow": [
"Bash(find:*)",
"Bash(cat:*)"
],
"deny": []
},
"mcp": {
"servers": {
"gitea-mcp": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"GITEA_ACCESS_TOKEN=ad1e513137d5a15b638f7b4b5f65e1bda1c70cd7",
"-e",
"GITEA_BASE_URL=https://dev.railbird.ai",
"docker.gitea.com/gitea-mcp-server"
],
"env": {
"GITEA_ACCESS_TOKEN": "ad1e513137d5a15b638f7b4b5f65e1bda1c70cd7",
"GITEA_BASE_URL": "https://dev.railbird.ai"
}
},
"chrome-devtools": {
"command": "npx",
"args": [
"chrome-devtools-mcp@latest",
"--auto-connect"
]
},
"imap-email": {
"command": "npx",
"args": ["-y", "imap-email-mcp"],
"env": {
"IMAP_USER": "IvanMalison@gmail.com",
"IMAP_PASSWORD": "iiobqyuuczibsnmi",
"IMAP_HOST": "imap.gmail.com"
}
}
}
},
"enabledMcpjsonServers": [
"chrome-devtools",
"imap-email"
],
"enableAllProjectMcpServers": true
}

1
dotfiles/codex/AGENTS.md Symbolic link
View File

@@ -0,0 +1 @@
../agents/AGENTS.md

View File

@@ -0,0 +1,56 @@
model = "gpt-5.2-codex"
model_reasoning_effort = "high"
personality = "pragmatic"
[projects."/home/imalison/Projects/nixpkgs"]
trust_level = "trusted"
[projects."/home/imalison/dotfiles"]
trust_level = "trusted"
[projects."/home/imalison/Projects/railbird"]
trust_level = "trusted"
[projects."/home/imalison/Projects/subtr-actor"]
trust_level = "trusted"
[projects."/home/imalison/Projects/google-messages-api"]
trust_level = "trusted"
[projects."/home/imalison"]
trust_level = "trusted"
[projects."/home/imalison/Projects/scrobble-scrubber"]
trust_level = "trusted"
[projects."/home/imalison/temp"]
trust_level = "trusted"
[projects."/home/imalison/Projects/org-agenda-api"]
trust_level = "untrusted"
[projects."/home/imalison/org"]
trust_level = "trusted"
[notice]
hide_gpt5_1_migration_prompt = true
"hide_gpt-5.1-codex-max_migration_prompt" = true
[notice.model_migrations]
"gpt-5.2" = "gpt-5.2-codex"
[mcp_servers.chrome-devtools]
command = "npx"
args = ["-y", "chrome-devtools-mcp@latest", "--auto-connect"]
[mcp_servers.observability]
command = "npx"
args = ["-y", "@google-cloud/observability-mcp"]
[mcp_servers.gmail]
command = "nix"
args = ["run", "/home/imalison/Projects/gmail-mcp#gmail-mcp-server"]
[features]
unified_exec = true
apps = true
steer = true

View File

@@ -2,7 +2,7 @@
import = ["~/.config/alacritty/themes/themes/dracula.toml"] import = ["~/.config/alacritty/themes/themes/dracula.toml"]
[font] [font]
size = 8 size = 12
[scrolling] [scrolling]
history = 10000 history = 10000

View File

@@ -0,0 +1,39 @@
output DP-1
off
output HDMI-1
off
output DP-2
off
output HDMI-2
off
output DP-1-0
off
output DP-1-1
off
output DP-1-2
off
output DP-1-3
off
output DP-1-4
off
output DP-1-5
off
output DP-1-6
off
output eDP-1
crtc 0
mode 2560x1600
pos 0x0
primary
rate 240.00
x-prop-broadcast_rgb Automatic
x-prop-colorspace Default
x-prop-max_bpc 12
x-prop-non_desktop 0
x-prop-scaling_mode Full aspect
output HDMI-1-0
crtc 4
mode 3440x1440
pos 2560x0
rate 99.98
x-prop-non_desktop 0

View File

@@ -0,0 +1,2 @@
HDMI-1-0 00ffffffffffff0010ace3a1535a333016210103805123782a25a1b14d3db7250e505421080001010101010101010101010101010101e77c70a0d0a029503020350029623100001a000000ff00237442737a474441594542634e000000fd0018781e963c010a202020202020000000fc0044656c6c204157333432334457015f020337f148101f04130312013f230907018301000068030c002000383c006ad85dc401788000000278e305c000e2006ae60605018d4b004ed470a0d0a046503020350029623100001a9d6770a0d0a022503020350029623100001a565e00a0a0a029503020350029623100001a6fc200a0a0a055503020350029623100001a3c
eDP-1 00ffffffffffff0009e5580c0000000001210104b527187803bbc5ae503fb7250c515500000001010101010101010101010101010101c07200a0a040c8603020360084f21000001a000000fd0c30f0b1b176010a202020202020000000fe00424f452043510a202020202020000000fc004e4531383051444d2d4e4d310a029602030f00e3058080e606050195731000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fa702079020021001d280f7409000a400680dd2a511824b249120e023554b060ec64662a1378220014ffed1185ff099f002f001f003f06c700020005002b000c27003cef00002700303b0000810015741a0000030b30f0006095107310f0000000008d00000000000000000000000000000000000000000000000000000000bc90

View File

@@ -0,0 +1,39 @@
output DP-1
off
output HDMI-1
off
output DP-2
off
output HDMI-2
off
output DP-1-0
off
output DP-1-1
off
output DP-1-2
off
output DP-1-3
off
output DP-1-4
off
output DP-1-5
off
output DP-1-6
off
output eDP-1
crtc 0
mode 2560x1600
pos 0x0
primary
rate 240.00
x-prop-broadcast_rgb Automatic
x-prop-colorspace Default
x-prop-max_bpc 12
x-prop-non_desktop 0
x-prop-scaling_mode Full aspect
output HDMI-1-0
crtc 4
mode 3440x1440
pos 2560x0
rate 99.98
x-prop-non_desktop 0

View File

@@ -0,0 +1,2 @@
HDMI-1-0 00ffffffffffff0010ace3a1535a333016210103805123782a25a1b14d3db7250e505421080001010101010101010101010101010101e77c70a0d0a029503020350029623100001a000000ff00237442737a474441594542634e000000fd0018781e963c010a202020202020000000fc0044656c6c204157333432334457015f020337f148101f04130312013f230907018301000068030c003000383c006ad85dc401788000000278e305c000e2006ae60605018d4b004ed470a0d0a046503020350029623100001a9d6770a0d0a022503020350029623100001a565e00a0a0a029503020350029623100001a6fc200a0a0a055503020350029623100001a2c
eDP-1 00ffffffffffff0009e5580c0000000001210104b527187803bbc5ae503fb7250c515500000001010101010101010101010101010101c07200a0a040c8603020360084f21000001a000000fd0c30f0b1b176010a202020202020000000fe00424f452043510a202020202020000000fc004e4531383051444d2d4e4d310a029602030f00e3058080e606050195731000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fa702079020021001d280f7409000a400680dd2a511824b249120e023554b060ec64662a1378220014ffed1185ff099f002f001f003f06c700020005002b000c27003cef00002700303b0000810015741a0000030b30f0006095107310f0000000008d00000000000000000000000000000000000000000000000000000000bc90

View File

@@ -1,27 +0,0 @@
[rc]
use_copy=true
use_primary=true
synchronize=false
automatic_paste=false
show_indexes=true
save_uris=true
use_rmb_menu=false
save_history=true
history_limit=1000
history_timeout_seconds=30
history_timeout=false
items_menu=50
statics_show=true
statics_items=10
hyperlinks_only=false
confirm_clear=false
single_line=false
reverse_history=false
item_length=50
ellipsize=2
history_key=
actions_key=
menu_key=
search_key=
offline_key=
offline_mode=false

View File

@@ -1,25 +1,36 @@
# Hyprland Configuration # Hyprland Configuration
# XMonad-like dynamic tiling using hy3 plugin
# Based on XMonad configuration from xmonad.hs # Based on XMonad configuration from xmonad.hs
# See https://wiki.hyprland.org/Configuring/Monitors/ # =============================================================================
monitor=,preferred,auto,auto # PLUGINS (Hyprland pinned to 0.53.0 to match hy3)
# =============================================================================
# Load the plugin before parsing keybinds/layouts that depend on it
plugin = /run/current-system/sw/lib/libhy3.so
plugin = /run/current-system/sw/lib/libhyprexpo.so
# Source a file (multi-file configs) # =============================================================================
# source = ~/.config/hypr/myColors.conf # MONITORS
# =============================================================================
monitor=,preferred,auto,1
# Set programs that you use # =============================================================================
# PROGRAMS
# =============================================================================
$terminal = alacritty $terminal = alacritty
$fileManager = dolphin $fileManager = dolphin
$menu = rofi -show drun -show-icons $menu = rofi -show drun -show-icons
$runMenu = rofi -show run $runMenu = rofi -show run
# Environment variables # =============================================================================
# ENVIRONMENT VARIABLES
# =============================================================================
env = XCURSOR_SIZE,24 env = XCURSOR_SIZE,24
env = QT_QPA_PLATFORMTHEME,qt5ct env = QT_QPA_PLATFORMTHEME,qt5ct
env = GDK_DPI_SCALE,1.25
env = QT_FONT_DPI,120
# Input configuration # =============================================================================
# INPUT CONFIGURATION
# =============================================================================
input { input {
kb_layout = us kb_layout = us
kb_variant = kb_variant =
@@ -33,110 +44,252 @@ input {
natural_scroll = no natural_scroll = no
} }
sensitivity = 0 # -1.0 - 1.0, 0 means no modification. sensitivity = 0
} }
# General settings # Cursor warping behavior
cursor {
persistent_warps = true
}
# =============================================================================
# GENERAL SETTINGS
# =============================================================================
general { general {
gaps_in = 5 gaps_in = 5
gaps_out = 20 gaps_out = 10
border_size = 2 border_size = 2
col.active_border = rgba(edb443ee) rgba(33ccffee) 45deg col.active_border = rgba(edb443ee) rgba(33ccffee) 45deg
col.inactive_border = rgba(595959aa) col.inactive_border = rgba(595959aa)
layout = master # Use hy3 layout for XMonad-like dynamic tiling
layout = hy3
allow_tearing = false allow_tearing = false
} }
# Decoration # =============================================================================
# DECORATION
# =============================================================================
decoration { decoration {
rounding = 10 rounding = 5
blur { blur {
enabled = true enabled = true
size = 3 size = 3
passes = 1 passes = 1
} }
# Fade inactive windows (like XMonad's fadeInactive)
active_opacity = 1.0
inactive_opacity = 0.9
} }
# Animations # =============================================================================
# ANIMATIONS
# =============================================================================
animations { animations {
enabled = yes enabled = yes
bezier = myBezier, 0.05, 0.9, 0.1, 1.05 bezier = myBezier, 0.05, 0.9, 0.1, 1.05
bezier = linear, 0, 0, 1, 1
animation = windows, 1, 7, myBezier animation = windows, 1, 4, myBezier
animation = windowsOut, 1, 7, default, popin 80% animation = windowsOut, 1, 4, default, popin 80%
animation = border, 1, 10, default animation = border, 1, 10, default
animation = borderangle, 1, 8, default animation = borderangle, 1, 8, default
animation = fade, 1, 7, default animation = fade, 1, 4, default
animation = workspaces, 1, 6, default animation = workspaces, 1, 4, default
}
# Layout configuration
dwindle {
pseudotile = yes # master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
preserve_split = yes # you probably want this
} }
# =============================================================================
# MASTER LAYOUT CONFIGURATION
# =============================================================================
master { master {
mfact = 0.25 new_status = slave
mfact = 0.5
orientation = left orientation = left
} }
# Misc # Dwindle layout (alternative - binary tree like i3)
dwindle {
pseudotile = yes
preserve_split = yes
}
# =============================================================================
# WORKSPACE RULES (SMART GAPS)
# =============================================================================
# Replace no_gaps_when_only (removed in newer Hyprland)
# Remove gaps when there's only one visible tiled window (ignore special workspaces)
workspace = w[tv1]s[false], gapsout:0, gapsin:0
workspace = f[1]s[false], gapsout:0, gapsin:0
# Group/tabbed window configuration (built-in alternative to hy3 tabs)
group {
col.border_active = rgba(edb443ff)
col.border_inactive = rgba(091f2eff)
groupbar {
enabled = true
font_size = 12
height = 22
col.active = rgba(edb443ff)
col.inactive = rgba(091f2eff)
text_color = rgba(091f2eff)
}
}
# =============================================================================
# HY3/HYPREXPO PLUGIN CONFIG
# =============================================================================
plugin {
hy3 {
# Disable autotile to get XMonad-like manual control
autotile {
enable = false
}
# Tab configuration
tabs {
height = 22
padding = 6
render_text = true
text_font = "Sans"
text_height = 10
text_padding = 3
col.active = rgba(edb443ff)
col.inactive = rgba(091f2eff)
col.urgent = rgba(ff0000ff)
col.text.active = rgba(091f2eff)
col.text.inactive = rgba(ffffffff)
col.text.urgent = rgba(ffffffff)
}
}
hyprexpo {
# Always include workspace 1 in the overview grid
workspace_method = first 1
# Only show workspaces with windows
skip_empty = true
# 3 columns -> 3x3 grid when 9 workspaces are visible
columns = 3
}
}
# =============================================================================
# MISC
# =============================================================================
misc { misc {
force_default_wallpaper = 0 force_default_wallpaper = 0
disable_hyprland_logo = true disable_hyprland_logo = true
} }
# Scratchpad-like windows # =============================================================================
windowrule = float, title:^(htop)$ # BINDS OPTIONS
windowrule = size 80% 80%, title:^(htop)$ # =============================================================================
binds {
# Keep workspace history so "previous" can toggle back reliably.
allow_workspace_cycles = true
workspace_back_and_forth = true
}
# Chrome specific rules # =============================================================================
windowrule = float, class:^(chrome)$,title:^(.*@gmail.com.*Gmail.*)$ # WINDOW RULES
windowrule = float, class:^(chrome)$,title:^(Messages)$ # =============================================================================
windowrule = size 90% 90%, class:^(chrome)$,title:^(.*@gmail.com.*Gmail.*)$ # Float dialogs
windowrule = size 90% 90%, class:^(chrome)$,title:^(Messages)$ windowrulev2 = float, class:^()$,title:^()$
windowrulev2 = float, title:^(Picture-in-Picture)$
windowrulev2 = float, title:^(Open File)$
windowrulev2 = float, title:^(Save File)$
windowrulev2 = float, title:^(Confirm)$
# ===== KEY BINDINGS ===== # Scratchpad windows - float and size
# Based on XMonad configuration windowrulev2 = workspace special:htop silent, class:^(htop-scratch)$
windowrulev2 = float, class:^(htop-scratch)$
windowrulev2 = size 90% 90%, class:^(htop-scratch)$
windowrulev2 = center, class:^(htop-scratch)$
# Main modifier key (Super/Windows key equivalent to mod4Mask) windowrulev2 = workspace special:volume silent, class:^(?i)(pavucontrol|pavucontrol-qt|org\.pulseaudio\.pavucontrol)$
windowrulev2 = float, class:^(?i)(pavucontrol|pavucontrol-qt|org\.pulseaudio\.pavucontrol)$
windowrulev2 = size 90% 90%, class:^(?i)(pavucontrol|pavucontrol-qt|org\.pulseaudio\.pavucontrol)$
windowrulev2 = center, class:^(?i)(pavucontrol|pavucontrol-qt|org\.pulseaudio\.pavucontrol)$
windowrulev2 = workspace special:spotify silent, class:^(spotify)$
windowrulev2 = float, class:^(spotify)$
windowrulev2 = size 90% 90%, class:^(spotify)$
windowrulev2 = center, class:^(spotify)$
windowrulev2 = workspace special:element silent, class:^(Element)$
windowrulev2 = float, class:^(Element)$
windowrulev2 = size 90% 90%, class:^(Element)$
windowrulev2 = center, class:^(Element)$
windowrulev2 = workspace special:slack silent, class:^(Slack)$
windowrulev2 = float, class:^(Slack)$
windowrulev2 = size 90% 90%, class:^(Slack)$
windowrulev2 = center, class:^(Slack)$
windowrulev2 = workspace special:transmission silent, class:^(transmission-gtk)$
windowrulev2 = float, class:^(transmission-gtk)$
windowrulev2 = size 90% 90%, class:^(transmission-gtk)$
windowrulev2 = center, class:^(transmission-gtk)$
# Gmail and Messages (Chrome windows)
windowrulev2 = workspace special:gmail silent, class:^(google-chrome)$,title:^(.*@gmail.com.*Gmail.*)$
windowrulev2 = float, class:^(google-chrome)$,title:^(.*@gmail.com.*Gmail.*)$
windowrulev2 = size 90% 90%, class:^(google-chrome)$,title:^(.*@gmail.com.*Gmail.*)$
windowrulev2 = center, class:^(google-chrome)$,title:^(.*@gmail.com.*Gmail.*)$
windowrulev2 = workspace special:messages silent, class:^(google-chrome)$,title:^(Messages.*)$
windowrulev2 = float, class:^(google-chrome)$,title:^(Messages.*)$
windowrulev2 = size 90% 90%, class:^(google-chrome)$,title:^(Messages.*)$
windowrulev2 = center, class:^(google-chrome)$,title:^(Messages.*)$
# =============================================================================
# KEY BINDINGS
# =============================================================================
# Modifier keys
$mainMod = SUPER $mainMod = SUPER
$modAlt = SUPER ALT
$hyper = SUPER CTRL ALT
# Mod+Alt combination (equivalent to modalt in XMonad) # -----------------------------------------------------------------------------
$modAlt = SUPER_ALT # Program Launching
# -----------------------------------------------------------------------------
# Hyper key (equivalent to mod3Mask in XMonad)
$hyper = ALT_R
# Program launching
bind = $mainMod, P, exec, $menu bind = $mainMod, P, exec, $menu
bind = $mainMod SHIFT, P, exec, $runMenu bind = $mainMod SHIFT, P, exec, $runMenu
bind = $mainMod SHIFT, Return, exec, $terminal bind = $mainMod SHIFT, Return, exec, $terminal
# -----------------------------------------------------------------------------
# Overview (Hyprexpo)
# -----------------------------------------------------------------------------
bind = $mainMod, TAB, hyprexpo:expo, toggle
bind = $mainMod, Q, killactive, bind = $mainMod, Q, killactive,
bind = $mainMod SHIFT, C, killactive, bind = $mainMod SHIFT, C, killactive,
bind = $mainMod SHIFT, Q, exit, bind = $mainMod SHIFT, Q, exit,
bind = $mainMod, E, exec, emacsclient -c # Emacs-everywhere (like XMonad's emacs-everywhere)
bind = $mainMod, V, exec, xclip -o | xdotool type --file - bind = $mainMod, E, exec, emacsclient --eval '(emacs-everywhere)'
bind = $mainMod, V, exec, wl-paste | xdotool type --file -
# Chrome/Browser launching (equivalent to bindBringAndRaise) # Chrome/Browser (raise or spawn like XMonad's bindBringAndRaise)
bind = $modAlt, C, exec, google-chrome-stable bind = $modAlt, C, exec, ~/.config/hypr/scripts/raise-or-run.sh google-chrome google-chrome-stable
# Scratchpad equivalents (toggle special workspaces) # -----------------------------------------------------------------------------
bind = $modAlt, E, togglespecialworkspace, element # SCRATCHPADS (Special Workspaces)
bind = $modAlt, G, togglespecialworkspace, gmail # -----------------------------------------------------------------------------
bind = $modAlt, H, togglespecialworkspace, htop # Toggle scratchpads
bind = $modAlt, M, togglespecialworkspace, messages bind = $modAlt, E, exec, ~/.config/hypr/scripts/toggle-scratchpad.sh element '^Element$' - element-desktop
bind = $modAlt, K, togglespecialworkspace, slack bind = $modAlt, G, exec, ~/.config/hypr/scripts/toggle-scratchpad.sh gmail '^google-chrome$' '.*@gmail.com.*Gmail.*' google-chrome-stable --new-window https://mail.google.com/mail/u/0/#inbox
bind = $modAlt, S, togglespecialworkspace, spotify bind = $modAlt, H, exec, ~/.config/hypr/scripts/toggle-scratchpad.sh htop '^htop-scratch$' - alacritty --class htop-scratch --title htop -e htop
bind = $modAlt, T, togglespecialworkspace, transmission bind = $modAlt, M, exec, ~/.config/hypr/scripts/toggle-scratchpad.sh messages '^google-chrome$' '^Messages.*' google-chrome-stable --new-window https://messages.google.com/web/conversations
bind = $modAlt, V, togglespecialworkspace, volume bind = $modAlt, K, exec, ~/.config/hypr/scripts/toggle-scratchpad.sh slack '^Slack$' - slack
bind = $modAlt, S, exec, ~/.config/hypr/scripts/toggle-scratchpad.sh spotify '^spotify$' - spotify
bind = $modAlt, T, exec, ~/.config/hypr/scripts/toggle-scratchpad.sh transmission '^transmission-gtk$' - transmission-gtk
bind = $modAlt, V, exec, ~/.config/hypr/scripts/toggle-scratchpad.sh volume '^(pavucontrol|pavucontrol-qt|org\.pulseaudio\.pavucontrol)$' - pavucontrol
# Move windows to special workspaces # Move windows to scratchpads
bind = $modAlt SHIFT, E, movetoworkspace, special:element bind = $modAlt SHIFT, E, movetoworkspace, special:element
bind = $modAlt SHIFT, G, movetoworkspace, special:gmail bind = $modAlt SHIFT, G, movetoworkspace, special:gmail
bind = $modAlt SHIFT, H, movetoworkspace, special:htop bind = $modAlt SHIFT, H, movetoworkspace, special:htop
@@ -146,56 +299,113 @@ bind = $modAlt SHIFT, S, movetoworkspace, special:spotify
bind = $modAlt SHIFT, T, movetoworkspace, special:transmission bind = $modAlt SHIFT, T, movetoworkspace, special:transmission
bind = $modAlt SHIFT, V, movetoworkspace, special:volume bind = $modAlt SHIFT, V, movetoworkspace, special:volume
# Directional navigation (WASD keys as in XMonad) # Hidden workspace (like XMonad's NSP)
bind = $mainMod, W, movefocus, u bind = $mainMod, X, movetoworkspace, special:NSP
bind = $mainMod, S, movefocus, d bind = $mainMod SHIFT, X, togglespecialworkspace, NSP
bind = $mainMod, A, movefocus, l
bind = $mainMod, D, movefocus, r
# Move windows directionally # -----------------------------------------------------------------------------
bind = $mainMod SHIFT, W, movewindow, u # DIRECTIONAL NAVIGATION (WASD - like XMonad Navigation2D)
bind = $mainMod SHIFT, S, movewindow, d # Using hy3 dispatchers for proper tree-based navigation
bind = $mainMod SHIFT, A, movewindow, l # -----------------------------------------------------------------------------
bind = $mainMod SHIFT, D, movewindow, r
# Resize windows # Focus movement (Mod + WASD) - hy3:movefocus navigates the tree
bind = $mainMod CTRL, W, resizeactive, 0 -50 bind = $mainMod, W, hy3:movefocus, u
bind = $mainMod CTRL, S, resizeactive, 0 50 bind = $mainMod, S, hy3:movefocus, d
bind = $mainMod CTRL, A, resizeactive, -50 0 bind = $mainMod, A, hy3:movefocus, l
bind = $mainMod CTRL, D, resizeactive, 50 0 bind = $mainMod, D, hy3:movefocus, r
# Layout control # Move windows (Mod + Shift + WASD) - hy3:movewindow with once=true for swapping
bind = $mainMod, Space, exec, hyprctl dispatch layoutmsg cyclenext bind = $mainMod SHIFT, W, hy3:movewindow, u, once
bind = $mainMod CTRL, Space, fullscreen, 0 bind = $mainMod SHIFT, S, hy3:movewindow, d, once
bind = $mainMod, slash, exec, hyprctl dispatch layoutmsg orientationcycle left top bind = $mainMod SHIFT, A, hy3:movewindow, l, once
bind = $mainMod SHIFT, D, hy3:movewindow, r, once
# Resize windows (Mod + Ctrl + WASD)
binde = $mainMod CTRL, W, resizeactive, 0 -50
binde = $mainMod CTRL, S, resizeactive, 0 50
binde = $mainMod CTRL, A, resizeactive, -50 0
binde = $mainMod CTRL, D, resizeactive, 50 0
# Screen/Monitor focus (Hyper + WASD)
bind = $hyper, W, focusmonitor, u
bind = $hyper, S, focusmonitor, d
bind = $hyper, A, focusmonitor, l
bind = $hyper, D, focusmonitor, r
# Move window to monitor and follow (Hyper + Shift + WASD)
bind = $hyper SHIFT, W, movewindow, mon:u
bind = $hyper SHIFT, S, movewindow, mon:d
bind = $hyper SHIFT, A, movewindow, mon:l
bind = $hyper SHIFT, D, movewindow, mon:r
# Shift to empty workspace on screen direction (Hyper + Ctrl + WASD)
# Like XMonad's shiftToEmptyOnScreen
bind = $hyper CTRL, W, exec, ~/.config/hypr/scripts/shift-to-empty-on-screen.sh u
bind = $hyper CTRL, S, exec, ~/.config/hypr/scripts/shift-to-empty-on-screen.sh d
bind = $hyper CTRL, A, exec, ~/.config/hypr/scripts/shift-to-empty-on-screen.sh l
bind = $hyper CTRL, D, exec, ~/.config/hypr/scripts/shift-to-empty-on-screen.sh r
# -----------------------------------------------------------------------------
# LAYOUT CONTROL (XMonad-like with hy3)
# -----------------------------------------------------------------------------
# Create groups with different orientations (like XMonad layouts)
# hy3:makegroup creates a split/tab group from focused window
bind = $mainMod, Space, hy3:changegroup, toggletab
bind = $mainMod SHIFT, Space, hy3:changegroup, opposite
# Create specific group types
bind = $mainMod, H, hy3:makegroup, h
bind = $mainMod SHIFT, V, hy3:makegroup, v
# Mod+Ctrl+Space mirrors Mod+Space (tabs instead of fullscreen)
bind = $mainMod CTRL, Space, hy3:changegroup, toggletab
# Change group type (cycle h -> v -> tab)
bind = $mainMod, slash, hy3:changegroup, h
bind = $mainMod SHIFT, slash, hy3:changegroup, v
# Tab navigation (like XMonad's focus next/prev in tabbed)
bind = $mainMod, bracketright, hy3:focustab, r, wrap
bind = $mainMod, bracketleft, hy3:focustab, l, wrap
# Move window within tab group (hy3 has no movetab dispatcher)
bind = $mainMod SHIFT, bracketright, hy3:movewindow, r, visible
bind = $mainMod SHIFT, bracketleft, hy3:movewindow, l, visible
# Expand focus to parent group (like XMonad's focus parent)
bind = $mainMod, grave, hy3:expand, expand
bind = $mainMod SHIFT, grave, hy3:expand, base
# Fullscreen (like XMonad's NBFULL toggle)
bind = $mainMod, F, fullscreen, 0 bind = $mainMod, F, fullscreen, 0
bind = $mainMod SHIFT, F, fullscreen, 1 bind = $mainMod SHIFT, F, fullscreen, 1
# Toggle floating
bind = $mainMod, T, togglefloating, bind = $mainMod, T, togglefloating,
bind = $mainMod SHIFT, Y, pseudo, # dwindle pseudotile
bind = $mainMod, J, togglesplit, # dwindle split direction
bind = $mainMod, comma, exec, hyprctl dispatch splitratio -0.05
bind = $mainMod, period, exec, hyprctl dispatch splitratio +0.05
bind = $mainMod, N, exec, hyprctl dispatch layoutmsg addmaster
bind = $mainMod SHIFT, N, exec, hyprctl dispatch layoutmsg removemaster
# Focus manipulation # Resize split ratio (hy3 uses resizeactive for splits)
bind = $mainMod, Tab, exec, hyprctl dispatch focuswindow "class:$(hyprctl activewindow -j | jq -r '.class')" binde = $mainMod, comma, resizeactive, -50 0
bind = $mainMod, M, exec, hyprctl dispatch focuswindow "class:master" binde = $mainMod, period, resizeactive, 50 0
# Monitor/Screen control # Equalize window sizes on workspace (hy3)
bind = $mainMod, Z, focusmonitor, +1 bind = $mainMod SHIFT, equal, hy3:equalize, workspace
bind = $mainMod SHIFT, Z, movewindow, mon:+1
# Window management # Kill group - removes the focused window from its group
bind = $mainMod, G, exec, hyprctl clients -j | jq -r '.[] | select(.workspace.id >= 0) | "\(.title) - \(.class)"' | rofi -dmenu -i -p "Go to window" | head -1 | xargs -I {} hyprctl dispatch focuswindow "title:{}" bind = $mainMod, N, hy3:killactive
bind = $mainMod, B, exec, SELECTION=$(hyprctl clients -j | jq -r '.[] | select(.workspace.id >= 0) | "\(.title) - \(.class) [\(.address)]"' | rofi -dmenu -i -p "Bring window"); if [ -n "$SELECTION" ]; then ADDRESS=$(echo "$SELECTION" | sed 's/.*\[\(.*\)\]/\1/'); hyprctl dispatch movetoworkspace "$(hyprctl activeworkspace -j | jq -r '.id')",address:"$ADDRESS"; fi
bind = $mainMod SHIFT, B, exec, hyprctl clients -j | jq -r '.[] | select(.workspace.id >= 0) | "\(.title) - \(.class)"' | rofi -dmenu -i -p "Replace window" | head -1 | xargs -I {} hyprctl dispatch swapwindow "title:{}"
bind = $mainMod, M, exec, hyprctl dispatch togglespecialworkspace minimized
bind = $mainMod SHIFT, M, exec, hyprctl dispatch movetoworkspace special:minimized
bind = $mainMod SHIFT, H, exec, EMPTY_WS=$(hyprctl workspaces -j | jq -r 'map(select(.windows == 0)) | .[0].id // empty'); if [ -z "$EMPTY_WS" ]; then EMPTY_WS=$(hyprctl workspaces -j | jq -r 'max_by(.id).id + 1'); fi; hyprctl dispatch movetoworkspace $EMPTY_WS && hyprctl dispatch workspace $EMPTY_WS
bind = $mainMod, X, exec, hyprctl dispatch movetoworkspace special:NSP
# Workspace switching # hy3:setswallow - set a window to swallow newly spawned windows
bind = $mainMod, M, hy3:setswallow, toggle
# Minimize to special workspace (like XMonad's minimizeWindow)
bind = $mainMod SHIFT, M, movetoworkspace, special:minimized
# Restore last minimized
bind = $modAlt, Return, togglespecialworkspace, minimized
# -----------------------------------------------------------------------------
# WORKSPACE CONTROL
# -----------------------------------------------------------------------------
# Switch workspaces (1-9, 0=10)
bind = $mainMod, 1, workspace, 1 bind = $mainMod, 1, workspace, 1
bind = $mainMod, 2, workspace, 2 bind = $mainMod, 2, workspace, 2
bind = $mainMod, 3, workspace, 3 bind = $mainMod, 3, workspace, 3
@@ -207,7 +417,7 @@ bind = $mainMod, 8, workspace, 8
bind = $mainMod, 9, workspace, 9 bind = $mainMod, 9, workspace, 9
bind = $mainMod, 0, workspace, 10 bind = $mainMod, 0, workspace, 10
# Move windows to workspaces # Move window to workspace
bind = $mainMod SHIFT, 1, movetoworkspace, 1 bind = $mainMod SHIFT, 1, movetoworkspace, 1
bind = $mainMod SHIFT, 2, movetoworkspace, 2 bind = $mainMod SHIFT, 2, movetoworkspace, 2
bind = $mainMod SHIFT, 3, movetoworkspace, 3 bind = $mainMod SHIFT, 3, movetoworkspace, 3
@@ -219,27 +429,76 @@ bind = $mainMod SHIFT, 8, movetoworkspace, 8
bind = $mainMod SHIFT, 9, movetoworkspace, 9 bind = $mainMod SHIFT, 9, movetoworkspace, 9
bind = $mainMod SHIFT, 0, movetoworkspace, 10 bind = $mainMod SHIFT, 0, movetoworkspace, 10
# Move and follow to workspace # Move and follow to workspace (like XMonad's shiftThenView)
bind = $mainMod CTRL, 1, movetoworkspace, 1 bind = $mainMod CTRL, 1, movetoworkspacesilent, 1
bind = $mainMod CTRL, 2, movetoworkspace, 2 bind = $mainMod CTRL, 1, workspace, 1
bind = $mainMod CTRL, 3, movetoworkspace, 3 bind = $mainMod CTRL, 2, movetoworkspacesilent, 2
bind = $mainMod CTRL, 4, movetoworkspace, 4 bind = $mainMod CTRL, 2, workspace, 2
bind = $mainMod CTRL, 5, movetoworkspace, 5 bind = $mainMod CTRL, 3, movetoworkspacesilent, 3
bind = $mainMod CTRL, 6, movetoworkspace, 6 bind = $mainMod CTRL, 3, workspace, 3
bind = $mainMod CTRL, 7, movetoworkspace, 7 bind = $mainMod CTRL, 4, movetoworkspacesilent, 4
bind = $mainMod CTRL, 8, movetoworkspace, 8 bind = $mainMod CTRL, 4, workspace, 4
bind = $mainMod CTRL, 9, movetoworkspace, 9 bind = $mainMod CTRL, 5, movetoworkspacesilent, 5
bind = $mainMod CTRL, 0, movetoworkspace, 10 bind = $mainMod CTRL, 5, workspace, 5
bind = $mainMod CTRL, 6, movetoworkspacesilent, 6
bind = $mainMod CTRL, 6, workspace, 6
bind = $mainMod CTRL, 7, movetoworkspacesilent, 7
bind = $mainMod CTRL, 7, workspace, 7
bind = $mainMod CTRL, 8, movetoworkspacesilent, 8
bind = $mainMod CTRL, 8, workspace, 8
bind = $mainMod CTRL, 9, movetoworkspacesilent, 9
bind = $mainMod CTRL, 9, workspace, 9
bind = $mainMod CTRL, 0, movetoworkspacesilent, 10
bind = $mainMod CTRL, 0, workspace, 10
# Media keys and volume control # Workspace cycling (like XMonad's cycleWorkspaceOnCurrentScreen)
bind = , XF86AudioRaiseVolume, exec, set_volume --unmute --change-volume +5 bind = $mainMod, backslash, exec, ~/.config/hypr/scripts/workspace-back.sh
bind = , XF86AudioLowerVolume, exec, set_volume --unmute --change-volume -5
# Swap current workspace with another (like XMonad's swapWithCurrent)
bind = $hyper, 5, exec, ~/.config/hypr/scripts/swap-workspaces.sh
# Go to next empty workspace (like XMonad's moveTo Next emptyWS)
bind = $hyper, E, workspace, empty
# Move to next screen (like XMonad's shiftToNextScreenX)
bind = $mainMod, Z, focusmonitor, +1
bind = $mainMod SHIFT, Z, movewindow, mon:+1
# Shift to empty workspace and view (like XMonad's shiftToEmptyAndView)
bind = $mainMod SHIFT, H, movetoworkspace, empty
# -----------------------------------------------------------------------------
# WINDOW MANAGEMENT
# -----------------------------------------------------------------------------
# Go to window (rofi window switcher)
bind = $mainMod, G, exec, rofi -show window -show-icons
# Bring window (move to current workspace)
bind = $mainMod, B, exec, ~/.config/hypr/scripts/bring-window.sh
# Replace window (swap focused with selected - like XMonad's myReplaceWindow)
bind = $mainMod SHIFT, B, exec, ~/.config/hypr/scripts/replace-window.sh
# Gather windows of same class (like XMonad's gatherThisClass)
bind = $hyper, G, exec, ~/.config/hypr/scripts/gather-class.sh
# Focus next window of different class (like XMonad's focusNextClass)
bind = $mainMod, apostrophe, exec, ~/.config/hypr/scripts/focus-next-class.sh
# -----------------------------------------------------------------------------
# MEDIA KEYS
# -----------------------------------------------------------------------------
# Volume control (matching XMonad: Mod+I=up, Mod+K=down, Mod+U=mute)
binde = , XF86AudioRaiseVolume, exec, set_volume --unmute --change-volume +5
binde = , XF86AudioLowerVolume, exec, set_volume --unmute --change-volume -5
bind = , XF86AudioMute, exec, set_volume --toggle-mute bind = , XF86AudioMute, exec, set_volume --toggle-mute
bind = $mainMod, I, exec, set_volume --unmute --change-volume +5 binde = $mainMod, I, exec, set_volume --unmute --change-volume +5
bind = $mainMod, K, exec, set_volume --unmute --change-volume -5 binde = $mainMod, K, exec, set_volume --unmute --change-volume -5
bind = $mainMod, U, exec, set_volume --toggle-mute bind = $mainMod, U, exec, set_volume --toggle-mute
# Media player controls # Media player controls (matching XMonad: Mod+;=play, Mod+L=next, Mod+J=prev)
bind = $mainMod, semicolon, exec, playerctl play-pause bind = $mainMod, semicolon, exec, playerctl play-pause
bind = , XF86AudioPlay, exec, playerctl play-pause bind = , XF86AudioPlay, exec, playerctl play-pause
bind = , XF86AudioPause, exec, playerctl play-pause bind = , XF86AudioPause, exec, playerctl play-pause
@@ -248,47 +507,67 @@ bind = , XF86AudioNext, exec, playerctl next
bind = $mainMod, J, exec, playerctl previous bind = $mainMod, J, exec, playerctl previous
bind = , XF86AudioPrev, exec, playerctl previous bind = , XF86AudioPrev, exec, playerctl previous
# Brightness control # Mute current window (like XMonad's toggle_mute_current_window)
bind = , XF86MonBrightnessUp, exec, brightness.sh 5 bind = $hyper SHIFT, Q, exec, toggle_mute_current_window.sh
bind = , XF86MonBrightnessDown, exec, brightness.sh -5 bind = $hyper CTRL, Q, exec, toggle_mute_current_window.sh only
# Utility bindings # Brightness control
bind = $hyper, V, exec, rofi_clipit.sh binde = , XF86MonBrightnessUp, exec, brightness.sh up
bind = $hyper, Y, exec, rofi-pass binde = , XF86MonBrightnessDown, exec, brightness.sh down
bind = $hyper, H, exec, rofi_shutter
# -----------------------------------------------------------------------------
# UTILITY BINDINGS
# -----------------------------------------------------------------------------
bind = $hyper, V, exec, cliphist list | rofi -dmenu -p "Clipboard" | cliphist decode | wl-copy
bind = $hyper, P, exec, rofi-pass
bind = $hyper, H, exec, grim -g "$(slurp)" - | swappy -f -
bind = $hyper, C, exec, shell_command.sh bind = $hyper, C, exec, shell_command.sh
bind = $hyper, X, exec, rofi_command.sh bind = $hyper, X, exec, rofi_command.sh
bind = $hyper SHIFT, L, exec, dm-tool lock bind = $hyper SHIFT, L, exec, hyprlock
bind = $hyper, K, exec, rofi_kill_process.sh bind = $hyper, K, exec, rofi_kill_process.sh
bind = $hyper SHIFT, K, exec, rofi_kill_all.sh bind = $hyper SHIFT, K, exec, rofi_kill_all.sh
bind = $hyper, R, exec, rofi-systemd bind = $hyper, R, exec, rofi-systemd
bind = $hyper, 9, exec, start_synergy.sh bind = $hyper, 9, exec, start_synergy.sh
bind = $hyper, slash, exec, toggle_taffybar
bind = $hyper, Space, exec, skippy-xd
bind = $hyper, I, exec, rofi_select_input.hs bind = $hyper, I, exec, rofi_select_input.hs
bind = $hyper, O, exec, rofi_paswitch bind = $hyper, O, exec, rofi_paswitch
bind = $mainMod, apostrophe, exec, load_default_map
bind = $modAlt, apostrophe, exec, load_xkb_map # Reload config
bind = $mainMod, R, exec, hyprctl reload bind = $mainMod, R, exec, hyprctl reload
# Workspace cycling # -----------------------------------------------------------------------------
bind = $mainMod, backslash, workspace, previous # MOUSE BINDINGS
bind = $mainMod, Tab, workspace, previous # -----------------------------------------------------------------------------
# Mouse bindings
bindm = $mainMod, mouse:272, movewindow bindm = $mainMod, mouse:272, movewindow
bindm = $mainMod, mouse:273, resizewindow bindm = $mainMod, mouse:273, resizewindow
# Scroll through existing workspaces with mainMod + scroll # Scroll through workspaces
bind = $mainMod, mouse_down, workspace, e+1 bind = $mainMod, mouse_down, workspace, e+1
bind = $mainMod, mouse_up, workspace, e-1 bind = $mainMod, mouse_up, workspace, e-1
# Special workspaces for "scratchpad" applications # =============================================================================
exec-once = [workspace special:element silent] element-desktop # AUTOSTART
exec-once = [workspace special:gmail silent] google-chrome-stable --new-window https://mail.google.com/mail/u/0/#inbox # =============================================================================
exec-once = [workspace special:htop silent] alacritty --title htop -e htop
exec-once = [workspace special:messages silent] google-chrome-stable --new-window https://messages.google.com/web/conversations # Start Hyprland session target for systemd user services (e.g., waybar)
exec-once = [workspace special:slack silent] slack exec-once = systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE
exec-once = [workspace special:spotify silent] spotify exec-once = systemctl --user start hyprland-session.target
exec-once = [workspace special:transmission silent] transmission-gtk exec-once = ~/.config/hypr/scripts/workspace-history.sh
exec-once = [workspace special:volume silent] pavucontrol
# Scratchpad applications (spawn on demand via keybinds)
# exec-once = [workspace special:element silent] element-desktop
# exec-once = [workspace special:gmail silent] google-chrome-stable --new-window https://mail.google.com/mail/u/0/#inbox
# exec-once = [workspace special:htop silent] alacritty --class htop-scratch --title htop -e htop
# exec-once = [workspace special:messages silent] google-chrome-stable --new-window https://messages.google.com/web/conversations
# exec-once = [workspace special:slack silent] slack
# exec-once = [workspace special:spotify silent] spotify
# exec-once = [workspace special:transmission silent] transmission-gtk
# exec-once = [workspace special:volume silent] pavucontrol
# Clipboard history daemon
exec-once = wl-paste --type text --watch cliphist store
exec-once = wl-paste --type image --watch cliphist store
# Night light (optional - comment out if not needed)
# exec-once = wlsunset -l 37.7 -L -122.4

View File

@@ -0,0 +1,30 @@
#!/usr/bin/env bash
# Bring window to current workspace (like XMonad's bringWindow)
# Uses rofi to select a window and moves it to the current workspace
set -euo pipefail
# Get current workspace
CURRENT_WS=$(hyprctl activeworkspace -j | jq -r '.id')
# Get all windows and format for rofi
WINDOWS=$(hyprctl clients -j | jq -r '.[] | select(.workspace.id >= 0 and .workspace.id != '"$CURRENT_WS"') | "\(.title) [\(.class)] - WS:\(.workspace.id) |\(.address)"')
if [ -z "$WINDOWS" ]; then
notify-send "Bring Window" "No windows on other workspaces"
exit 0
fi
# Show rofi menu
SELECTION=$(echo "$WINDOWS" | rofi -dmenu -i -p "Bring window" -format 's')
if [ -n "$SELECTION" ]; then
# Extract the window address (after the last |)
ADDRESS=$(echo "$SELECTION" | sed 's/.*|//')
# Move window to current workspace
hyprctl dispatch movetoworkspace "$CURRENT_WS,address:$ADDRESS"
# Focus the window
hyprctl dispatch focuswindow "address:$ADDRESS"
fi

View File

@@ -0,0 +1,15 @@
#!/usr/bin/env bash
# Cycle between master and dwindle layouts
# Like XMonad's NextLayout
set -euo pipefail
CURRENT=$(hyprctl getoption general:layout -j | jq -r '.str')
if [ "$CURRENT" = "master" ]; then
hyprctl keyword general:layout dwindle
notify-send "Layout" "Switched to Dwindle (binary tree)"
else
hyprctl keyword general:layout master
notify-send "Layout" "Switched to Master (XMonad-like)"
fi

View File

@@ -0,0 +1,48 @@
#!/usr/bin/env bash
# Focus next window of a different class (like XMonad's focusNextClass)
set -euo pipefail
# Get focused window class
FOCUSED_CLASS=$(hyprctl activewindow -j | jq -r '.class')
FOCUSED_ADDR=$(hyprctl activewindow -j | jq -r '.address')
if [ "$FOCUSED_CLASS" = "null" ] || [ -z "$FOCUSED_CLASS" ]; then
# No focused window, just focus any window
hyprctl dispatch cyclenext
exit 0
fi
# Get all unique classes
ALL_CLASSES=$(hyprctl clients -j | jq -r '[.[] | select(.workspace.id >= 0) | .class] | unique | .[]')
# Get sorted list of classes
CLASSES_ARRAY=()
while IFS= read -r class; do
CLASSES_ARRAY+=("$class")
done <<< "$ALL_CLASSES"
# Find current class index and get next class
CURRENT_INDEX=-1
for i in "${!CLASSES_ARRAY[@]}"; do
if [ "${CLASSES_ARRAY[$i]}" = "$FOCUSED_CLASS" ]; then
CURRENT_INDEX=$i
break
fi
done
if [ $CURRENT_INDEX -eq -1 ] || [ ${#CLASSES_ARRAY[@]} -le 1 ]; then
# Only one class or class not found
exit 0
fi
# Get next class (wrapping around)
NEXT_INDEX=$(( (CURRENT_INDEX + 1) % ${#CLASSES_ARRAY[@]} ))
NEXT_CLASS="${CLASSES_ARRAY[$NEXT_INDEX]}"
# Find first window of next class
NEXT_WINDOW=$(hyprctl clients -j | jq -r ".[] | select(.class == \"$NEXT_CLASS\" and .workspace.id >= 0) | .address" | head -1)
if [ -n "$NEXT_WINDOW" ]; then
hyprctl dispatch focuswindow "address:$NEXT_WINDOW"
fi

View File

@@ -0,0 +1,30 @@
#!/usr/bin/env bash
# Gather all windows of the same class as focused window (like XMonad's gatherThisClass)
set -euo pipefail
# Get focused window class
FOCUSED_CLASS=$(hyprctl activewindow -j | jq -r '.class')
CURRENT_WS=$(hyprctl activeworkspace -j | jq -r '.id')
if [ "$FOCUSED_CLASS" = "null" ] || [ -z "$FOCUSED_CLASS" ]; then
notify-send "Gather Class" "No focused window"
exit 0
fi
# Find all windows with same class on other workspaces
WINDOWS=$(hyprctl clients -j | jq -r ".[] | select(.class == \"$FOCUSED_CLASS\" and .workspace.id != $CURRENT_WS and .workspace.id >= 0) | .address")
if [ -z "$WINDOWS" ]; then
notify-send "Gather Class" "No other windows of class '$FOCUSED_CLASS'"
exit 0
fi
# Move each window to current workspace
COUNT=0
for ADDR in $WINDOWS; do
hyprctl dispatch movetoworkspace "$CURRENT_WS,address:$ADDR"
((COUNT++))
done
notify-send "Gather Class" "Gathered $COUNT windows of class '$FOCUSED_CLASS'"

View File

@@ -0,0 +1,19 @@
#!/usr/bin/env bash
# Raise existing window or run command (like XMonad's raiseNextMaybe)
# Usage: raise-or-run.sh <class-pattern> <command>
set -euo pipefail
CLASS_PATTERN="$1"
COMMAND="$2"
# Find windows matching the class pattern
MATCHING=$(hyprctl clients -j | jq -r ".[] | select(.class | test(\"$CLASS_PATTERN\"; \"i\")) | .address" | head -1)
if [ -n "$MATCHING" ]; then
# Window exists, focus it
hyprctl dispatch focuswindow "address:$MATCHING"
else
# No matching window, run the command
exec $COMMAND
fi

View File

@@ -0,0 +1,33 @@
#!/usr/bin/env bash
# Replace focused window with selected window (like XMonad's myReplaceWindow)
# Swaps the positions of focused window and selected window
set -euo pipefail
# Get current workspace and focused window
CURRENT_WS=$(hyprctl activeworkspace -j | jq -r '.id')
FOCUSED=$(hyprctl activewindow -j | jq -r '.address')
if [ "$FOCUSED" = "null" ] || [ -z "$FOCUSED" ]; then
notify-send "Replace Window" "No focused window"
exit 0
fi
# Get all windows except focused
WINDOWS=$(hyprctl clients -j | jq -r ".[] | select(.workspace.id >= 0 and .address != \"$FOCUSED\") | \"\(.title) [\(.class)] - WS:\(.workspace.id) |\(.address)\"")
if [ -z "$WINDOWS" ]; then
notify-send "Replace Window" "No other windows available"
exit 0
fi
# Show rofi menu
SELECTION=$(echo "$WINDOWS" | rofi -dmenu -i -p "Replace with" -format 's')
if [ -n "$SELECTION" ]; then
# Extract the window address
ADDRESS=$(echo "$SELECTION" | sed 's/.*|//')
# Swap windows using hy3
hyprctl dispatch hy3:movewindow "address:$ADDRESS"
fi

View File

@@ -0,0 +1,39 @@
#!/usr/bin/env bash
# Shift window to empty workspace on screen in given direction
# Like XMonad's shiftToEmptyOnScreen
# Usage: shift-to-empty-on-screen.sh <direction: u|d|l|r>
set -euo pipefail
DIRECTION="$1"
# Track the current monitor so we can return
ORIG_MONITOR=$(hyprctl activeworkspace -j | jq -r '.monitor')
# Move focus to the screen in that direction
hyprctl dispatch focusmonitor "$DIRECTION"
# Get the monitor we're now on (target monitor)
MONITOR=$(hyprctl activeworkspace -j | jq -r '.monitor')
# If there is no monitor in that direction, bail
if [ "$MONITOR" = "$ORIG_MONITOR" ]; then
exit 0
fi
# Find an empty workspace or create one
# First check if there's an empty workspace on this monitor
EMPTY_WS=$(hyprctl workspaces -j | jq -r ".[] | select(.windows == 0 and .monitor == \"$MONITOR\") | .id" | head -1)
if [ -z "$EMPTY_WS" ]; then
# No empty workspace, find next available workspace number
MAX_WS=$(hyprctl workspaces -j | jq -r 'map(.id) | max')
EMPTY_WS=$((MAX_WS + 1))
fi
# Ensure the workspace exists on the target monitor
hyprctl dispatch workspace "$EMPTY_WS"
# Go back to original monitor and move the window (without following)
hyprctl dispatch focusmonitor "$ORIG_MONITOR"
hyprctl dispatch movetoworkspacesilent "$EMPTY_WS"

View File

@@ -0,0 +1,45 @@
#!/usr/bin/env bash
# Swap the contents of the current workspace with another workspace.
# Intended to mirror XMonad's swapWithCurrent behavior.
set -euo pipefail
CURRENT_WS="$(hyprctl activeworkspace -j | jq -r '.id')"
if [[ -z "${CURRENT_WS}" || "${CURRENT_WS}" == "null" ]]; then
exit 0
fi
TARGET_WS="${1:-}"
if [[ -z "${TARGET_WS}" ]]; then
WS_LIST="$({
seq 1 10
hyprctl workspaces -j | jq -r '.[].id' 2>/dev/null || true
} | awk 'NF {print $1}' | awk '!seen[$0]++' | sort -n)"
TARGET_WS="$(printf "%s\n" "${WS_LIST}" | rofi -dmenu -p "Swap with workspace")"
fi
if [[ -z "${TARGET_WS}" || "${TARGET_WS}" == "null" ]]; then
exit 0
fi
if [[ "${TARGET_WS}" == "${CURRENT_WS}" ]]; then
exit 0
fi
if ! [[ "${TARGET_WS}" =~ ^-?[0-9]+$ ]]; then
notify-send "Swap Workspace" "Invalid workspace: ${TARGET_WS}"
exit 1
fi
WINDOWS_CURRENT="$(hyprctl clients -j | jq -r --arg ws "${CURRENT_WS}" '.[] | select((.workspace.id|tostring) == $ws) | .address')"
WINDOWS_TARGET="$(hyprctl clients -j | jq -r --arg ws "${TARGET_WS}" '.[] | select((.workspace.id|tostring) == $ws) | .address')"
for ADDR in ${WINDOWS_CURRENT}; do
hyprctl dispatch movetoworkspace "${TARGET_WS},address:${ADDR}"
done
for ADDR in ${WINDOWS_TARGET}; do
hyprctl dispatch movetoworkspace "${CURRENT_WS},address:${ADDR}"
done

View File

@@ -0,0 +1,51 @@
#!/usr/bin/env bash
# Toggle a named Hyprland scratchpad, spawning it if needed.
# Usage: toggle-scratchpad.sh <name> <class_regex|-> <title_regex|-> <command...>
set -euo pipefail
if [ "$#" -lt 4 ]; then
echo "usage: $0 <name> <class_regex|-> <title_regex|-> <command...>" >&2
exit 1
fi
NAME="$1"
shift
CLASS_REGEX="$1"
shift
TITLE_REGEX="$1"
shift
COMMAND=("$@")
if [ "$CLASS_REGEX" = "-" ]; then
CLASS_REGEX=""
fi
if [ "$TITLE_REGEX" = "-" ]; then
TITLE_REGEX=""
fi
if [ -z "$CLASS_REGEX" ] && [ -z "$TITLE_REGEX" ]; then
echo "toggle-scratchpad: provide a class or title regex" >&2
exit 1
fi
MATCHING=$(hyprctl clients -j | jq -r --arg cre "$CLASS_REGEX" --arg tre "$TITLE_REGEX" '
.[]
| select(
(($cre == "") or (.class | test($cre; "i")))
and
(($tre == "") or (.title | test($tre; "i")))
)
| .address
')
if [ -z "$MATCHING" ]; then
"${COMMAND[@]}" &
else
while IFS= read -r ADDR; do
[ -n "$ADDR" ] || continue
hyprctl dispatch movetoworkspacesilent "special:$NAME,address:$ADDR"
done <<< "$MATCHING"
fi
hyprctl dispatch togglespecialworkspace "$NAME"

View File

@@ -0,0 +1,13 @@
#!/usr/bin/env bash
set -euo pipefail
runtime_dir="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
state_dir="${runtime_dir}/hypr"
prev_file="${state_dir}/prev-workspace"
prev="$(cat "${prev_file}" 2>/dev/null || true)"
if [[ -z "${prev}" ]]; then
exit 0
fi
hyprctl dispatch workspace "${prev}" >/dev/null 2>&1 || true

View File

@@ -0,0 +1,60 @@
#!/usr/bin/env bash
set -euo pipefail
runtime_dir="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
sig="${HYPRLAND_INSTANCE_SIGNATURE:-}"
if [[ -z "$sig" ]]; then
exit 0
fi
sock="${runtime_dir}/hypr/${sig}/.socket2.sock"
state_dir="${runtime_dir}/hypr"
last_file="${state_dir}/last-workspace"
prev_file="${state_dir}/prev-workspace"
mkdir -p "${state_dir}"
# Initialize current workspace to avoid empty state.
if command -v hyprctl >/dev/null 2>&1; then
cur_id="$(hyprctl activeworkspace -j | jq -r '.id' 2>/dev/null || true)"
if [[ -n "${cur_id}" && "${cur_id}" != "null" ]]; then
echo "${cur_id}" > "${last_file}"
fi
fi
# Wait for the event socket to be ready.
while [[ ! -S "${sock}" ]]; do
sleep 0.2
done
nc -U "${sock}" | while read -r line; do
case "${line}" in
workspace*">>"*)
payload="${line#*>>}"
# Handle workspacev2 payloads: id,name
if [[ "${payload}" == *","* ]]; then
ws_id="${payload%%,*}"
ws_name="${payload#*,}"
else
ws_id="${payload}"
ws_name="${payload}"
fi
# Ignore special/negative workspaces.
if [[ "${ws_id}" =~ ^- ]] || [[ "${ws_name}" == special:* ]]; then
continue
fi
ws_ident="${ws_name}"
if [[ -z "${ws_ident}" ]]; then
ws_ident="${ws_id}"
fi
prev="$(cat "${last_file}" 2>/dev/null || true)"
if [[ -n "${prev}" && "${ws_ident}" != "${prev}" ]]; then
echo "${prev}" > "${prev_file}"
fi
echo "${ws_ident}" > "${last_file}"
;;
esac
done

View File

@@ -8,7 +8,7 @@
*/ */
configuration { configuration {
font: "Noto Sans 10"; font: "Fira Code 10";
show-icons: true; show-icons: true;
display-drun: ""; display-drun: "";
drun-display-format: "{name}"; drun-display-format: "{name}";
@@ -25,7 +25,7 @@ window {
border: 0px; border: 0px;
border-color: @ac; border-color: @ac;
border-radius: 12px; border-radius: 12px;
width: 30%; width: 40%;
location: center; location: center;
x-offset: 0; x-offset: 0;
y-offset: 0; y-offset: 0;
@@ -36,7 +36,6 @@ prompt {
padding: 0.30% 1% 0% -0.5%; padding: 0.30% 1% 0% -0.5%;
background-color: @al; background-color: @al;
text-color: @fg; text-color: @fg;
font: "Fira Code 12";
} }
entry { entry {

View File

@@ -5,7 +5,8 @@ configuration {
terminal: "alacritty"; terminal: "alacritty";
sidebar-mode: false; sidebar-mode: false;
fullscreen: true; fullscreen: true;
dpi: 100; /* Let rofi auto-detect DPI under Wayland/Xwayland to avoid blurry scaling. */
dpi: 0;
} }
@theme "colorful/style_7.rasi" @theme "colorful/style_7.rasi"

View File

@@ -28,7 +28,6 @@ import System.Log.Handler.Simple
import System.Log.Logger import System.Log.Logger
import System.Process import System.Process
import System.Taffybar import System.Taffybar
import System.Taffybar.Auth
import System.Taffybar.Context (appendHook) import System.Taffybar.Context (appendHook)
import System.Taffybar.DBus import System.Taffybar.DBus
import System.Taffybar.DBus.Toggle import System.Taffybar.DBus.Toggle
@@ -40,7 +39,6 @@ import System.Taffybar.Information.X11DesktopInfo
import System.Taffybar.SimpleConfig import System.Taffybar.SimpleConfig
import System.Taffybar.Util import System.Taffybar.Util
import System.Taffybar.Widget import System.Taffybar.Widget
import System.Taffybar.Widget.Crypto
import System.Taffybar.Widget.Generic.Icon import System.Taffybar.Widget.Generic.Icon
import System.Taffybar.Widget.Generic.PollingGraph import System.Taffybar.Widget.Generic.PollingGraph
import System.Taffybar.Widget.Generic.PollingLabel import System.Taffybar.Widget.Generic.PollingLabel
@@ -174,9 +172,6 @@ main = do
{ clockUpdateStrategy = RoundedTargetInterval 60 0.0 { clockUpdateStrategy = RoundedTargetInterval 60 0.0
, clockFormatString = "%a %b %_d, 🕑%I:%M %p" , clockFormatString = "%a %b %_d, 🕑%I:%M %p"
} }
myICP = deocrateWithSetClassAndBoxes "icp" $ cryptoPriceLabelWithIcon @"ICP-USD"
myBTC = deocrateWithSetClassAndBoxes "btc" $ cryptoPriceLabelWithIcon @"BTC-USD"
myETH = deocrateWithSetClassAndBoxes "eth" $ cryptoPriceLabelWithIcon @"ETH-USD"
myTray = deocrateWithSetClassAndBoxes "tray" $ myTray = deocrateWithSetClassAndBoxes "tray" $
sniTrayNewFromParams defaultTrayParams { trayLeftClickAction = PopupMenu sniTrayNewFromParams defaultTrayParams { trayLeftClickAction = PopupMenu
, trayRightClickAction = Activate , trayRightClickAction = Activate
@@ -194,9 +189,6 @@ main = do
batteryWidgets = [myBatteryIcon, myBatteryText] batteryWidgets = [myBatteryIcon, myBatteryText]
baseEndWidgets = baseEndWidgets =
[ myTray [ myTray
, myICP
, myBTC
, myETH
, myMpris , myMpris
] ]
fullEndWidgets = baseEndWidgets ++ [ myCPU, myMem, myNet, myMpris ] fullEndWidgets = baseEndWidgets ++ [ myCPU, myMem, myNet, myMpris ]
@@ -210,7 +202,6 @@ main = do
, barPadding = 0 , barPadding = 0
, barHeight = ScreenRatio $ 1/27 , barHeight = ScreenRatio $ 1/27
, cssPaths = cssFiles , cssPaths = cssFiles
, startupHook = void $ setCMCAPIKey "f9e66366-9d42-4c6e-8d40-4194a0aaa329"
, centerWidgets = [ myClock ] , centerWidgets = [ myClock ]
} }
selectedConfig = selectedConfig =

View File

@@ -0,0 +1,103 @@
// -*- mode: jsonc -*-
{
"height": 42,
"spacing": 4,
"modules-left": [
"hyprland/workspaces",
"hyprland/submap"
],
"modules-center": [
"hyprland/window"
],
"modules-right": [
"idle_inhibitor",
"pulseaudio",
"network",
"power-profiles-daemon",
"cpu",
"memory",
"custom/diskfree",
"temperature",
"backlight",
"battery",
"clock",
"tray"
],
"idle_inhibitor": {
"format": "INHIB {icon}",
"format-icons": {
"activated": "ON",
"deactivated": "OFF"
}
},
"tray": {
"spacing": 10
},
"clock": {
"format": "{:%H:%M}",
"tooltip-format": "{:%Y %B}\n{calendar}",
"format-alt": "{:%Y-%m-%d}"
},
"cpu": {
"format": "CPU {usage}%",
"tooltip": false
},
"memory": {
"format": "MEM {}%"
},
"custom/diskfree": {
"exec": "~/.config/waybar/scripts/diskfree",
"interval": 30,
"format": "DISK {text}",
"tooltip": false
},
"temperature": {
"critical-threshold": 80,
"format": "TEMP {temperatureC}C"
},
"backlight": {
"format": "BL {percent}%"
},
"battery": {
"states": {
"warning": 30,
"critical": 15
},
"format": "BAT {capacity}%",
"format-full": "BAT {capacity}%",
"format-charging": "BAT {capacity}% charging",
"format-plugged": "BAT {capacity}% plugged",
"format-alt": "BAT {time}"
},
"power-profiles-daemon": {
"format": "PWR {profile}",
"tooltip-format": "Power profile: {profile}\nDriver: {driver}",
"tooltip": true
},
"network": {
"format-wifi": "WIFI {essid} {signalStrength}%",
"format-ethernet": "ETH {ipaddr}/{cidr}",
"tooltip-format": "{ifname} via {gwaddr}",
"format-linked": "{ifname} (No IP)",
"format-disconnected": "NET disconnected",
"format-alt": "{ifname}: {ipaddr}/{cidr}"
},
"pulseaudio": {
"format": "VOL {volume}%",
"format-muted": "VOL muted",
"format-source": "MIC {volume}%",
"format-source-muted": "MIC muted",
"on-click": "pavucontrol"
},
"hyprland/workspaces": {
"format": "{id} {windows}",
"on-click": "activate",
"workspace-taskbar": {
"enable": true,
"update-active-window": true,
"format": "{icon}",
"icon-size": 24,
"on-click-window": "hyprctl dispatch focuswindow address:{address}"
}
}
}

View File

@@ -0,0 +1,45 @@
#!/usr/bin/env bash
set -euo pipefail
config_dir="${XDG_CONFIG_HOME:-$HOME/.config}/waybar"
list_file="${config_dir}/disks"
mounts=()
if [[ -n "${WAYBAR_DISKS:-}" ]]; then
# Accept comma or space separated values.
IFS=', ' read -r -a mounts <<< "${WAYBAR_DISKS//:/,}"
elif [[ -f "$list_file" ]]; then
while IFS= read -r line; do
line="${line%%#*}"
line="${line#"${line%%[![:space:]]*}"}"
line="${line%"${line##*[![:space:]]}"}"
[[ -z "$line" ]] && continue
mounts+=("$line")
done < "$list_file"
fi
if [[ ${#mounts[@]} -eq 0 ]]; then
mounts=("/")
fi
items=()
for mount in "${mounts[@]}"; do
if df_out=$(df -h --output=avail,target "$mount" 2>/dev/null | awk 'NR==2 {print $2, $1}'); then
items+=("$df_out")
fi
done
if [[ ${#items[@]} -eq 0 ]]; then
exit 0
fi
output=""
for item in "${items[@]}"; do
if [[ -n "$output" ]]; then
output+=" | "
fi
output+="$item"
done
printf '%s\n' "$output"

View File

@@ -0,0 +1,361 @@
* {
/* `otf-font-awesome` is required to be installed for icons */
font-family: FontAwesome, Roboto, Helvetica, Arial, sans-serif;
font-size: 14px;
}
window#waybar {
background-color: rgba(43, 48, 59, 0.5);
border-bottom: 3px solid rgba(100, 114, 125, 0.5);
color: #ffffff;
transition-property: background-color;
transition-duration: .5s;
}
window#waybar.hidden {
opacity: 0.2;
}
/*
window#waybar.empty {
background-color: transparent;
}
window#waybar.solo {
background-color: #FFFFFF;
}
*/
window#waybar.termite {
background-color: #3F3F3F;
}
window#waybar.chromium {
background-color: #000000;
border: none;
}
button {
/* Use box-shadow instead of border so the text isn't offset */
box-shadow: inset 0 -3px transparent;
/* Avoid rounded borders under each button name */
border: none;
border-radius: 0;
}
/* https://github.com/Alexays/Waybar/wiki/FAQ#the-workspace-buttons-have-a-strange-hover-effect */
button:hover {
background: inherit;
box-shadow: inset 0 -3px #ffffff;
}
/* you can set a style on hover for any module like this */
#pulseaudio:hover {
background-color: #a37800;
}
#workspaces button,
#taskbar button {
padding: 0 3px;
background-color: transparent;
color: #ffffff;
}
#workspaces button:hover,
#taskbar button:hover {
background: rgba(0, 0, 0, 0.2);
}
#workspaces button.focused,
#taskbar button.active,
#taskbar button.focused {
background-color: #64727D;
box-shadow: inset 0 -3px #ffffff;
}
#workspaces button.urgent,
#taskbar button.urgent {
background-color: #eb4d4b;
}
#workspaces .workspace-label {
padding: 0 2px;
}
#workspaces .taskbar-window {
padding: 0 2px;
}
#workspaces .taskbar-window.active {
background-color: #64727D;
box-shadow: inset 0 -3px #ffffff;
}
#workspaces .taskbar-window label {
color: #ffffff;
}
#workspaces .taskbar-window image {
margin: 0 1px;
}
#mode {
background-color: #64727D;
box-shadow: inset 0 -3px #ffffff;
}
#clock,
#battery,
#cpu,
#memory,
#disk,
#custom-diskfree,
#temperature,
#backlight,
#network,
#pulseaudio,
#wireplumber,
#custom-media,
#tray,
#mode,
#idle_inhibitor,
#scratchpad,
#power-profiles-daemon,
#mpd {
padding: 0 8px;
color: #ffffff;
}
#window,
#workspaces,
#taskbar {
margin: 0 4px;
}
/* If workspaces is the leftmost module, omit left margin */
.modules-left > widget:first-child > #workspaces,
.modules-left > widget:first-child > #taskbar {
margin-left: 0;
}
/* If workspaces is the rightmost module, omit right margin */
.modules-right > widget:last-child > #workspaces,
.modules-right > widget:last-child > #taskbar {
margin-right: 0;
}
#clock {
background-color: #64727D;
}
#battery {
background-color: #ffffff;
color: #000000;
}
#battery.charging, #battery.plugged {
color: #ffffff;
background-color: #26A65B;
}
@keyframes blink {
to {
background-color: #ffffff;
color: #000000;
}
}
/* Using steps() instead of linear as a timing function to limit cpu usage */
#battery.critical:not(.charging) {
background-color: #f53c3c;
color: #ffffff;
animation-name: blink;
animation-duration: 0.5s;
animation-timing-function: steps(12);
animation-iteration-count: infinite;
animation-direction: alternate;
}
#power-profiles-daemon {
padding-right: 15px;
}
#power-profiles-daemon.performance {
background-color: #f53c3c;
color: #ffffff;
}
#power-profiles-daemon.balanced {
background-color: #2980b9;
color: #ffffff;
}
#power-profiles-daemon.power-saver {
background-color: #2ecc71;
color: #000000;
}
label:focus {
background-color: #000000;
}
#cpu {
background-color: #2ecc71;
color: #000000;
}
#memory {
background-color: #9b59b6;
}
#disk {
background-color: #964B00;
}
#custom-diskfree {
background-color: #964B00;
}
#backlight {
background-color: #90b1b1;
}
#network {
background-color: #2980b9;
}
#network.disconnected {
background-color: #f53c3c;
}
#pulseaudio {
background-color: #f1c40f;
color: #000000;
}
#pulseaudio.muted {
background-color: #90b1b1;
color: #2a5c45;
}
#wireplumber {
background-color: #fff0f5;
color: #000000;
}
#wireplumber.muted {
background-color: #f53c3c;
}
#custom-media {
background-color: #66cc99;
color: #2a5c45;
min-width: 100px;
}
#custom-media.custom-spotify {
background-color: #66cc99;
}
#custom-media.custom-vlc {
background-color: #ffa000;
}
#temperature {
background-color: #f0932b;
}
#temperature.critical {
background-color: #eb4d4b;
}
#tray {
background-color: #2980b9;
}
#tray > .passive {
-gtk-icon-effect: dim;
}
#tray > .needs-attention {
-gtk-icon-effect: highlight;
background-color: #eb4d4b;
}
#idle_inhibitor {
background-color: #2d3436;
}
#idle_inhibitor.activated {
background-color: #ecf0f1;
color: #2d3436;
}
#mpd {
background-color: #66cc99;
color: #2a5c45;
}
#mpd.disconnected {
background-color: #f53c3c;
}
#mpd.stopped {
background-color: #90b1b1;
}
#mpd.paused {
background-color: #51a37a;
}
#language {
background: #00b093;
color: #740864;
padding: 0 5px;
margin: 0 5px;
min-width: 16px;
}
#keyboard-state {
background: #97e1ad;
color: #000000;
padding: 0 0px;
margin: 0 5px;
min-width: 16px;
}
#keyboard-state > label {
padding: 0 5px;
}
#keyboard-state > label.locked {
background: rgba(0, 0, 0, 0.2);
}
#scratchpad {
background: rgba(0, 0, 0, 0.2);
}
#scratchpad.empty {
background-color: transparent;
}
#privacy {
padding: 0;
}
#privacy-item {
padding: 0 5px;
color: white;
}
#privacy-item.screenshare {
background-color: #cf5700;
}
#privacy-item.audio-in {
background-color: #1ca000;
}
#privacy-item.audio-out {
background-color: #0069d4;
}

View File

@@ -5,11 +5,11 @@
"systems": "systems" "systems": "systems"
}, },
"locked": { "locked": {
"lastModified": 1694529238, "lastModified": 1731533236,
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384", "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -23,11 +23,11 @@
"systems": "systems_2" "systems": "systems_2"
}, },
"locked": { "locked": {
"lastModified": 1694529238, "lastModified": 1731533236,
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384", "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -41,29 +41,11 @@
"systems": "systems_3" "systems": "systems_3"
}, },
"locked": { "locked": {
"lastModified": 1694529238, "lastModified": 1731533236,
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384", "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_4": {
"inputs": {
"systems": "systems_4"
},
"locked": {
"lastModified": 1694529238,
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -74,19 +56,18 @@
}, },
"git-ignore-nix": { "git-ignore-nix": {
"inputs": { "inputs": {
"nixpkgs": "nixpkgs_2" "nixpkgs": "nixpkgs"
}, },
"locked": { "locked": {
"lastModified": 1694102001, "lastModified": 1762808025,
"narHash": "sha256-vky6VPK1n1od6vXbqzOXnekrQpTL4hbPAwUhT5J9c9E=", "narHash": "sha256-XmjITeZNMTQXGhhww6ed/Wacy2KzD6svioyCX7pkUu4=",
"owner": "hercules-ci", "owner": "hercules-ci",
"repo": "gitignore.nix", "repo": "gitignore.nix",
"rev": "9e21c80adf67ebcb077d75bd5e7d724d21eeafd6", "rev": "cb5e3fdca1de58ccbc3ef53de65bd372b48f567c",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "hercules-ci", "owner": "hercules-ci",
"ref": "master",
"repo": "gitignore.nix", "repo": "gitignore.nix",
"type": "github" "type": "github"
} }
@@ -96,11 +77,11 @@
"nixpkgs": "nixpkgs_3" "nixpkgs": "nixpkgs_3"
}, },
"locked": { "locked": {
"lastModified": 1694102001, "lastModified": 1762808025,
"narHash": "sha256-vky6VPK1n1od6vXbqzOXnekrQpTL4hbPAwUhT5J9c9E=", "narHash": "sha256-XmjITeZNMTQXGhhww6ed/Wacy2KzD6svioyCX7pkUu4=",
"owner": "hercules-ci", "owner": "hercules-ci",
"repo": "gitignore.nix", "repo": "gitignore.nix",
"rev": "9e21c80adf67ebcb077d75bd5e7d724d21eeafd6", "rev": "cb5e3fdca1de58ccbc3ef53de65bd372b48f567c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -115,11 +96,11 @@
"nixpkgs": "nixpkgs_4" "nixpkgs": "nixpkgs_4"
}, },
"locked": { "locked": {
"lastModified": 1694102001, "lastModified": 1762808025,
"narHash": "sha256-vky6VPK1n1od6vXbqzOXnekrQpTL4hbPAwUhT5J9c9E=", "narHash": "sha256-XmjITeZNMTQXGhhww6ed/Wacy2KzD6svioyCX7pkUu4=",
"owner": "hercules-ci", "owner": "hercules-ci",
"repo": "gitignore.nix", "repo": "gitignore.nix",
"rev": "9e21c80adf67ebcb077d75bd5e7d724d21eeafd6", "rev": "cb5e3fdca1de58ccbc3ef53de65bd372b48f567c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -131,11 +112,12 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1693099187, "lastModified": 1666603677,
"narHash": "sha256-FXCc6OIghv9k4xYOhSMZI6bj7o56S8BJKzKtTKzdUVQ=", "narHash": "sha256-apAEIj+z1iwMaMJ4tB21r/VTetfGDLDzuhXRHJknIAU=",
"path": "/nix/store/wr9zk0l6xw1bi0zjrrsj998b5wgykyz5-source", "owner": "NixOS",
"rev": "cf2004afe4d4b95a295c63c911e949e40915eedb", "repo": "nixpkgs",
"type": "path" "rev": "074da18a72269cc5a6cf444dce42daea5649b2fe",
"type": "github"
}, },
"original": { "original": {
"id": "nixpkgs", "id": "nixpkgs",
@@ -144,11 +126,11 @@
}, },
"nixpkgs_2": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1666603677, "lastModified": 1769740369,
"narHash": "sha256-apAEIj+z1iwMaMJ4tB21r/VTetfGDLDzuhXRHJknIAU=", "narHash": "sha256-xKPyJoMoXfXpDM5DFDZDsi9PHArf2k5BJjvReYXoFpM=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "074da18a72269cc5a6cf444dce42daea5649b2fe", "rev": "6308c3b21396534d8aaeac46179c14c439a89b8a",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -184,23 +166,11 @@
"type": "indirect" "type": "indirect"
} }
}, },
"nixpkgs_5": {
"locked": {
"lastModified": 1693099187,
"narHash": "sha256-FXCc6OIghv9k4xYOhSMZI6bj7o56S8BJKzKtTKzdUVQ=",
"path": "/nix/store/wr9zk0l6xw1bi0zjrrsj998b5wgykyz5-source",
"rev": "cf2004afe4d4b95a295c63c911e949e40915eedb",
"type": "path"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"root": { "root": {
"inputs": { "inputs": {
"flake-utils": "flake-utils", "flake-utils": "flake-utils",
"nixpkgs": "nixpkgs", "git-ignore-nix": "git-ignore-nix",
"nixpkgs": "nixpkgs_2",
"xmonad": "xmonad", "xmonad": "xmonad",
"xmonad-contrib": "xmonad-contrib" "xmonad-contrib": "xmonad-contrib"
} }
@@ -250,44 +220,13 @@
"type": "github" "type": "github"
} }
}, },
"systems_4": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"unstable": { "unstable": {
"locked": { "locked": {
"lastModified": 1696019113, "lastModified": 1769461804,
"narHash": "sha256-X3+DKYWJm93DRSdC5M6K5hLqzSya9BjibtBsuARoPco=", "narHash": "sha256-msG8SU5WsBUfVVa/9RPLaymvi5bI8edTavbIq3vRlhI=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "f5892ddac112a1e9b3612c39af1b72987ee5783a", "rev": "bfc1b8a4574108ceef22f02bafcf6611380c100d",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"unstable_2": {
"locked": {
"lastModified": 1696019113,
"narHash": "sha256-X3+DKYWJm93DRSdC5M6K5hLqzSya9BjibtBsuARoPco=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "f5892ddac112a1e9b3612c39af1b72987ee5783a",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -300,56 +239,18 @@
"xmonad": { "xmonad": {
"inputs": { "inputs": {
"flake-utils": "flake-utils_2", "flake-utils": "flake-utils_2",
"git-ignore-nix": "git-ignore-nix", "git-ignore-nix": "git-ignore-nix_2",
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
], ],
"unstable": "unstable" "unstable": "unstable"
}, },
"locked": { "locked": {
"lastModified": 1, "lastModified": 1767819257,
"narHash": "sha256-dOrvPpypuNn/fAWY2XjMacpsAXEiMZ4Dll3Ot81iQL4=", "narHash": "sha256-U7MIHr0B10wDSNgUvq4QTK22HZ4pl2oIYkdOKEMnxC4=",
"path": "./xmonad",
"type": "path"
},
"original": {
"path": "./xmonad",
"type": "path"
}
},
"xmonad-contrib": {
"inputs": {
"flake-utils": "flake-utils_3",
"git-ignore-nix": "git-ignore-nix_2",
"nixpkgs": [
"nixpkgs"
],
"xmonad": "xmonad_2"
},
"locked": {
"lastModified": 1,
"narHash": "sha256-MwbeBTfcf6vE7bQvha4ueg5zLZxBiU3678ESYrXD4lw=",
"path": "./xmonad-contrib",
"type": "path"
},
"original": {
"path": "./xmonad-contrib",
"type": "path"
}
},
"xmonad_2": {
"inputs": {
"flake-utils": "flake-utils_4",
"git-ignore-nix": "git-ignore-nix_3",
"nixpkgs": "nixpkgs_5",
"unstable": "unstable_2"
},
"locked": {
"lastModified": 1695471545,
"narHash": "sha256-3EK3rWNuPsc4FwkY7S1sPVI4hr9O7/AXI5AqdO0gJ/A=",
"owner": "xmonad", "owner": "xmonad",
"repo": "xmonad", "repo": "xmonad",
"rev": "327c2cf0c14f8eec234ec74d1a657d3e2fd5df11", "rev": "bb33042d408c15d8727011b1ed4aa22b2716d73d",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -357,6 +258,32 @@
"repo": "xmonad", "repo": "xmonad",
"type": "github" "type": "github"
} }
},
"xmonad-contrib": {
"inputs": {
"flake-utils": "flake-utils_3",
"git-ignore-nix": "git-ignore-nix_3",
"nixpkgs": [
"nixpkgs"
],
"xmonad": [
"xmonad"
]
},
"locked": {
"lastModified": 1755152326,
"narHash": "sha256-47gGXt1TxzfQx/6X895t/T8Ozj+7fmQdU1i4cwyxcSg=",
"owner": "IvanMalison",
"repo": "xmonad-contrib",
"rev": "1a8da46855ca83e11cfb31cbbaed980ed7a8dfcc",
"type": "github"
},
"original": {
"owner": "IvanMalison",
"ref": "withMyChanges",
"repo": "xmonad-contrib",
"type": "github"
}
} }
}, },
"root": "root", "root": "root",

View File

@@ -1,16 +1,18 @@
{ {
inputs = { inputs = {
flake-utils.url = github:numtide/flake-utils; flake-utils.url = "github:numtide/flake-utils";
xmonad-contrib = { git-ignore-nix.url = "github:hercules-ci/gitignore.nix";
url = path:./xmonad-contrib; xmonad = {
url = "github:xmonad/xmonad";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
xmonad = { xmonad-contrib = {
url = path:./xmonad; url = "github:IvanMalison/xmonad-contrib/withMyChanges";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
inputs.xmonad.follows = "xmonad";
}; };
}; };
outputs = { self, flake-utils, nixpkgs, xmonad, xmonad-contrib }: outputs = { self, flake-utils, nixpkgs, xmonad, xmonad-contrib, git-ignore-nix }:
let let
overlay = import ./overlay.nix; overlay = import ./overlay.nix;
overlays = [ overlay xmonad.overlay xmonad-contrib.overlay ]; overlays = [ overlay xmonad.overlay xmonad-contrib.overlay ];

View File

@@ -1019,7 +1019,7 @@ addKeys conf@XConfig { modMask = modm } =
-- Non-XMonad -- Non-XMonad
, ((modm, xK_v), spawn "xclip -o | xdotool type --file -") , ((modm, xK_v), spawn "xclip -o | xdotool type --file -")
, ((hyper, xK_v), spawn "rofi_clipit.sh") , ((hyper, xK_v), spawn "rofi -modi 'clipboard:greenclip print' -show clipboard")
, ((hyper, xK_p), spawn "rofi-pass") , ((hyper, xK_p), spawn "rofi-pass")
, ((hyper, xK_h), spawn "rofi_shutter") , ((hyper, xK_h), spawn "rofi_shutter")
, ((hyper, xK_c), spawn "shell_command.sh") , ((hyper, xK_c), spawn "shell_command.sh")

View File

@@ -9,6 +9,7 @@
.tern-port .tern-port
.tutor .tutor
/eln-cache /eln-cache
/elpaca
/transient /transient
/tree-sitter /tree-sitter
README.el README.el

View File

@@ -1,6 +1,6 @@
# -*- mode: org; -*- # -*- mode: org; -*-
[[https://travis-ci.org/IvanMalison/dotfiles][ [[https://github.com/IvanMalison/dotfiles/actions/workflows/gh-pages.yml][
file:https://travis-ci.org/IvanMalison/dotfiles.svg?branch=master]] file:https://github.com/IvanMalison/dotfiles/actions/workflows/gh-pages.yml/badge.svg?branch=master]]
This document is best read at [[http://ivanmalison.github.io/dotfiles/]] or, of This document is best read at [[http://ivanmalison.github.io/dotfiles/]] or, of
course, in emacs, as the internal links that follow are unlikely to work course, in emacs, as the internal links that follow are unlikely to work
@@ -17,18 +17,10 @@ These sections are the ones that have the most potential to be interesting to
others: others:
** How I generate http://ivanmalison.github.io/dotfiles/ ** How I generate http://ivanmalison.github.io/dotfiles/
*** org-export *** org-export
**** travis-ci **** GitHub Actions
[[https://github.com/IvanMalison/dotfiles/tree/master/gen-gh-pages][This directory]] contains a collection of scripts that export this org document [[https://github.com/IvanMalison/dotfiles/tree/master/gen-gh-pages][This directory]] contains a collection of scripts that export this org document
to html. This approach is taken (with only a few modifications) from [[https://gist.github.com/domenic/ec8b0fc8ab45f39403dd][here]]. to html. A [[https://github.com/IvanMalison/dotfiles/blob/master/.github/workflows/gh-pages.yml][GitHub Actions workflow]] runs on every push to master, generating the
**** githook (The old way) HTML and deploying it to GitHub Pages.
NOTE: I've left this here in case other people have an interest in this method,
but I no longer use it.
I wrote a [[https://github.com/IvanMalison/dotfiles/tree/9e56ced1dd70e50e1026aca5af51437e93add026/dotfiles/emacs.d/bin][githook and an installer script]] that automatically update index.html
at the root of the repository by running ~org-html-export-to-html~ on my
README.org (essentially this document) . These should work no matter where they
are placed in a repository. The org-mode file that they target is set [[https://github.com/IvanMalison/dotfiles/blob/16a4f6c3aadef39a45d30c15e8637b40858721ea/dotfiles/emacs.d/bin/util.sh#L4][here]] and
should be relatively easy to change.
*** [[https://github.com/fniessen/org-html-themes][Read The Org]] *** [[https://github.com/fniessen/org-html-themes][Read The Org]]
I use [[https://github.com/fniessen][fniessen]]'s ReadTheOrg theme which can be found at I use [[https://github.com/fniessen][fniessen]]'s ReadTheOrg theme which can be found at
https://github.com/fniessen/org-html-themes. https://github.com/fniessen/org-html-themes.
@@ -171,8 +163,9 @@ startup as possible.
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(defvar imalison:do-benchmark) (defvar imalison:do-benchmark)
(let ((bench-file (concat (file-name-directory user-init-file) "benchmark.el"))) (when user-init-file
(when (file-exists-p bench-file) (load bench-file))) (let ((bench-file (concat (file-name-directory user-init-file) "benchmark.el")))
(when (file-exists-p bench-file) (load bench-file))))
(use-package benchmark-init (use-package benchmark-init
:if imalison:do-benchmark :if imalison:do-benchmark
@@ -238,6 +231,7 @@ Sets environment variables by starting a shell.
** noflet ** noflet
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package noflet (use-package noflet
:after (dash) ;;@HACK: noflet does not properly declare dependencies
:demand t) :demand t)
#+END_SRC #+END_SRC
** Non-Forking Shell Command To String ** Non-Forking Shell Command To String
@@ -323,63 +317,41 @@ I want to control my own font for emacs
* Functions * Functions
** Join Paths ** Join Paths
Works in the same way as os.path.join in python Works in the same way as os.path.join in python
#+BEGIN_SRC emacs-lisp #+NAME: imalison-join-paths
#+BEGIN_SRC emacs-lisp :tangle no
(defun imalison:join-paths (root &rest dirs) (defun imalison:join-paths (root &rest dirs)
(let ((result root)) (let ((result root))
(cl-loop for dir in dirs do (cl-loop for dir in dirs do
(setq result (concat (file-name-as-directory result) dir))) (setq result (concat (file-name-as-directory result) dir)))
result)) result))
#+END_SRC #+END_SRC
#+BEGIN_SRC emacs-lisp :noweb yes
<<imalison-join-paths>>
#+END_SRC
** Variables ** Variables
#+BEGIN_SRC emacs-lisp #+NAME: imalison-projects-directory
#+BEGIN_SRC emacs-lisp :tangle no
(defvar imalison:projects-directory (defvar imalison:projects-directory
(imalison:join-paths (substitute-in-file-name "$HOME") "Projects")) (imalison:join-paths (substitute-in-file-name "$HOME") "Projects"))
#+END_SRC
#+BEGIN_SRC emacs-lisp :noweb yes
<<imalison-projects-directory>>
#+END_SRC
#+BEGIN_SRC emacs-lisp :tangle org-config-bootstrap.el :noweb yes
<<imalison-join-paths>>
<<imalison-projects-directory>>
;; For org-config-bootstrap: frame-mode not needed in server/container context
(defvar imalison:use-frame-mode nil)
#+END_SRC
#+BEGIN_SRC emacs-lisp
(defvar imalison:gpg-key) (defvar imalison:gpg-key)
#+END_SRC #+END_SRC
** Required Packages
The packages in this section provide no functionality on their own,
but provide support for writing custom elisp.
*** s
#+BEGIN_SRC emacs-lisp
(use-package s :demand t)
#+END_SRC
*** dash
#+BEGIN_SRC emacs-lisp
(use-package dash
:demand t
:config
(progn
(dash-enable-font-lock)))
#+END_SRC
*** gh
#+BEGIN_SRC emacs-lisp
(use-package gh
:defer t
:straight (gh :type git :host github :repo "IvanMalison/gh.el"))
#+END_SRC
*** shut-up
#+BEGIN_SRC emacs-lisp
(use-package shut-up
:config
(defun imalison:shut-up-around (function &rest args)
(shut-up (apply function args))))
#+END_SRC
*** parse-csv
#+BEGIN_SRC emacs-lisp
(use-package parse-csv
:demand t)
#+END_SRC
*** emit
#+BEGIN_SRC emacs-lisp
(use-package emit
:straight (emit :type git :host github :repo "colonelpanic8/emit"))
#+END_SRC
*** request
#+BEGIN_SRC emacs-lisp
(use-package request
:defer t)
#+END_SRC
** Named Build ** Named Build
<<namedbuild>> <<namedbuild>>
imalison:named-build provides a way to invoke a macro in such a way imalison:named-build provides a way to invoke a macro in such a way
@@ -754,8 +726,14 @@ A macro for composing functions together to build an interactive command to copy
#+END_SRC #+END_SRC
*** Copy portions of the buffer file name *** Copy portions of the buffer file name
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(defun imalison:buffer-file-name-or-directory ()
"Return `buffer-file-name' if available, otherwise `default-directory'.
This allows copy functions to work with buffers like magit that
aren't visiting a file but are associated with a directory."
(or buffer-file-name default-directory))
(defmacro imalison:copy-buffer-file-path-builder (&rest args) (defmacro imalison:copy-buffer-file-path-builder (&rest args)
`(imalison:compose-copy-builder ,@args buffer-file-name)) `(imalison:compose-copy-builder ,@args imalison:buffer-file-name-or-directory))
(imalison:copy-buffer-file-path-builder imalison:copy-buffer-file-path-full) (imalison:copy-buffer-file-path-builder imalison:copy-buffer-file-path-full)
(imalison:copy-buffer-file-path-builder imalison:copy-buffer-file-name (imalison:copy-buffer-file-path-builder imalison:copy-buffer-file-name
@@ -856,6 +834,7 @@ details.
(directory-files filepath)))) (directory-files filepath))))
(use-package eshell (use-package eshell
:ensure nil
:commands (eshell-parse-colon-path imalison:get-executables-on-path) :commands (eshell-parse-colon-path imalison:get-executables-on-path)
:config :config
(defun imalison:get-executables-on-path () (defun imalison:get-executables-on-path ()
@@ -1138,8 +1117,15 @@ I keep it around just in case I need it.
*** frame-mode *** frame-mode
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(defvar imalison:use-frame-mode (defvar imalison:use-frame-mode
(or (s-contains? "xmonad" (shell-command-to-string "wmctrl -m")) (let ((xdg-current (downcase (or (getenv "XDG_CURRENT_DESKTOP") "")))
(s-contains? "Hyprland" (shell-command-to-string "wmctrl -m")))) (xdg-session (downcase (or (getenv "XDG_SESSION_DESKTOP") "")))
(desktop-session (downcase (or (getenv "DESKTOP_SESSION") ""))))
(or (getenv "HYPRLAND_INSTANCE_SIGNATURE")
(s-contains? "hyprland" xdg-current)
(s-contains? "hyprland" xdg-session)
(s-contains? "hyprland" desktop-session)
(and (executable-find "wmctrl")
(s-contains? "xmonad" (shell-command-to-string "wmctrl -m"))))))
(use-package frame-mode (use-package frame-mode
:if imalison:use-frame-mode :if imalison:use-frame-mode
@@ -1150,10 +1136,6 @@ I keep it around just in case I need it.
(frame-mode +1) (frame-mode +1)
(frame-keys-mode +1))) (frame-keys-mode +1)))
#+END_SRC #+END_SRC
*** Handle xrefs annoying dedicated window garbage
#+BEGIN_SRC emacs-lisp
(use-package xref)
#+END_SRC
** Fill Setup ** Fill Setup
Get rid of nags about requiring setences to end with two spaces. Get rid of nags about requiring setences to end with two spaces.
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
@@ -1234,6 +1216,7 @@ This makes ~forward-word~ and ~backward-word~ understand snake and camel case.
proced is an top like utility that runs inside of emacs. The following sets auto updating automatically and makes the update interval faster. proced is an top like utility that runs inside of emacs. The following sets auto updating automatically and makes the update interval faster.
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package proced (use-package proced
:ensure nil
:defer t :defer t
:config :config
(progn (progn
@@ -1377,6 +1360,7 @@ Paradox is a package.el extension. I have no use for it now that I use straight.
** server ** server
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package server (use-package server
:ensure nil
:demand t :demand t
:config :config
(progn (progn
@@ -1448,6 +1432,7 @@ The file server file for this emacs instance no longer exists.")
** winner ** winner
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package winner (use-package winner
:ensure nil
:commands (winner-undo winner-redo) :commands (winner-undo winner-redo)
:bind ("C-c q" . imalison:winner-hydra/body) :bind ("C-c q" . imalison:winner-hydra/body)
:config :config
@@ -1458,15 +1443,6 @@ The file server file for this emacs instance no longer exists.")
("n" winner-redo "forward" :exit t)) ("n" winner-redo "forward" :exit t))
(winner-mode 1))) (winner-mode 1)))
#+END_SRC #+END_SRC
** eyebrowse
I don't have any use for this now that I use frames mode, but its an interesting idea.
#+BEGIN_SRC emacs-lisp
(use-package eyebrowse
:disabled t
:defer 1
:config
(progn (eyebrowse-mode +1)))
#+END_SRC
** stream ** stream
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package stream :defer t) (use-package stream :defer t)
@@ -1519,9 +1495,9 @@ https://github.com/alpaker/Fill-Column-Indicator/issues/21 for more details
#+begin_src emacs-lisp #+begin_src emacs-lisp
(use-package indent-bars (use-package indent-bars
:disabled t :disabled t
:straight (indent-bars :type git :host github :repo "jdtsmith/indent-bars") :ensure (indent-bars :type git :host github :repo "jdtsmith/indent-bars")
:config :config
(require 'indent-bars-ts) ; not needed with straight (require 'indent-bars-ts)
:custom :custom
(indent-bars-treesit-support t) (indent-bars-treesit-support t)
(indent-bars-treesit-ignore-blank-lines-types '("module")) (indent-bars-treesit-ignore-blank-lines-types '("module"))
@@ -1541,6 +1517,7 @@ fixes that, but for now, it needs to be run manually, since I haven't figured
out how to detect that a buffer is a man mode buffer. out how to detect that a buffer is a man mode buffer.
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package man (use-package man
:ensure nil
:config :config
(progn (progn
(defun imalison:fontify-man-page-buffer () (defun imalison:fontify-man-page-buffer ()
@@ -1611,10 +1588,6 @@ out how to detect that a buffer is a man mode buffer.
(progn (progn
(global-set-key (kbd "<escape>") 'god-local-mode))) (global-set-key (kbd "<escape>") 'god-local-mode)))
#+END_SRC #+END_SRC
** bind-key
#+BEGIN_SRC emacs-lisp
(use-package bind-key)
#+END_SRC
** which-key ** which-key
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package which-key (use-package which-key
@@ -1752,6 +1725,7 @@ bind-key and global-set-key forms.
** xref ** xref
#+begin_src emacs-lisp #+begin_src emacs-lisp
(use-package xref (use-package xref
:ensure nil
:bind ("M-," . xref-go-back)) :bind ("M-," . xref-go-back))
#+end_src #+end_src
* Navigation * Navigation
@@ -1766,6 +1740,7 @@ bind-key and global-set-key forms.
#+END_SRC #+END_SRC
** projectile ** projectile
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package projectile (use-package projectile
:demand t :demand t
:bind (:map projectile-mode-map :bind (:map projectile-mode-map
@@ -1779,7 +1754,7 @@ bind-key and global-set-key forms.
(projectile-git-submodule-command nil) (projectile-git-submodule-command nil)
(project-vc-merge-submodules nil) (project-vc-merge-submodules nil)
(projectile-current-project-on-switch 'keep)) (projectile-current-project-on-switch 'keep))
:preface :config
(progn (progn
(defmacro imalison:projectile-do-in-project (project-dir &rest forms) (defmacro imalison:projectile-do-in-project (project-dir &rest forms)
`(imalison:with-default-directory ,project-dir `(imalison:with-default-directory ,project-dir
@@ -1882,12 +1857,6 @@ bind-key and global-set-key forms.
:config (setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l)) :config (setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l))
:bind ("C-c w" . imalison:ace-window)) :bind ("C-c w" . imalison:ace-window))
#+END_SRC #+END_SRC
** neotree
Neotree is useless with frame mode for now, so I've disabled it.
#+BEGIN_SRC emacs-lisp
(use-package neotree
:disabled t)
#+END_SRC
** flimenu ** flimenu
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package flimenu (use-package flimenu
@@ -1907,39 +1876,29 @@ Neotree is useless with frame mode for now, so I've disabled it.
#+begin_src emacs-lisp #+begin_src emacs-lisp
(use-package vertico (use-package vertico
:demand t :demand t
:bind (:map vertico-map
("TAB" . embark-act))
:config
(vertico-mode))
(use-package vertico-directory :ensure nil
:after (vertico)
:bind (:map vertico-map
("RET" . vertico-directory-enter)
("DEL" . vertico-directory-delete-char)
("M-DEL" . vertico-directory-delete-word))
:config)
(use-package vertico-grid :ensure nil :after (vertico))
(use-package vertico-buffer :ensure nil :after (vertico))
(use-package vertico-flat :ensure nil :after (vertico))
(use-package vertico-multiform :ensure nil :after (vertico)
:config :config
(progn (progn
(defmacro imalison:use-vertico-extension (extension-name &rest forms) (vertico-multiform-mode +1)
(let ((extension-symbol (intern (concat "vertico-" (symbol-name extension-name))))) (setq vertico-multiform-commands
`(use-package ,extension-symbol '((consult-imenu grid)
:after vertico (consult-ripgrep buffer)))))
:straight (,extension-symbol
:repo "emacs-straight/vertico"
:host github
:files ,(list (concat "extensions/" (symbol-name extension-symbol) ".el")))
,@forms)))
(put 'imalison:use-vertico-extension 'lisp-indent-function 'defun)
(imalison:use-vertico-extension directory
:bind (:map vertico-map
("RET" . vertico-directory-enter)
("DEL" . vertico-directory-delete-char)
("M-DEL" . vertico-directory-delete-word)
("TAB" . embark-act)))
(imalison:use-vertico-extension grid)
(imalison:use-vertico-extension buffer)
(imalison:use-vertico-extension flat)
(imalison:use-vertico-extension multiform
:config
(progn
(vertico-multiform-mode +1)
(setq vertico-multiform-commands
'((consult-imenu grid)
(consult-ripgrep buffer)))))
(vertico-mode +1)))
#+end_src #+end_src
** orderless ** orderless
#+begin_src emacs-lisp #+begin_src emacs-lisp
@@ -2059,22 +2018,6 @@ Neotree is useless with frame mode for now, so I've disabled it.
:config :config
(company-flx-mode +1)) (company-flx-mode +1))
#+END_SRC #+END_SRC
** auto-complete
I don't use auto-complete at all, so I have set up a hook to automatically disable it whenever it is enabled to avoid creating conflicting popups when company is activated.
#+BEGIN_SRC emacs-lisp
(use-package auto-complete
:defer t
:preface
(progn
(defun imalison:auto-complete-hook ()
(debug)
(warn "auto-complete-mode was activated, but is being automatically disabled.")
(let ((auto-complete-mode-hook nil))
(auto-complete-mode -1))))
:config
(progn
(add-hook 'auto-complete-mode-hook 'imalison:auto-complete-hook)))
#+END_SRC
* Text Manipulation * Text Manipulation
** smartparens ** smartparens
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
@@ -2222,6 +2165,7 @@ I don't use auto-complete at all, so I have set up a hook to automatically disab
** align ** align
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package align (use-package align
:ensure nil
:bind ("C-c C-a" . imalison:align-regexp-hydra/body) :bind ("C-c C-a" . imalison:align-regexp-hydra/body)
:config :config
(progn (progn
@@ -2269,16 +2213,10 @@ I don't use auto-complete at all, so I have set up a hook to automatically disab
(global-flycheck-mode)) (global-flycheck-mode))
:diminish flycheck-mode) :diminish flycheck-mode)
#+END_SRC #+END_SRC
* straight
#+BEGIN_SRC emacs-lisp
(use-package straight
:config
(setq straight-vc-git-auto-fast-forward t))
#+END_SRC
* auth-source * auth-source
#+begin_src emacs-lisp #+begin_src emacs-lisp
(use-package auth-source (use-package auth-source
:straight nil :ensure nil
:config :config
(progn (progn
(setq auth-sources '("~/.authinfo.gpg")))) (setq auth-sources '("~/.authinfo.gpg"))))
@@ -2292,6 +2230,7 @@ I don't use auto-complete at all, so I have set up a hook to automatically disab
(defvar imalison:use-lsp-python t) (defvar imalison:use-lsp-python t)
(use-package python (use-package python
:ensure nil
:commands python-mode :commands python-mode
:mode ("\\.py\\'" . python-mode) :mode ("\\.py\\'" . python-mode)
:preface :preface
@@ -2327,9 +2266,11 @@ I don't use auto-complete at all, so I have set up a hook to automatically disab
*** ruby *** ruby
#+begin_src emacs-lisp #+begin_src emacs-lisp
(use-package ruby-mode (use-package ruby-mode
:ensure nil
:config :config
(setf (alist-get 'ruby-ts-mode apheleia-mode-alist) (with-eval-after-load 'apheleia
'(rubocop))) (setf (alist-get 'ruby-ts-mode apheleia-mode-alist)
'(rubocop))))
#+end_src #+end_src
*** go *** go
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
@@ -2480,6 +2421,7 @@ it's supposed to do, but instead uses its own collection of functions to control
where the definition is popped up. This fixes that. where the definition is popped up. This fixes that.
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package find-func (use-package find-func
:ensure nil
:preface :preface
(progn (progn
(defun imalison:find-function-display-buffer (function) (defun imalison:find-function-display-buffer (function)
@@ -2499,14 +2441,6 @@ Macrostep is an indespensible tool for writing emacs lisp macros. It lets you se
:bind (:map lisp-mode-shared-map :bind (:map lisp-mode-shared-map
("C-c e" . macrostep-expand))) ("C-c e" . macrostep-expand)))
#+END_SRC #+END_SRC
**** emr
#+BEGIN_SRC emacs-lisp
(use-package emr
:bind ("M-RET" . emr-show-refactor-menu)
:config
(progn
(add-hook 'prog-mode-hook 'emr-initialize)))
#+END_SRC
**** Editing configuration **** Editing configuration
Reduce indentation for some functions Reduce indentation for some functions
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
@@ -2520,6 +2454,7 @@ Reduce indentation for some functions
**** edebug **** edebug
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package edebug (use-package edebug
:ensure nil
:defer t :defer t
:config :config
(progn (setq edebug-trace t))) (progn (setq edebug-trace t)))
@@ -2600,7 +2535,7 @@ eval-last-sexp.
(check-parens))) (check-parens)))
(defun imalison:emacs-lisp-hook () (defun imalison:emacs-lisp-hook ()
(elisp-slime-nav-mode t) (when (fboundp 'elisp-slime-nav-mode) (elisp-slime-nav-mode t))
(add-hook 'write-file-functions 'imalison:maybe-check-parens nil t)) (add-hook 'write-file-functions 'imalison:maybe-check-parens nil t))
(add-hook 'emacs-lisp-mode-hook 'imalison:emacs-lisp-hook) (add-hook 'emacs-lisp-mode-hook 'imalison:emacs-lisp-hook)
@@ -2642,7 +2577,7 @@ eval-last-sexp.
(setq nix-indent-function 'nix-indent-line))) (setq nix-indent-function 'nix-indent-line)))
(use-package lsp-nix (use-package lsp-nix
:straight nil :ensure nil
:after (lsp-mode) :after (lsp-mode)
:config :config
(progn (progn
@@ -2716,6 +2651,8 @@ The following is taken from [[https://github.com/syl20bnr/spacemacs/blob/a650877
#+END_SRC #+END_SRC
**** clj-refactor **** clj-refactor
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
;;@WORKAROUND clj-refactor dependency inflections Version metadata
(use-package inflections :ensure (:depth nil :version elpaca-latest-tag :version-regexp "[[:digit:]]\\.[[:digit:]]"))
(use-package clj-refactor (use-package clj-refactor
:commands clj-refactor-mode) :commands clj-refactor-mode)
#+END_SRC #+END_SRC
@@ -2881,10 +2818,9 @@ The following is taken from [[https://github.com/syl20bnr/spacemacs/blob/a650877
(use-package purty (use-package purty
:commands purty-on-save-mode :commands purty-on-save-mode
:straight (purty :repo "joneshf/purty" :ensure (purty :repo "joneshf/purty"
:type git :host gitlab
:host gitlab :files ("purty.el")))
:files ("purty.el")))
(use-package psc-ide (use-package psc-ide
:after purescript-mode :after purescript-mode
@@ -2922,7 +2858,7 @@ The following is taken from [[https://github.com/syl20bnr/spacemacs/blob/a650877
#+END_SRC #+END_SRC
*** C/C++ *** C/C++
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package cc-mode) (use-package cc-mode :ensure nil :defer t)
#+END_SRC #+END_SRC
*** C-- *** C--
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
@@ -3009,13 +2945,19 @@ The following is taken from [[https://github.com/syl20bnr/spacemacs/blob/a650877
*** org *** org
My org-mode configuration now lives in its own file org-config.org. My org-mode configuration now lives in its own file org-config.org.
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(org-babel-load-file (let* ((org-config (expand-file-name "org-config.org" user-emacs-directory))
(concat (file-name-directory load-file-name) "org-config.org")) (org-config-el (expand-file-name "org-config.el" user-emacs-directory)))
(when (file-newer-than-file-p org-config org-config-el)
;; Tangle all outputs so org-config-bind.el/org-config-config.el are fresh.
(org-babel-tangle-file org-config)
(when (file-exists-p org-config-el)
(set-file-times org-config-el)))
(load-file org-config-el))
#+END_SRC #+END_SRC
*** TeX *** TeX
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package tex (use-package tex
:straight (auctex :host github :repo "raxod502/auctex" :ensure (auctex :host github :repo "raxod502/auctex"
:branch "fork/1" :branch "fork/1"
:files (:defaults (:exclude "doc/*.texi"))) :files (:defaults (:exclude "doc/*.texi")))
:commands TeX-mode :commands TeX-mode
@@ -3040,7 +2982,7 @@ My org-mode configuration now lives in its own file org-config.org.
**** latex **** latex
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package latex (use-package latex
:straight auctex :ensure nil
:after tex :after tex
:config :config
(progn (progn
@@ -3189,6 +3131,7 @@ My org-mode configuration now lives in its own file org-config.org.
** vc ** vc
#+begin_src emacs-lisp #+begin_src emacs-lisp
(use-package vc (use-package vc
:ensure nil
:config :config
(progn (progn
(defun vc-find-revision-of-file (revision) (defun vc-find-revision-of-file (revision)
@@ -3335,6 +3278,7 @@ emr (emacs refactor) provides support for refactoring in many programming langua
** semantic ** semantic
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package semantic (use-package semantic
:ensure nil
:commands semantic-mode :commands semantic-mode
:disabled t :disabled t
:preface :preface
@@ -3397,6 +3341,7 @@ in term-mode. This makes term-mode 1000% more useful
(especially having M-x and C-y available). (especially having M-x and C-y available).
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package term (use-package term
:ensure nil
:demand t :demand t
:preface :preface
(progn (progn
@@ -3474,8 +3419,8 @@ in term-mode. This makes term-mode 1000% more useful
(progn (progn
(use-package term-manager-eat (use-package term-manager-eat
:demand t :demand t
:straight :ensure
(term-manager-eat :type git :files ("term-manager-eat.el") (term-manager-eat :files ("term-manager-eat.el")
:host github :repo "colonelpanic8/term-manager")) :host github :repo "colonelpanic8/term-manager"))
(setq term-projectile-term-manager (term-projectile :build-term 'term-manager-eat-build-term)) (setq term-projectile-term-manager (term-projectile :build-term 'term-manager-eat-build-term))
(emit-prefix-selector imalison:term (emit-prefix-selector imalison:term
@@ -3572,15 +3517,6 @@ crux-reopen-as-root-mode makes it so that any file owned by root will automatica
(setq gptel-model "gpt-4") (setq gptel-model "gpt-4")
)) ))
#+end_src #+end_src
** claude-code-ide
#+begin_src emacs-lisp
(use-package claude-code-ide
:straight (:type git :host github :repo "manzaltu/claude-code-ide.el")
:bind ("C-c C-'" . claude-code-ide-menu)
:config
(claude-code-ide-emacs-tools-setup)
(setq claude-code-ide-terminal-backend 'eat))
#+end_src
* Cooperation * Cooperation
** togetherly ** togetherly
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
@@ -3618,23 +3554,17 @@ crux-reopen-as-root-mode makes it so that any file owned by root will automatica
(define-key isearch-mode-map [remap isearch-query-replace-regexp] (define-key isearch-mode-map [remap isearch-query-replace-regexp]
#'anzu-isearch-query-replace-regexp))) #'anzu-isearch-query-replace-regexp)))
#+END_SRC #+END_SRC
** shell-history
I think that shell-history is causing projectile to be very slow so I have disabled it.
#+BEGIN_SRC emacs-lisp
(use-package shell-history
:demand t
:disabled t)
#+END_SRC
** iedit ** iedit
I don't use iedit directly, but it is used by [[*emr][emr]] and I need to disable ~iedit-toggle-key-default~ or else a buffer pops up complaing that the key has been bound to something else I don't use iedit directly, but it is used by [[*emr][emr]] and I need to disable ~iedit-toggle-key-default~ or else a buffer pops up complaing that the key has been bound to something else
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package iedit ;;@WORKAROUND iedit has oddball version scheme. Report upstream bug.
(use-package iedit :ensure (:depth nil :version (lambda (_) "0.99"))
:defer t) :defer t)
#+END_SRC #+END_SRC
** tramp ** tramp
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package tramp (use-package tramp
:straight nil :ensure nil
:commands tramp :commands tramp
:config :config
(setq tramp-default-method "scp")) (setq tramp-default-method "scp"))
@@ -3642,6 +3572,8 @@ I don't use iedit directly, but it is used by [[*emr][emr]] and I need to disabl
** narrow-indirect ** narrow-indirect
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package narrow-indirect (use-package narrow-indirect
:disabled t ;;@FIX where is it hosted? locally? add :ensure nil + use-package :load-path keyword
:ensure nil
:init :init
(progn (progn
(define-key ctl-x-4-map "nd" 'ni-narrow-to-defun-indirect-other-window) (define-key ctl-x-4-map "nd" 'ni-narrow-to-defun-indirect-other-window)
@@ -3697,6 +3629,7 @@ I had to disable this mode because something that it does messes with coding set
** recentf ** recentf
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package recentf (use-package recentf
:ensure nil
:demand t :demand t
:config :config
(progn (progn
@@ -3735,7 +3668,7 @@ I have currently disabled key-chord because it may cause typing lag.
** calc-mode ** calc-mode
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package calc-mode (use-package calc-mode
:straight nil :ensure nil
:commands calc :commands calc
:config :config
(progn (progn
@@ -3792,6 +3725,7 @@ Not really sure what this is
** epg ** epg
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package epg (use-package epg
:ensure nil
:after shut-up :after shut-up
:config :config
(shut-up (shut-up
@@ -3804,124 +3738,6 @@ Not really sure what this is
:config :config
(pinentry-start)) (pinentry-start))
#+END_SRC #+END_SRC
** twittering-mode
#+BEGIN_SRC emacs-lisp
(use-package twittering-mode
:commands twittering-mode)
#+END_SRC
** matrix-client
#+BEGIN_SRC emacs-lisp
(use-package matrix-client
:disabled t ;; fails to load eieio on startup
)
#+END_SRC
** mu4e
#+BEGIN_SRC emacs-lisp
;; (eval-when-compile
;; (require 's)
;; (defvar mu4e-elisp-directory
;; (s-trim (shell-command-to-string "mu4e_directory"))))
(use-package mu4e
:disabled t
:load-path mu4e-elisp-directory
:straight nil
:commands (mu4e mu4e-view-message-with-msgid mu4e-update-index email)
:bind ("C-c 0" . email)
:config
(progn
(defun email (&optional arg)
(interactive "P")
(if (string-equal (persp-name persp-curr) "email")
(progn (delete-other-windows) (mu4e))
(progn
(persp-switch "email")
(when (or (not (mu4e-running-p)) arg)
(delete-other-windows) (mu4e)))))
;; enable inline images
(setq mu4e-view-show-images t)
;; show images
(setq mu4e-show-images t)
;; Try to display html as text
(setq mu4e-view-prefer-html nil)
(setq mu4e-html2text-command "html2text -width 80 -nobs -utf8")
;; use imagemagick, if available
(when (fboundp 'imagemagick-register-types)
(imagemagick-register-types))
(setq mail-user-agent 'mu4e-user-agent)
(require 'org-mu4e)
(setq mu4e-compose-complete-only-after nil)
(setq mu4e-maildir "~/Mail")
(setq mu4e-drafts-folder "/[Gmail].Drafts")
(setq mu4e-sent-folder "/[Gmail].Sent Mail")
(setq mu4e-trash-folder "/[Gmail].Trash")
(setq mu4e-sent-messages-behavior 'delete)
(setq mu4e-headers-skip-duplicates t)
(setq mu4e-update-interval (* 60 20))
(setq message-kill-buffer-on-exit t)
(setq mail-user-agent 'mu4e-user-agent) ;; make mu4e the default mail client
;; don't save message to Sent Messages, Gmail/IMAP takes care of this
(setq mu4e-sent-messages-behavior 'delete)
;; allow for updating mail using 'U' in the main view:
(setq mu4e-get-mail-command "timeout 60 offlineimap")
(add-hook 'mu4e-compose-mode-hook
(defun my-do-compose-stuff () (flyspell-mode)))
(add-to-list 'mu4e-headers-actions '("view in browser" . mu4e-action-view-in-browser))
(add-to-list 'mu4e-view-actions '("view in browser" . mu4e-action-view-in-browser))
(defun mu4e-view (msg headersbuf)
"Display the message MSG in a new buffer, and keep in sync with HDRSBUF.
'In sync' here means that moving to the next/previous message in
the the message view affects HDRSBUF, as does marking etc.
As a side-effect, a message that is being viewed loses its 'unread'
marking if it still had that."
(let* ((embedded ;; is it as an embedded msg (ie. message/rfc822 att)?
(when (gethash (mu4e-message-field msg :path)
mu4e~path-parent-docid-map) t))
(buf
(if embedded
(mu4e~view-embedded-winbuf)
(get-buffer-create mu4e~view-buffer-name))))
;; note: mu4e~view-mark-as-read will pseudo-recursively call mu4e-view again
;; by triggering mu4e~view again as it marks the message as read
(with-current-buffer buf
(switch-to-buffer buf)
(setq mu4e~view-msg msg)
;;(or embedded (not (mu4e~view-mark-as-read msg)))
(when (or (mu4e~view-mark-as-read msg) t)
(let ((inhibit-read-only t))
(erase-buffer)
(mu4e~delete-all-overlays)
(insert (mu4e-view-message-text msg))
(goto-char (point-min))
(mu4e~fontify-cited)
(mu4e~fontify-signature)
(mu4e~view-make-urls-clickable)
(mu4e~view-show-images-maybe msg)
(setq
mu4e~view-buffer buf
mu4e~view-headers-buffer headersbuf)
(when embedded (local-set-key "q" 'kill-buffer-and-window))
(mu4e-view-mode))))))
(require 'smtpmail)
;; alternatively, for emacs-24 you can use:
(setq message-send-mail-function 'smtpmail-send-it
smtpmail-stream-type 'starttls
smtpmail-default-smtp-server "smtp.gmail.com"
smtpmail-smtp-server "smtp.gmail.com"
smtpmail-smtp-service 587)))
#+END_SRC
** gmail-message-mode ** gmail-message-mode
This is useful with server mode when editing gmail messages. I think that it is not currently working, or it may need to be manually enabled. This is useful with server mode when editing gmail messages. I think that it is not currently working, or it may need to be manually enabled.
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
@@ -3966,7 +3782,7 @@ This is useful with server mode when editing gmail messages. I think that it is
(progn (progn
(when (eq system-type 'darwin) (when (eq system-type 'darwin)
(setq sauron-modules '(sauron-erc sauron-org sauron-notifications (setq sauron-modules '(sauron-erc sauron-org sauron-notifications
sauron-twittering sauron-jabber sauron-identica)) sauron-jabber sauron-identica))
(defun sauron-dbus-start () (defun sauron-dbus-start ()
nil) nil)
(makunbound 'dbus-path-emacs))) (makunbound 'dbus-path-emacs)))
@@ -3985,14 +3801,11 @@ This is useful with server mode when editing gmail messages. I think that it is
(defun sauron:erc-notify (origin priority message &optional properties) (defun sauron:erc-notify (origin priority message &optional properties)
(let ((event (plist-get properties :event))) (let ((event (plist-get properties :event)))
(funcall notify-function "IRC" message))) (funcall notify-function "IRC" message)))
(defun sauron:mu4e-notify (origin priority message &optional properties)
nil)
(defun sauron:dbus-notify (origin priority message &optional properties) (defun sauron:dbus-notify (origin priority message &optional properties)
(funcall notify-function "GMail" message)) (funcall notify-function "GMail" message))
(defun sauron:dispatch-notify (origin priority message &optional properties) (defun sauron:dispatch-notify (origin priority message &optional properties)
(let ((handler (cond ((string= origin "erc") 'sauron:erc-notify) (let ((handler (cond ((string= origin "erc") 'sauron:erc-notify)
((string= origin "jabber") 'sauron:jabber-notify) ((string= origin "jabber") 'sauron:jabber-notify)
((string= origin "mu4e") 'sauron:mu4e-notify)
((string= origin "dbus") 'sauron:dbus-notify) ((string= origin "dbus") 'sauron:dbus-notify)
(t (lambda (&rest r) nil))))) (t (lambda (&rest r) nil)))))
(funcall handler origin priority message properties))) (funcall handler origin priority message properties)))
@@ -4004,6 +3817,7 @@ This is useful with server mode when editing gmail messages. I think that it is
** screenshot ** screenshot
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package screenshot (use-package screenshot
:disabled t ;;@FIX :ensure (:host github :repo "tecosaur/screenshot")?
:commands screenshot) :commands screenshot)
#+END_SRC #+END_SRC
** libmpdee ** libmpdee
@@ -4014,6 +3828,7 @@ This is useful with server mode when editing gmail messages. I think that it is
** flyspell ** flyspell
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package flyspell (use-package flyspell
:ensure nil
:disabled t ; kind of annoying :disabled t ; kind of annoying
:preface (setq flyspell-issue-welcome-flag nil) :preface (setq flyspell-issue-welcome-flag nil)
:config :config
@@ -4064,55 +3879,6 @@ This is useful with server mode when editing gmail messages. I think that it is
("gtl" . "\\.cql\\'"))))) ("gtl" . "\\.cql\\'")))))
#+END_SRC #+END_SRC
** perspective
I've disabled perspective because I just don't use it much.
#+BEGIN_SRC emacs-lisp
(use-package perspective
:disabled t
:demand t
:config
(progn
(persp-mode)
(defun persp-get-perspectives-for-buffer (buffer)
"Get the names of all of the perspectives of which `buffer` is a member."
(cl-loop for perspective being the hash-value of perspectives-hash
if (member buffer (persp-buffers perspective))
collect (persp-name perspective)))
(defun persp-pick-perspective-by-buffer (buffer)
"Select a buffer and go to the perspective to which that buffer
belongs. If the buffer belongs to more than one perspective
completion will be used to pick the perspective to switch to.
Switch the focus to the window in which said buffer is displayed
if such a window exists. Otherwise display the buffer in whatever
window is active in the perspective."
(interactive (list (funcall persp-interactive-completion-function
"Buffer: " (mapcar 'buffer-name (buffer-list)))))
(let* ((perspectives (persp-get-perspectives-for-buffer (get-buffer buffer)))
(perspective (if (> (length perspectives) 1)
(funcall persp-interactive-completion-function
(format "Select the perspective in which you would like to visit %s."
buffer)
perspectives)
(car perspectives))))
(if (string= (persp-name persp-curr) perspective)
;; This allows the opening of a single buffer in more than one window
;; in a single perspective.
(switch-to-buffer buffer)
(progn
(persp-switch perspective)
(if (get-buffer-window buffer)
(set-frame-selected-window nil (get-buffer-window buffer))
(switch-to-buffer buffer))))))
(defun persp-mode-switch-buffers (arg)
(interactive "P")
(if arg (call-interactively 'ido-switch-buffer)
(call-interactively 'persp-pick-perspective-by-buffer)))
(define-key persp-mode-map (kbd "C-x b") 'persp-mode-switch-buffers))
:bind ("C-c 9" . persp-switch))
#+END_SRC
** android-mode ** android-mode
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package android-mode (use-package android-mode
@@ -4136,17 +3902,20 @@ This also adds syntax highlighting for gradle
** jsx-mode ** jsx-mode
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package jsx-mode (use-package jsx-mode
:disabled t ;;@FIX Add :ensure with package recipe. Could not find "jsx-mode" hosted anywhere
:defer t) :defer t)
#+END_SRC #+END_SRC
** css ** css
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package css-mode (use-package css-mode
:ensure nil
:mode (("\\.css\\'" . css-mode) :mode (("\\.css\\'" . css-mode)
("\\.rasi\\'" . css-mode))) ("\\.rasi\\'" . css-mode)))
#+END_SRC #+END_SRC
** sgml-mode ** sgml-mode
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package sgml-mode (use-package sgml-mode
:ensure nil
;; :bind ("C-c b" . web-beautify-html) TODO: mode specific, change binding ;; :bind ("C-c b" . web-beautify-html) TODO: mode specific, change binding
:commands sgml-mode) :commands sgml-mode)
#+END_SRC #+END_SRC
@@ -4180,13 +3949,13 @@ Ensure all themes that I use are installed:
(defvar-setq packages-appearance (defvar-setq packages-appearance
'(monokai-theme zenburn-theme base16-theme molokai-theme moe-theme '(monokai-theme zenburn-theme base16-theme molokai-theme moe-theme
tango-2-theme gotham-theme sublime-themes rainbow-delimiters tango-2-theme gotham-theme sublime-themes
waher-theme ample-theme material-theme zerodark-theme waher-theme ample-theme material-theme zerodark-theme
color-theme-modern leuven-theme spacemacs-theme gruvbox-theme color-theme-modern leuven-theme spacemacs-theme gruvbox-theme
forest-blue-theme flatland-theme afternoon-theme forest-blue-theme flatland-theme afternoon-theme
cyberpunk-theme dracula-theme)) cyberpunk-theme dracula-theme))
(mapcar 'straight-use-package packages-appearance) (mapcar #'elpaca-try packages-appearance)
(use-package doom-themes (use-package doom-themes
:defer t) :defer t)
@@ -4198,9 +3967,15 @@ Ensure all themes that I use are installed:
(use-package all-the-icons (use-package all-the-icons
:demand t) :demand t)
#+END_SRC #+END_SRC
** nerd-icons
#+BEGIN_SRC emacs-lisp
(use-package nerd-icons
:demand t)
#+END_SRC
** doom-modeline ** doom-modeline
#+begin_src emacs-lisp #+begin_src emacs-lisp
(use-package doom-modeline (use-package doom-modeline
:after nerd-icons
:commands doom-modeline-mode :commands doom-modeline-mode
:custom :custom
(doom-modeline-height 40)) (doom-modeline-height 40))
@@ -4347,8 +4122,7 @@ load-theme hook (See the heading below).
(setq imalison:default-font-size-pt (face-attribute 'default :height)) (setq imalison:default-font-size-pt (face-attribute 'default :height))
(setq imalison:appearance-setup-done t))) (setq imalison:appearance-setup-done t)))
(add-hook 'after-make-frame-functions 'imalison:appearance-setup-hook) (add-hook 'elpaca-after-init-hook 'imalison:appearance-setup-hook)
(add-hook 'after-init-hook 'imalison:appearance-setup-hook)
#+END_SRC #+END_SRC
* Post Init Custom * Post Init Custom
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp

View File

@@ -0,0 +1,39 @@
;; Elpaca Installer -*- lexical-binding: t; -*-
(defvar elpaca-installer-version 0.11)
(defvar elpaca-directory (expand-file-name "elpaca/" user-emacs-directory))
(defvar elpaca-builds-directory (expand-file-name "builds/" elpaca-directory))
(defvar elpaca-repos-directory (expand-file-name "repos/" elpaca-directory))
(defvar elpaca-order '(elpaca :repo "https://github.com/progfolio/elpaca.git"
:ref nil :depth 1 :inherit ignore
:files (:defaults "elpaca-test.el" (:exclude "extensions"))
:build (:not elpaca--activate-package)))
(let* ((repo (expand-file-name "elpaca/" elpaca-repos-directory))
(build (expand-file-name "elpaca/" elpaca-builds-directory))
(order (cdr elpaca-order))
(default-directory repo))
(add-to-list 'load-path (if (file-exists-p build) build repo))
(unless (file-exists-p repo)
(make-directory repo t)
(when (<= emacs-major-version 28) (require 'subr-x))
(condition-case-unless-debug err
(if-let* ((buffer (pop-to-buffer-same-window "*elpaca-bootstrap*"))
((zerop (apply #'call-process `("git" nil ,buffer t "clone"
,@(when-let* ((depth (plist-get order :depth)))
(list (format "--depth=%d" depth) "--no-single-branch"))
,(plist-get order :repo) ,repo))))
((zerop (call-process "git" nil buffer t "checkout"
(or (plist-get order :ref) "--"))))
(emacs (concat invocation-directory invocation-name))
((zerop (call-process emacs nil buffer nil "-Q" "-L" "." "--batch"
"--eval" "(byte-recompile-directory \".\" 0 'force)")))
((require 'elpaca))
((elpaca-generate-autoloads "elpaca" repo)))
(progn (message "%s" (buffer-string)) (kill-buffer buffer))
(error "%s" (with-current-buffer buffer (buffer-string))))
((error) (warn "%s" err) (delete-directory repo 'recursive))))
(unless (require 'elpaca-autoloads nil t)
(require 'elpaca)
(elpaca-generate-autoloads "elpaca" repo)
(let ((load-source-file-function nil)) (load "./elpaca-autoloads"))))
(add-hook 'after-init-hook #'elpaca-process-queues)
(elpaca `(,@elpaca-order))

View File

@@ -1,49 +1,19 @@
;; -*- no-byte-compile: t -*- ;; -*- no-byte-compile: t; lexical-binding: t; -*-
(let ((bootstrap-file (concat user-emacs-directory "straight/bootstrap.el"))
(bootstrap-version 2))
(unless (file-exists-p bootstrap-file)
(with-current-buffer
(url-retrieve-synchronously
"https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
'silent 'inhibit-cookies)
(goto-char (point-max))
(eval-print-last-sexp)))
(load bootstrap-file nil 'nomessage))
(setq native-comp-deferred-compilation-deny-list '("magit")) (setq native-comp-deferred-compilation-deny-list '("magit"))
(setq native-comp-always-compile t) (setq native-comp-always-compile t)
(setq load-no-native t) (setq load-no-native t)
(setq no-native-compile t) (setq no-native-compile t)
(setq warning-minimum-level :emergency)
(setq straight-disable-native-compile t)
;; This is a workaround for an issue in emacs28 with symlinks. See https://github.com/radian-software/straight.el/issues/701
(defun my-patch-package-find-file-visit-truename (oldfun &rest r)
(let ((find-file-visit-truename nil))
(apply oldfun r)))
(advice-add #'straight--build-autoloads :around
#'my-patch-package-find-file-visit-truename)
(setq package-enable-at-startup nil
straight-use-package-by-default t
straight-vc-git-default-protocol 'ssh)
(straight-use-package 'use-package)
(require 'use-package)
(setq use-package-enable-imenu-support t)
(setq use-package-ensure-function 'straight-use-package-ensure-function)
(defvar imalison:do-benchmark nil) (defvar imalison:do-benchmark nil)
(let ((bench-file (concat (file-name-directory user-init-file) "benchmark.el"))) (defun emacs-directory-filepath (filename)
(when (file-exists-p bench-file) (load bench-file))) (concat (file-name-directory load-file-name) filename))
(use-package benchmark-init (load-file (expand-file-name "elpaca-installer.el" user-emacs-directory))
:if imalison:do-benchmark (elpaca elpaca-use-package (elpaca-use-package-mode))
:demand t (setq use-package-enable-imenu-support t)
:config (setq use-package-always-ensure t)
(setq max-specpdl-size 99999999))
(defvar imalison:kat-mode nil) (defvar imalison:kat-mode nil)
(setq custom-file "~/.emacs.d/custom-before.el") (setq custom-file "~/.emacs.d/custom-before.el")
@@ -55,36 +25,81 @@
(setq mac-option-modifier 'meta) (setq mac-option-modifier 'meta)
(setq mac-command-modifier 'super)) (setq mac-command-modifier 'super))
;; See https://github.com/magit/magit/discussions/4997 . Without this magit is broken. ;;The packages in this section are used to as utilities in the rest of this init file.
(use-package magit ;;Ensure they are installed/activated first.
(use-package s
:ensure (:wait t)
:demand t) :demand t)
;; This seems to fix issues with helm not explicitly declaring its dependency on async (use-package dash
(use-package async :demand t) :ensure (:wait t)
:demand t
:config
(progn (dash-enable-font-lock)))
(use-package gh
:defer t
:ensure (:host github :repo "IvanMalison/gh.el"))
(use-package shut-up
:config
(defun imalison:shut-up-around (function &rest args)
(shut-up (apply function args))))
(use-package parse-csv :demand t)
(use-package emit
:ensure (emit :type git :host github :repo "colonelpanic8/emit")
:demand t
:config
(progn
(emit-prefix-selector imalison:mark-ring mark-ring)
(emit-prefix-selector imalison:shell-command-on-region
imalison:copy-shell-command-on-region
imalison:shell-command-on-region-replace
imalison:jq-replace)
(defun imalison:jq-replace (start end)
(interactive (region-if-active-otherwise-buffer))
(imalison:shell-command-on-region-replace start end "jq ."))
(emit-compose
imalison:copy-eval-last-sexp kill-new prin1-to-string eval-last-sexp)
(emit-prefix-selector imalison:eval-last-sexp
eval-region-or-last-sexp
imalison:copy-eval-last-sexp)))
(use-package request :defer t)
;; Without this, org can behave very strangely ;; Without this, org can behave very strangely
(use-package org (use-package org
:straight :ensure
(org :type git :host github :repo "colonelpanic8/org-mode" :local-repo "org" (org :type git :host github :repo "colonelpanic8/org-mode" :local-repo "org"
:branch "my-main-2025" :branch "my-main-2025"
:depth full :pre-build (straight-recipes-org-elpa--build) :build :depth full
(:not autoloads) :files :build (:not autoloads)
(:defaults "lisp/*.el" ("etc/styles/" "etc/styles/*"))) :files (:defaults "lisp/*.el" ("etc/styles/" "etc/styles/*"))
:defer t) :wait t))
(use-package dash :demand t) (elpaca-wait)
;; Install transient early to prevent built-in version from loading
(use-package transient
:ensure (:host github :repo "magit/transient" :wait t)
:demand t)
(elpaca-wait)
(when (or (equal (s-trim (shell-command-to-string "whoami")) "kat")
imalison:kat-mode)
(let ((debug-on-error t))
(org-babel-load-file
(concat (file-name-directory load-file-name) "kat-mode.org"))))
(let ((debug-on-error t)) (let ((debug-on-error t))
(org-babel-load-file (org-babel-load-file
(concat (file-name-directory load-file-name) "README.org"))) (expand-file-name "README.org" user-emacs-directory)))
(when (or (equal (s-trim (shell-command-to-string "whoami")) "kat") ;; (when imalison:do-benchmark (benchmark-init/deactivate))
imalison:kat-mode)
(let ((debug-on-error t))
(org-babel-load-file
(concat (file-name-directory load-file-name) "kat-mode.org"))))
(when imalison:do-benchmark (benchmark-init/deactivate))
;; Local Variables: ;; Local Variables:
;; flycheck-disabled-checkers: (emacs-lisp-checkdoc) ;; flycheck-disabled-checkers: (emacs-lisp-checkdoc)

View File

@@ -90,7 +90,7 @@ This makes evil-mode play nice with org-fc
*** javascript *** javascript
#+begin_src emacs-lisp #+begin_src emacs-lisp
(use-package ob-js (use-package ob-js
:straight nil :ensure nil
:after org :after org
:config :config
(progn (progn

View File

@@ -1,91 +1,43 @@
;;; org-api.el --- org-agenda-api server configuration -*- lexical-binding: t; -*-
;; Load main emacs config to get org settings, custom commands, etc.
(let ((current-dir (if load-file-name (file-name-directory load-file-name) "~/.emacs.d/"))) (let ((current-dir (if load-file-name (file-name-directory load-file-name) "~/.emacs.d/")))
(load (expand-file-name "init.el" current-dir))) (load (expand-file-name "init.el" current-dir)))
(use-package simple-httpd ;; Ensure dependencies are loaded
:demand t)
(require 'simple-httpd) (require 'simple-httpd)
(require 'org-agenda-api)
(defun org-api-get-todo-elements-from-filepath (filepath) ;; Configure capture templates for the API
(let ((todo-elements nil)) ;; These use the org-agenda-api format with :prompts for API parameters
(with-current-buffer (find-file-noselect filepath) (setq org-agenda-api-capture-templates
(save-excursion `(("gtd-todo"
(goto-char (point-min)) :name "GTD Todo"
(while (re-search-forward org-todo-regexp nil t) :template ("t" "Todo" entry (file "~/org/inbox.org")
(let* ((element (org-element-at-point)) (function (lambda ()
(type (org-element-type element))) (imalison:make-org-todo-template :content "%^{Title}")))
(when (eq type 'headline) :immediate-finish t)
(let ((todo (org-element-property :todo-keyword element))) :prompts (("Title" :type string :required t)))
(when todo ("scheduled-todo"
(push element todo-elements)))))))) :name "Scheduled Todo"
todo-elements)) :template ("s" "Scheduled" entry (file "~/org/inbox.org")
"* TODO %^{Title}\nSCHEDULED: %^{When}t\n"
:immediate-finish t)
:prompts (("Title" :type string :required t)
("When" :type date :required t)))
("tagged-todo"
:name "Tagged Todo"
:template ("g" "Tagged" entry (file "~/org/inbox.org")
"* TODO %^{Title} %^{Tags}g\n"
:immediate-finish t)
:prompts (("Title" :type string :required t)
("Tags" :type tags :required nil)))))
(defun org-api-get-agenda-todos () ;; Configure the server
(let* ((today (calendar-gregorian-from-absolute (org-today)))) (setq org-agenda-api-port 2025)
(mapcan 'org-api-get-todo-elements-from-filepath org-agenda-files))) (setq org-agenda-api-inbox-file "~/org/inbox.org")
(defun org-api-get-element-json (element) ;; Start the server
(let ((todo (org-element-property :todo-keyword element)) (message "Starting org-agenda-api server on port %d" org-agenda-api-port)
(title (org-element-property :raw-value element)) (org-agenda-api-start)
(tags (org-element-property :tags element)) (message "org-agenda-api server started")
(level (org-element-property :level element))
(scheduled (org-element-property :scheduled element))
(deadline (org-element-property :deadline element)))
`(("todo" . ,todo)
("title" . ,title)
("tags" . ,tags)
("level" . ,level)
("scheduled" . ,(when scheduled (org-format-timestamp scheduled "%Y-%m-%dT%H:%M:%SZ")))
("deadline" . ,(when deadline (org-format-timestamp deadline "%Y-%m-%dT%H:%M:%SZ"))))))
(defun org-api-item-json (item)
(let* ((todo (get-text-property 0 'todo-state item))
(title (substring-no-properties item))
(tags (get-text-property 0 'tags item))
(s (get-text-property 0 'ts-date item))
(scheduled (when s
(org-format-timestamp (org-time-from-absolute s) "%Y-%m-%dT%H:%M:%SZ") )))
`(("todo" . ,todo)
("title" . ,title)
("tags" . ,tags))))
(defun org-api-get-scheduled-or-deadlined (day filepath)
(with-current-buffer (find-file-noselect filepath)
(org-dlet ((date day))
(setf org-agenda-current-date date)
(nconc (org-agenda-get-deadlines) (org-agenda-get-scheduled)))))
(defun org-api-get-today-agenda ()
(let ((day (calendar-current-date)))
(mapcan (lambda (filepath) (org-api-get-scheduled-or-deadlined day filepath))
org-agenda-files)))
(defservlet get-all-todos application/json ()
(insert (json-encode (mapcar 'org-api-get-element-json (org-api-get-agenda-todos)))))
(defservlet get-todays-agenda application/json ()
(insert
(json-encode
(mapcar 'org-api-item-json
(org-api-get-today-agenda)))))
(defservlet create-todo application/json (a b c)
(org-api-capture (gethash "title" (json-parse-string (cadr (assoc "Content" c))))))
(cl-defun org-api-build-capture-template
(content &key (character "d") (heading "Dynamic"))
`(,character ,heading entry (file "~/org/inbox.org")
(function (lambda ()
(imalison:make-org-todo-template :content content)))
:immediate-finish t))
(defun org-api-capture (content)
(let* ((org-capture-templates (list (org-api-build-capture-template content))))
(org-capture nil "d")))
(message "Starting http server")
(setq httpd-port 2025)
(httpd-start)
(message "Finished starting http server")

View File

@@ -1,6 +1,6 @@
* include-file-as-forms * include-file-as-forms
We're going to use this to write separate parts of our config to different sections that will then be provided to our use package statment We're going to use this to write separate parts of our config to different sections that will then be provided to our use package statment
#+begin_src emacs-lisp #+begin_src emacs-lisp :tangle org-config.el
(defun imalison:include-file-as-forms (filename) (defun imalison:include-file-as-forms (filename)
"Include the contents of FILENAME into the source as s-expressions." "Include the contents of FILENAME into the source as s-expressions."
(with-temp-buffer (with-temp-buffer
@@ -15,9 +15,10 @@ We're going to use this to write separate parts of our config to different secti
`,@(nreverse forms)))) `,@(nreverse forms))))
#+end_src #+end_src
* use-package * use-package
#+begin_src emacs-lisp #+begin_src emacs-lisp :tangle org-config.el
(defmacro imalison:org-config () (defmacro imalison:org-config ()
`(use-package org `(use-package org
:ensure nil
:commands (org-mode org org-mobile-push org-mobile-pull org-agenda) :commands (org-mode org org-mobile-push org-mobile-pull org-agenda)
:mode ("\\.org\\'" . org-mode) :mode ("\\.org\\'" . org-mode)
:preface (progn ,@(imalison:include-file-as-forms (imalison:join-paths user-emacs-directory "org-config-preface.el"))) :preface (progn ,@(imalison:include-file-as-forms (imalison:join-paths user-emacs-directory "org-config-preface.el")))
@@ -28,9 +29,25 @@ We're going to use this to write separate parts of our config to different secti
(imalison:org-config) (imalison:org-config)
#+end_src #+end_src
* My Customization Variables * My Customization Variables
#+begin_src emacs-lisp :tangle org-config.el
;; Load org-config-preface when org-config.el is loaded directly.
(let ((preface (expand-file-name "org-config-preface.el" user-emacs-directory)))
(when (file-exists-p preface)
(load-file preface)))
;; Fallbacks in case preface isn't available yet.
(unless (boundp 'imalison:org-dir)
(defvar imalison:org-dir "~/org"))
(unless (boundp 'imalison:created-property-string)
(defvar imalison:created-property-string "
:PROPERTIES:
:ID: %(org-id-new)
:CREATED: %U
:END:"))
#+end_src
#+begin_src emacs-lisp :tangle org-config-preface.el #+begin_src emacs-lisp :tangle org-config-preface.el
(defvar imalison:org-dir "~/org") (defvar imalison:org-dir "~/org")
(defvar imalison:shared-org-dir "~/katnivan") (defvar imalison:shared-org-dir "~/org")
(defvar imalison:org-whoami "Ivan Malison") (defvar imalison:org-whoami "Ivan Malison")
(defvar imalison:org-people (list nil "Ivan Malison" "Kat Huang")) (defvar imalison:org-people (list nil "Ivan Malison" "Kat Huang"))
(defvar imalison:org-people-associated-states (defvar imalison:org-people-associated-states
@@ -65,7 +82,7 @@ We're going to use this to write separate parts of our config to different secti
(defvar imalison:repeating-org-files (defvar imalison:repeating-org-files
(list imalison:org-habits-file imalison:shared-habits-file imalison:shared-repeating-file)) (list imalison:org-habits-file imalison:shared-habits-file imalison:shared-repeating-file))
(defvar imalison:include-repeating-in-agenda nil) (defvar imalison:include-repeating-in-agenda t)
(defun imalison:add-to-org-agenda-files (incoming-files) (defun imalison:add-to-org-agenda-files (incoming-files)
(setq org-agenda-files (setq org-agenda-files
@@ -76,6 +93,7 @@ We're going to use this to write separate parts of our config to different secti
(defvar imalison:created-property-string " (defvar imalison:created-property-string "
:PROPERTIES: :PROPERTIES:
:ID: %(org-id-new)
:CREATED: %U :CREATED: %U
:END:") :END:")
#+end_src #+end_src
@@ -96,7 +114,7 @@ We're going to use this to write separate parts of our config to different secti
#+end_src #+end_src
* Org Variable Customization * Org Variable Customization
#+begin_src emacs-lisp :tangle org-config-custom.el #+begin_src emacs-lisp :tangle org-config-custom.el
(org-agenda-log-mode-items '(closed)) (org-agenda-log-mode-items '(closed state))
(org-agenda-skip-deadline-if-done t) (org-agenda-skip-deadline-if-done t)
(org-agenda-skip-scheduled-if-done t) (org-agenda-skip-scheduled-if-done t)
(org-agenda-span 10) (org-agenda-span 10)
@@ -499,7 +517,11 @@ that have a SCHEDULED date before today to the current date."
(missing-priority (missing-priority
'(tags-todo "-PRIORITY={.}/!" '(tags-todo "-PRIORITY={.}/!"
((org-agenda-overriding-header ((org-agenda-overriding-header
"These don't have priorities:"))))) "These don't have priorities:"))))
(high-priority-unscheduled
'(tags-todo "+PRIORITY<\"C\"-SCHEDULED={.}-DEADLINE={.}/!"
((org-agenda-overriding-header
"High priority without scheduled/deadline:")))))
(setq org-agenda-custom-commands (setq org-agenda-custom-commands
`(("M" "Main agenda view" `(("M" "Main agenda view"
@@ -528,7 +550,12 @@ that have a SCHEDULED date before today to the current date."
((org-agenda-overriding-header "Completion History:") ((org-agenda-overriding-header "Completion History:")
(org-agenda-ndays 5) (org-agenda-ndays 5)
(org-agenda-entry-types '(:none)) (org-agenda-entry-types '(:none))
(org-agenda-start-with-log-mode '(state)))))))) (org-agenda-start-with-log-mode '(state)))))
,(cons "i" (cons "Inbox" inbox))
,(cons "n" (cons "Next" next))
("w" "Wait" todo "WAIT"
((org-agenda-overriding-header "Waiting:")))
,(cons "u" (cons "High priority unscheduled" high-priority-unscheduled)))))
#+end_src #+end_src
*** Filters *** Filters
**** Regexp Presets **** Regexp Presets
@@ -591,6 +618,7 @@ specific time, they should appear in the agenda at that time!
(with-temp-buffer (with-temp-buffer
(org-mode) (org-mode)
(insert content) (insert content)
(org-set-property "ID" (org-id-new))
(org-set-property "CREATED" (org-set-property "CREATED"
(with-temp-buffer (with-temp-buffer
(org-insert-time-stamp (org-insert-time-stamp
@@ -607,6 +635,7 @@ specific time, they should appear in the agenda at that time!
(org-insert-heading) (org-insert-heading)
(insert content) (insert content)
(org-todo creation-state) (org-todo creation-state)
(org-set-property "ID" (org-id-new))
(org-set-property "CREATED" (org-set-property "CREATED"
(with-temp-buffer (with-temp-buffer
(org-insert-time-stamp (org-insert-time-stamp
@@ -663,7 +692,7 @@ specific time, they should appear in the agenda at that time!
*** Templates *** Templates
#+begin_src emacs-lisp :tangle org-config-config.el #+begin_src emacs-lisp :tangle org-config-config.el
(use-package org-capture (use-package org-capture
:straight nil :ensure nil
:config :config
(add-to-list 'org-capture-templates (add-to-list 'org-capture-templates
`("t" "GTD Todo (Linked)" entry (file ,imalison:org-gtd-file) `("t" "GTD Todo (Linked)" entry (file ,imalison:org-gtd-file)
@@ -696,6 +725,7 @@ specific time, they should appear in the agenda at that time!
"* TODO "* TODO
SCHEDULED: %^t SCHEDULED: %^t
:PROPERTIES: :PROPERTIES:
:ID: %(org-id-new)
:CREATED: %U :CREATED: %U
:STYLE: habit :STYLE: habit
:END:")) :END:"))
@@ -706,7 +736,14 @@ SCHEDULED: %^t
(find-file (let ((date (format-time-string "%Y-%m-%d"))) (find-file (let ((date (format-time-string "%Y-%m-%d")))
(expand-file-name (concat date ".org") (expand-file-name (concat date ".org")
"~/org/weekly"))))) "~/org/weekly")))))
(file "~/org/capture-templates/weekly.org")))) (file "~/org/capture-templates/weekly.org")))
(add-to-list 'org-capture-templates
`("n" "Next (Scheduled Today)" entry (file ,imalison:org-gtd-file)
,(format "%s%s\n%s" "* NEXT %?" imalison:created-property-string
"SCHEDULED: %(format-time-string \"<%Y-%m-%d %a>\")")))
(add-to-list 'org-capture-templates
`("i" "Inbox" entry (file ,imalison:org-gtd-file)
(function (lambda (&rest args) (imalison:make-org-todo-template :creation-state "INBOX"))))))
#+end_src #+end_src
** Babel ** Babel
#+begin_src emacs-lisp :tangle org-config-config.el #+begin_src emacs-lisp :tangle org-config-config.el
@@ -741,6 +778,7 @@ SCHEDULED: %^t
Note that this does not go into org-config-config.el. This is on purpose Note that this does not go into org-config-config.el. This is on purpose
#+begin_src emacs-lisp #+begin_src emacs-lisp
(use-package org (use-package org
:ensure nil
:after frame-mode :after frame-mode
:config :config
(progn (progn
@@ -754,7 +792,7 @@ Note that this does not go into org-config-config.el. This is on purpose
** Disable yasnippet in org-mode ** Disable yasnippet in org-mode
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package org (use-package org
:straight nil :ensure nil
:config :config
(progn (progn
(defun imalison:disable-yas () (defun imalison:disable-yas ()
@@ -765,6 +803,7 @@ Note that this does not go into org-config-config.el. This is on purpose
This was taken from [[http://emacs.stackexchange.com/questions/3374/set-the-background-of-org-exported-code-blocks-according-to-theme][here]]. This was taken from [[http://emacs.stackexchange.com/questions/3374/set-the-background-of-org-exported-code-blocks-according-to-theme][here]].
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package org (use-package org
:ensure nil
:config :config
(progn (progn
(defun imalison:org-inline-css-hook (exporter) (defun imalison:org-inline-css-hook (exporter)
@@ -812,7 +851,7 @@ This function replaces the default naming scheme with a call to
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package ox (use-package ox
:defer t :defer t
:straight nil :ensure nil
:config :config
(defun org-export-get-reference (datum info) (defun org-export-get-reference (datum info)
"Return a unique reference for DATUM, as a string. "Return a unique reference for DATUM, as a string.
@@ -840,7 +879,7 @@ alphanumeric characters only."
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package ox-html (use-package ox-html
:commands (org-html-export-as-html org-html-export-as-html) :commands (org-html-export-as-html org-html-export-as-html)
:straight nil :ensure nil
:preface :preface
(progn (progn
(defvar imalison:link-svg-html (defvar imalison:link-svg-html
@@ -872,7 +911,7 @@ alphanumeric characters only."
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package ox-html (use-package ox-html
:defer t :defer t
:straight nil :ensure nil
:config :config
(setq org-html-inline-image-rules (setq org-html-inline-image-rules
'(("file" . "\\.\\(jpeg\\|jpg\\|png\\|gif\\|svg\\)\\(\\?.*?\\)?\\'") '(("file" . "\\.\\(jpeg\\|jpg\\|png\\|gif\\|svg\\)\\(\\?.*?\\)?\\'")
@@ -883,7 +922,7 @@ alphanumeric characters only."
** Use org-tempo to allow inserting templates using e.g. <s ** Use org-tempo to allow inserting templates using e.g. <s
#+begin_src emacs-lisp #+begin_src emacs-lisp
(use-package org-tempo (use-package org-tempo
:straight nil :ensure nil
:after org) :after org)
#+end_src #+end_src
* Packages * Packages
@@ -981,8 +1020,6 @@ alphanumeric characters only."
:config :config
(progn (progn
(when (version<= "29.0" emacs-version) (when (version<= "29.0" emacs-version)
(use-package emacsql-sqlite-builtin
:demand t)
(setq org-roam-database-connector 'sqlite-builtin)) (setq org-roam-database-connector 'sqlite-builtin))
(org-roam-db-autosync-mode +1) (org-roam-db-autosync-mode +1)
@@ -1004,22 +1041,22 @@ alphanumeric characters only."
((get-buffer org-roam-buffer) 'exists) ((get-buffer org-roam-buffer) 'exists)
(t 'none))) (t 'none)))
(use-package frame-mode ;; org-roam-buffer-visibility-fn was removed in newer org-roam versions
:if imalison:use-frame-mode (when (and imalison:use-frame-mode (boundp 'org-roam-buffer-visibility-fn))
:demand t (require 'frame-mode)
:config (emit-variable-set-mode
(progn imalison:org-roam-set-frame-visibility-mode
(emit-variable-set-mode org-roam-buffer-visibility-fn 'imalison:org-roam-frame-based-buffer-visibility-fn)
imalison:org-roam-set-frame-visibility-mode (emit-make-mode-dependent imalison:org-roam-set-frame-visibility-mode frame-mode)))
org-roam-buffer-visibility-fn 'imalison:org-roam-frame-based-buffer-visibility-fn)
(emit-make-mode-dependent imalison:org-roam-set-frame-visibility-mode frame-mode))))
:custom :custom
(org-roam-directory (file-truename "~/org/roam/"))) (org-roam-directory (file-truename "~/org/roam/")))
#+end_src #+end_src
***** ui ***** ui
#+begin_src emacs-lisp #+begin_src emacs-lisp
(use-package emacs-http-server (use-package simple-httpd
:demand t) :ensure (:host github :repo "skeeto/emacs-web-server"
:local-repo "simple-httpd"
:files ("simple-httpd.el")))
(use-package org-roam-ui (use-package org-roam-ui
:after org-roam :after org-roam
@@ -1084,7 +1121,7 @@ alphanumeric characters only."
:config :config
(progn (progn
(require 'org-fc-hydra)) (require 'org-fc-hydra))
:straight (org-fc :type git :host github :repo "l3kn/org-fc" :ensure (:host github :repo "l3kn/org-fc"
:files ("*.el" "awk" "demo.org"))) :files ("*.el" "awk" "demo.org")))
#+end_src #+end_src
** org-ql ** org-ql
@@ -1097,11 +1134,10 @@ alphanumeric characters only."
#+begin_src emacs-lisp #+begin_src emacs-lisp
(use-package org-window-habit (use-package org-window-habit
:demand t :demand t
:straight :ensure
(org-window-habit (:repo "colonelpanic8/org-window-habit"
:repo "colonelpanic8/org-window-habit"
:host github :host github
:files ("org-window-habit.el")) :files (:defaults "*.el"))
:custom :custom
((org-window-habit-property-prefix nil) ((org-window-habit-property-prefix nil)
(org-window-habit-repeat-to-scheduled t) (org-window-habit-repeat-to-scheduled t)

View File

@@ -1,63 +0,0 @@
#!/usr/bin/env python
from __future__ import print_function
import appdirs
import argparse
import os
import struct
clipit_history_file = os.path.join(
appdirs.user_data_dir(), "clipit/history",
)
def get_clipit_history(filename):
with open(filename, 'rb') as f:
f.read(68)
size, _ = struct.unpack('2i', f.read(8))
while (size > 0):
item = f.read(size)
if item:
yield item.decode('utf-8')
_, _, _, size, _ = struct.unpack('5i', f.read(20))
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Lookup clipit history')
parser.add_argument(
'--separator', '-s',
help='the separator to use when outputting history',
type=str,
default='\n',
)
parser.add_argument(
'--begin-index', '-b',
type=int,
default=0
)
parser.add_argument(
'--end-index', '-e',
type=int,
default=None
)
parser.add_argument(
'--index', '-i',
type=int,
default=None
)
parser.add_argument(
'--separator-replacement', '-r',
type=str,
default=None
)
args = parser.parse_args()
if not args.separator_replacement:
args.separator_replacement = args.separator
history = list(get_clipit_history(clipit_history_file))
if args.index is not None:
text = history[args.index]
else:
selected = history[args.begin_index:args.end_index]
text = args.separator.join([s.replace(args.separator, args.separator_replacement)
for s in selected])
print(text, end='')

View File

@@ -0,0 +1,2 @@
#!/usr/bin/env bash
rofi -modi "clipboard:greenclip print" -show clipboard

View File

@@ -1,9 +0,0 @@
#!/usr/bin/env bash
SELECTED_INDEX="$(clipit_history.py -r '(newline)' | rofi -dmenu -format i)"
if [ "$SELECTED_INDEX" -eq "$SELECTED_INDEX" ] 2>/dev/null; then
xdotool type "$(clipit_history.py -e 5 -i $SELECTED_INDEX)"
fi
xdotool type

View File

@@ -1,13 +1,40 @@
#!/usr/bin/env zsh #!/usr/bin/env zsh
set -euo pipefail
otherinputs () { otherinputs () {
get_sink_input_info.hs | jq 'select(.application_process_id != "'"$1"'")' get_sink_input_info.hs | jq 'select(.application_process_id != "'"$1"'")'
} }
thePID="$(xprop _NET_WM_PID -id $(xdotool getactivewindow) | grep -Eo '[0-9]*')" get_active_pid () {
sinkInfo="$(pashowinputbypid $thePID)" if [[ "${XDG_SESSION_TYPE:-}" == "wayland" ]] && command -v hyprctl >/dev/null 2>&1; then
sinkID="$(echo $sinkInfo | jq -r .sink_input_id)" hyprctl activewindow -j | jq -r '.pid'
muted="$(echo $sinkInfo | jq -r .Mute)" else
xprop _NET_WM_PID -id "$(xdotool getactivewindow)" | grep -Eo '[0-9]*'
fi
}
get_sink_info_by_pid () {
local pid="$1"
if command -v pashowinputbypid >/dev/null 2>&1; then
pashowinputbypid "$pid"
else
pactl -f json list sink-inputs | jq -c --arg pid "$pid" '
.[] | select(.properties."application.process.id" == ($pid|tonumber)) |
{ sink_input_id: .index, Mute: (if .mute then "yes" else "no" end) }
' | head -1
fi
}
thePID="$(get_active_pid)"
sinkInfo="$(get_sink_info_by_pid "$thePID")"
if [[ -z "$sinkInfo" ]]; then
exit 0
fi
sinkID="$(echo "$sinkInfo" | jq -r .sink_input_id)"
muted="$(echo "$sinkInfo" | jq -r .Mute)"
if [[ $muted == *"no"* ]]; then if [[ $muted == *"no"* ]]; then
newState="1" newState="1"
else else
@@ -16,7 +43,7 @@ fi
echo "$sinkID" echo "$sinkID"
if [[ $1 == *"only"* ]]; then if [[ "${1:-}" == *"only"* ]]; then
pactl set-sink-input-mute "$sinkID" 0 pactl set-sink-input-mute "$sinkID" 0
otherinputs "$thePID" | jq -r .sink_input_id | xargs -I theid sh -c 'pactl set-sink-input-mute theid 1' otherinputs "$thePID" | jq -r .sink_input_id | xargs -I theid sh -c 'pactl set-sink-input-mute theid 1'
else else

View File

@@ -0,0 +1,18 @@
#!/usr/bin/env sh
function codex_tmux {
base=$(basename "$PWD")
name="$base"
if tmux has-session -t "$name" 2>/dev/null; then
i=2
while tmux has-session -t "${name}-${i}" 2>/dev/null; do
i=$((i+1))
done
name="${name}-${i}"
fi
tmux new-session -s "$name" -c "$PWD" codex --dangerously-bypass-approvals-and-sandbox "$@"
}
codex_tmux "$@"

View File

@@ -0,0 +1,18 @@
#!/usr/bin/env sh
function passgen {
if [ -z "$1" ]; then
echo "Usage: passgen <pass-entry-name>" >&2
return 1
fi
local base_pass upper symbol password
base_pass="$(xkcdpass -n 3 | tr -d ' ')"
upper="$(echo {A..Z} | tr ' ' '\n' | shuf -n1)"
symbol="$(echo '!@#$%^&*' | fold -w1 | shuf -n1)"
password="${base_pass}${upper}${symbol}"
echo "$password" | pass insert -e "$1"
}
passgen

31
dotfiles/lib/functions/tn Executable file
View File

@@ -0,0 +1,31 @@
#!/usr/bin/env sh
function tn {
if [ -z "$TMUX" ]; then
echo "Not in a tmux session"
return 1
fi
base=$(basename "$PWD")
current=$(tmux display-message -p '#{session_name}')
# Don't rename if already named correctly
if [ "$current" = "$base" ]; then
echo "Session already named '$base'"
return 0
fi
if tmux has-session -t "$base" 2>/dev/null; then
i=2
while tmux has-session -t "${base}-${i}" 2>/dev/null; do
i=$((i+1))
done
tmux rename-session "${base}-${i}"
echo "Renamed session to '${base}-${i}'"
else
tmux rename-session "$base"
echo "Renamed session to '$base'"
fi
}
tn "$@"

View File

@@ -1,5 +1,3 @@
# Automatically rename new sessions to the basename of the current directory # Create a new Codex session from the current pane path and switch to it.
set-hook -g session-created 'run-shell "tmux rename-session -t #{session_name} $(basename #{pane_current_path})"' # Prefix + C starts a new session without prompting for a name.
bind-key C new-session -c '#{pane_current_path}' 'codex --dangerously-bypass-approvals-and-sandbox'
# Also rename when attaching to a session (optional)
set-hook -g client-session-changed 'run-shell "tmux rename-session -t #{session_name} $(basename #{pane_current_path})"'

View File

@@ -1,20 +1,25 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Local compilation script for generating HTML from README.org
# Note: For CI, this is now handled by GitHub Actions (.github/workflows/gh-pages.yml)
set -e
export PATH="$HOME/.cask/bin:$HOME/.evm/bin:$PATH"
THIS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" THIS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
TARGET=$(readlink -f "$THIS_DIR/../dotfiles/emacs.d/README.org") # Use system emacs or EMACS environment variable
EMACS="${EMACS:-emacs}"
git clone https://github.com/rejeep/evm.git "$HOME/.evm" cd "$THIS_DIR"
evm config path /tmp
evm install emacs-25.1-travis --use --skip
export EMACS="$(evm bin)"
git clone https://github.com/cask/cask # Install cask dependencies if needed
export PATH=$(pwd)/cask/bin:$PATH if [ ! -d ".cask" ]; then
cask install
fi
cask install # Generate HTML
cask exec "$EMACS" --script generate-html.el cask exec "$EMACS" --script generate-html.el
# Move the generated file
mv "$THIS_DIR/../dotfiles/emacs.d/README.html" . mv "$THIS_DIR/../dotfiles/emacs.d/README.html" .
echo "Generated README.html in $THIS_DIR"

View File

@@ -1,68 +1,11 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# This approach was adapted from https://gist.github.com/domenic/ec8b0fc8ab45f39403dd # DEPRECATED: This script was used for Travis CI deployments.
# Deployment is now handled by GitHub Actions (.github/workflows/gh-pages.yml)
#
# This script is kept for reference only.
# See: https://github.com/IvanMalison/dotfiles/blob/master/.github/workflows/gh-pages.yml
THIS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" echo "ERROR: This script is deprecated."
echo "Deployment is now handled by GitHub Actions."
cd $THIS_DIR echo "See: .github/workflows/gh-pages.yml"
exit 1
git config --global user.name "$COMMIT_AUTHOR_NAME"
git config --global user.email "$COMMIT_AUTHOR_EMAIL"
set -e # Exit with nonzero exit code if anything fails
SOURCE_BRANCH="master"
TARGET_BRANCH="gh-pages"
function doCompile {
./compile.sh
}
# Pull requests and commits to other branches shouldn't try to deploy, just build to verify
if [ "$TRAVIS_PULL_REQUEST" != "false" -o "$TRAVIS_BRANCH" != "$SOURCE_BRANCH" ]; then
echo "Skipping deploy; just doing a build."
doCompile
exit 0
fi
# Save some useful information
REPO=`git config remote.origin.url`
SSH_REPO=${REPO/https:\/\/github.com\//git@github.com:}
SHA=`git rev-parse --verify HEAD`
# Run our compile script
doCompile
# Get the deploy key by using Travis's stored variables to decrypt deploy_key.enc
ENCRYPTED_KEY_VAR="encrypted_${ENCRYPTION_LABEL}_key"
ENCRYPTED_IV_VAR="encrypted_${ENCRYPTION_LABEL}_iv"
ENCRYPTED_KEY=${!ENCRYPTED_KEY_VAR}
ENCRYPTED_IV=${!ENCRYPTED_IV_VAR}
openssl aes-256-cbc -K $ENCRYPTED_KEY -iv $ENCRYPTED_IV -in deploy_key.enc -out deploy_key -d
chmod 600 deploy_key
eval `ssh-agent -s`
ssh-add deploy_key
# Clone the existing gh-pages for this repo into out/
# Create a new empty branch if gh-pages doesn't exist yet (should only happen on first deply)
git clone $REPO out
cd out
git checkout $TARGET_BRANCH || git checkout --orphan $TARGET_BRANCH
# Clean out existing contents
git ls-files | xargs rm -rf
mv ../README.html ./index.html
# Commit the "changes", i.e. the new version.
# The delta will show diffs between new and old versions.
git add --all .
git commit -m "Deploy to GitHub Pages: ${SHA}"
git fetch origin master
if [ "$(git rev-parse origin/master)" == "$SHA" ]; then
git push "$SSH_REPO" "$TARGET_BRANCH"
else
echo "The commit this build was started for is not the one on master. Doing nothing."
fi

Binary file not shown.

View File

@@ -19,12 +19,9 @@
(require 's) (require 's)
(org-babel-tangle-file readme-src) (org-babel-tangle-file readme-src)
;; This makes it so that any dependencies specified with :straight, will (require 'cl-lib)
;; actually just be installed with the default melpa use-package ensure logic. (load-file (concat emacs-dir "org-config-bootstrap.el"))
(defalias 'use-package-handler/:straight (org-babel-tangle-file (concat emacs-dir "org-config.org"))
#'use-package-handler/:ensure)
(add-to-list 'use-package-keywords :straight)
(load-file (concat emacs-dir "org-config.el")) (load-file (concat emacs-dir "org-config.el"))
(defun export-target (target) (defun export-target (target)

114
nix-darwin/flake.lock generated
View File

@@ -8,7 +8,7 @@
"railbird-secrets", "railbird-secrets",
"nixpkgs" "nixpkgs"
], ],
"systems": "systems" "systems": "systems_3"
}, },
"locked": { "locked": {
"lastModified": 1707830867, "lastModified": 1707830867,
@@ -41,6 +41,48 @@
"type": "github" "type": "github"
} }
}, },
"claude-code-nix": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1770168651,
"narHash": "sha256-SxzTEu49iaAA/nAT28Rsr4BmjC3eCkiaM4/ZYBVhhNQ=",
"owner": "sadjow",
"repo": "claude-code-nix",
"rev": "f256f48c037a6e54afa332795328f753f2fafbaf",
"type": "github"
},
"original": {
"owner": "sadjow",
"repo": "claude-code-nix",
"type": "github"
}
},
"codex-cli-nix": {
"inputs": {
"flake-utils": "flake-utils_2",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1770232831,
"narHash": "sha256-C5e2wjd//pLJA1LqSYc/y9aZkM8wmZo/BAuzhZDuyFE=",
"owner": "sadjow",
"repo": "codex-cli-nix",
"rev": "64805eb1d1afffcbbcef0ffc053295f0065cd51d",
"type": "github"
},
"original": {
"owner": "sadjow",
"repo": "codex-cli-nix",
"type": "github"
}
},
"darwin": { "darwin": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@@ -65,9 +107,45 @@
} }
}, },
"flake-utils": { "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"
}
},
"flake-utils_2": {
"inputs": { "inputs": {
"systems": "systems_2" "systems": "systems_2"
}, },
"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"
}
},
"flake-utils_3": {
"inputs": {
"systems": "systems_4"
},
"locked": { "locked": {
"lastModified": 1709126324, "lastModified": 1709126324,
"narHash": "sha256-q6EQdSeUZOG26WelxqkmR7kArjgWCdw5sfJVHPH/7j8=", "narHash": "sha256-q6EQdSeUZOG26WelxqkmR7kArjgWCdw5sfJVHPH/7j8=",
@@ -229,7 +307,7 @@
"railbird-secrets": { "railbird-secrets": {
"inputs": { "inputs": {
"agenix": "agenix", "agenix": "agenix",
"flake-utils": "flake-utils", "flake-utils": "flake-utils_3",
"nixpkgs": "nixpkgs_2" "nixpkgs": "nixpkgs_2"
}, },
"locked": { "locked": {
@@ -248,6 +326,8 @@
}, },
"root": { "root": {
"inputs": { "inputs": {
"claude-code-nix": "claude-code-nix",
"codex-cli-nix": "codex-cli-nix",
"home-manager": "home-manager", "home-manager": "home-manager",
"homebrew-cask": "homebrew-cask", "homebrew-cask": "homebrew-cask",
"homebrew-core": "homebrew-core", "homebrew-core": "homebrew-core",
@@ -286,6 +366,36 @@
"repo": "default", "repo": "default",
"type": "github" "type": "github"
} }
},
"systems_3": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_4": {
"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

@@ -21,6 +21,16 @@
}; };
home-manager.url = "github:nix-community/home-manager"; home-manager.url = "github:nix-community/home-manager";
home-manager.inputs.nixpkgs.follows = "nixpkgs"; home-manager.inputs.nixpkgs.follows = "nixpkgs";
codex-cli-nix = {
url = "github:sadjow/codex-cli-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
claude-code-nix = {
url = "github:sadjow/claude-code-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
}; };
outputs = inputs@{ self, nix-darwin, nixpkgs, home-manager, ... }: outputs = inputs@{ self, nix-darwin, nixpkgs, home-manager, ... }:
@@ -112,7 +122,14 @@
}; };
}; };
nixpkgs.overlays = [(import ../nixos/overlay.nix)]; nixpkgs.overlays = [
(import ../nixos/overlay.nix)
# Use codex and claude-code from dedicated flakes with cachix
(final: prev: {
codex = inputs.codex-cli-nix.packages.${prev.stdenv.hostPlatform.system}.default;
claude-code = inputs.claude-code-nix.packages.${prev.stdenv.hostPlatform.system}.default;
})
];
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
#python-with-my-packages #python-with-my-packages
emacs emacs
@@ -126,7 +143,8 @@
nodejs nodejs
ripgrep ripgrep
slack slack
claude-code claude-code
codex
typescript typescript
vim vim
yarn yarn
@@ -141,7 +159,18 @@
programs.direnv.enable = true; programs.direnv.enable = true;
# Necessary for using flakes on this system. # Necessary for using flakes on this system.
nix.settings.experimental-features = "nix-command flakes"; nix.settings = {
experimental-features = "nix-command flakes";
substituters = [
"https://cache.nixos.org"
"https://codex-cli.cachix.org"
"https://claude-code.cachix.org"
];
trusted-public-keys = [
"codex-cli.cachix.org-1:1Br3H1hHoRYG22n//cGKJOk3cQXgYobUel6O8DgSing="
"claude-code.cachix.org-1:YeXf2aNu7UTX8Vwrze0za1WEDS+4DuI2kVeWEE4fsRk="
];
};
# Set Git commit hash for darwin-version. # Set Git commit hash for darwin-version.

View File

@@ -0,0 +1,80 @@
---
name: bump-overlay-versions
description: Use when user asks to bump, update, or upgrade claude-code or codex versions in overlay.nix, or when checking if newer versions are available
---
# Bump Overlay Versions
## Overview
Updates claude-code and/or codex to latest versions in `~/dotfiles/nixos/overlay.nix`. Nix requires correct hashes which must be discovered through failed builds.
## Quick Reference
| Package | Check Latest | Hash Fields |
|---------|--------------|-------------|
| claude-code | `npm view @anthropic-ai/claude-code version` | `hash`, `npmDepsHash` (keep empty) |
| codex | `curl -s "https://api.github.com/repos/openai/codex/releases/latest" \| jq -r '.tag_name'` | `hash`, `cargoHash` |
## Workflow
### 1. Check Current vs Latest Versions
```bash
# Current versions are in overlay.nix claudeCodeVersion and codexVersion blocks
# Check latest:
npm view @anthropic-ai/claude-code version
curl -s "https://api.github.com/repos/openai/codex/releases/latest" | jq -r '.tag_name'
# codex tag format: rust-v0.92.0 -> version is 0.92.0
```
### 2. Update Version and Clear Hashes
In `~/dotfiles/nixos/overlay.nix`:
**For claude-code:**
```nix
claudeCodeVersion = {
version = "X.Y.Z"; # Update to new version
hash = ""; # Clear - will get from build error
npmDepsHash = ""; # Keep empty (no npm deps)
};
```
**For codex:**
```nix
codexVersion = {
version = "X.Y.Z"; # Update to new version (without rust-v prefix)
hash = ""; # Clear - will get from build error
cargoHash = ""; # Clear - will get from build error
};
```
### 3. Build to Get Hashes
```bash
just switch
```
The build will fail with hash mismatch errors showing the correct hash. Copy the `got:` hash value.
**For codex:** You'll need to run twice - once for `hash` (source), once for `cargoHash` (cargo deps).
### 4. Update with Correct Hashes
Replace empty strings with the hashes from build errors, then run `just switch` again.
## Enable/Disable Overrides
The overlay uses boolean flags - set to `false` to use nixpkgs versions instead:
```nix
enableCodexOverride = true; # Set false to use nixpkgs codex
enableClaudeCodeOverride = true; # Set false to use nixpkgs claude-code
```
**Never delete the override code** - just toggle the flags.
## File Location
`~/dotfiles/nixos/overlay.nix`

View File

@@ -4,6 +4,6 @@
}; };
config = { config = {
nixpkgs.config.android_sdk.accept_license = true; nixpkgs.config.android_sdk.accept_license = true;
programs.adb.enable = true; environment.systemPackages = [ pkgs.android-tools ];
}; };
} }

View File

@@ -1,4 +1,4 @@
{ config, pkgs, forEachUser, makeEnable, realUsers, ... }: { config, pkgs, makeEnable, realUsers, ... }:
makeEnable config "myModules.base" true { makeEnable config "myModules.base" true {
nixpkgs.config.permittedInsecurePackages = [ nixpkgs.config.permittedInsecurePackages = [
"electron-12.2.3" "electron-12.2.3"
@@ -65,8 +65,13 @@ makeEnable config "myModules.base" true {
defaultLocale = "en_US.UTF-8"; defaultLocale = "en_US.UTF-8";
}; };
# # Update timezone automatically # Update timezone automatically
# The tzupdate.timer handles triggering with OnStartupSec=30s delay.
# We disable the service's direct WantedBy since network-online.target
# is reached before network is actually online (because we disable
# NetworkManager-wait-online.service to avoid boot hangs).
services.tzupdate.enable = true; services.tzupdate.enable = true;
systemd.services.tzupdate.wantedBy = pkgs.lib.mkForce [];
# TODO: Add a comment explaining what this does. # TODO: Add a comment explaining what this does.
services.locate.enable = true; services.locate.enable = true;
@@ -88,6 +93,5 @@ makeEnable config "myModules.base" true {
programs.dconf.enable = true; programs.dconf.enable = true;
home-manager.users = forEachUser (import ./home-manager.nix);
nix.settings.trusted-users = realUsers ++ ["gitea-runner"]; nix.settings.trusted-users = realUsers ++ ["gitea-runner"];
} }

View File

@@ -97,9 +97,7 @@
specialArgs = rec { specialArgs = rec {
inherit inputs machineNames; inherit inputs machineNames;
makeEnable = (import ../make-enable.nix) nixpkgs.lib; makeEnable = (import ../make-enable.nix) nixpkgs.lib;
mapValueToKeys = keys: value: builtins.listToAttrs (map (name: { inherit name value; }) keys);
realUsers = [ "root" "imalison" "kat" "dean" "alex" "ben"]; realUsers = [ "root" "imalison" "kat" "dean" "alex" "ben"];
forEachUser = mapValueToKeys realUsers;
} // specialArgs // (import ../keys.nix); } // specialArgs // (import ../keys.nix);
}); });
in in

View File

@@ -11,6 +11,7 @@ makeEnable config "myModules.code" true {
claude-code claude-code
codex codex
gemini-cli gemini-cli
opencode
# MCP # MCP
github-mcp-server github-mcp-server
@@ -77,7 +78,7 @@ makeEnable config "myModules.code" true {
nixd nixd
nil nil
alejandra alejandra
] ++ (if pkgs.system == "x86_64-linux" then with pkgs; [ ] ++ (if pkgs.stdenv.hostPlatform.system == "x86_64-linux" then with pkgs; [
# purescript # purescript
purescript purescript
# Broken # Broken

View File

@@ -1,4 +1,4 @@
{ config, lib, forEachUser, ... }: { config, lib, ... }:
{ {
imports = [ imports = [
./android.nix ./android.nix
@@ -42,6 +42,7 @@
./wsl.nix ./wsl.nix
./wyoming.nix ./wyoming.nix
./xmonad.nix ./xmonad.nix
./org-agenda-api-host.nix
]; ];
options = { options = {

View File

@@ -1,7 +1,10 @@
{ inputs, config, pkgs, makeEnable, ... }: { inputs, config, pkgs, makeEnable, ... }:
makeEnable config "myModules.desktop" true { makeEnable config "myModules.desktop" true {
services.greenclip.enable = true;
imports = [ imports = [
./fonts.nix ./fonts.nix
./hyprland.nix
./keyd.nix
]; ];
services.xserver = { services.xserver = {
@@ -21,8 +24,6 @@ makeEnable config "myModules.desktop" true {
}; };
}; };
programs.hyprland.enable = true;
services.autorandr = { services.autorandr = {
enable = true; enable = true;
}; };
@@ -47,6 +48,7 @@ makeEnable config "myModules.desktop" true {
# XOrg # XOrg
autorandr autorandr
keyd
wmctrl wmctrl
xclip xclip
xdotool xdotool
@@ -57,16 +59,15 @@ makeEnable config "myModules.desktop" true {
# Desktop # Desktop
alacritty alacritty
ghostty
blueman blueman
# clipit # clipit
d-spy d-spy
kdePackages.dolphin kdePackages.dolphin
# inputs.ghostty.packages."${system}".default
feh feh
firefox firefox
cheese cheese
gpaste
kdePackages.kleopatra kdePackages.kleopatra
libnotify libnotify
libreoffice libreoffice
@@ -88,7 +89,7 @@ makeEnable config "myModules.desktop" true {
# TODO: reenable # TODO: reenable
# transmission_3-gtk # transmission_3-gtk
vlc vlc
xfce.thunar thunar
# Audio # Audio
picard picard
@@ -103,7 +104,7 @@ makeEnable config "myModules.desktop" true {
# Visualization # Visualization
graphviz graphviz
nodePackages.mermaid-cli nodePackages.mermaid-cli
] ++ (if pkgs.system == "x86_64-linux" then with pkgs; [ ] ++ (if pkgs.stdenv.hostPlatform.system == "x86_64-linux" then with pkgs; [
google-chrome google-chrome
pommed_light pommed_light
slack slack

View File

@@ -1,4 +1,4 @@
{ pkgs, config, makeEnable, forEachUser, ... }: { pkgs, config, makeEnable, ... }:
makeEnable config "myModules.electron" false { makeEnable config "myModules.electron" false {
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
element-desktop element-desktop
@@ -8,21 +8,23 @@ makeEnable config "myModules.electron" false {
# keybase-gui # keybase-gui
zoom-us zoom-us
]; ];
home-manager.users = forEachUser (if pkgs.system == "x86_64-linux" then { home-manager.sharedModules = [
# systemd.user.services.bitwarden = { (if pkgs.stdenv.hostPlatform.system == "x86_64-linux" then {
# Unit = { # systemd.user.services.bitwarden = {
# Description = "Bitwarden"; # Unit = {
# After = [ "graphical-session-pre.target" "tray.target" ]; # Description = "Bitwarden";
# PartOf = [ "graphical-session.target" ]; # After = [ "graphical-session-pre.target" "tray.target" ];
# }; # PartOf = [ "graphical-session.target" ];
# };
# Install = { WantedBy = [ "graphical-session.target" ]; }; # Install = { WantedBy = [ "graphical-session.target" ]; };
# Service = { # Service = {
# ExecStart = "${pkgs.bitwarden}/bin/bitwarden"; # ExecStart = "${pkgs.bitwarden}/bin/bitwarden";
# Restart = "always"; # Restart = "always";
# RestartSec = 3; # RestartSec = 3;
# }; # };
# }; # };
} else {}); } else {})
];
} }

View File

@@ -1,7 +1,5 @@
{ config, pkgs, makeEnable, ... }: { config, pkgs, makeEnable, ... }:
makeEnable config "myModules.extra" false { makeEnable config "myModules.extra" false {
programs.hyprland.enable = true;
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
android-studio android-studio
gradle gradle

1312
nixos/flake.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -27,6 +27,26 @@
agenix = {url = "github:ryantm/agenix";}; agenix = {url = "github:ryantm/agenix";};
org-agenda-api = {
url = "github:colonelpanic8/org-agenda-api";
inputs.nixpkgs.follows = "nixpkgs";
};
# Hyprland and plugins from official flakes for proper plugin compatibility
hyprland = {
url = "git+https://github.com/hyprwm/Hyprland?submodules=1&ref=refs/tags/v0.53.0";
};
hy3 = {
url = "github:outfoxxed/hy3?ref=hl0.53.0";
inputs.hyprland.follows = "hyprland";
};
hyprland-plugins = {
url = "github:hyprwm/hyprland-plugins?ref=v0.53.0";
inputs.hyprland.follows = "hyprland";
};
railbird-secrets = { railbird-secrets = {
url = "git+ssh://gitea@dev.railbird.ai:1123/railbird/secrets-flake.git"; url = "git+ssh://gitea@dev.railbird.ai:1123/railbird/secrets-flake.git";
}; };
@@ -110,6 +130,17 @@
nixified-ai = {url = "github:nixified-ai/flake";}; nixified-ai = {url = "github:nixified-ai/flake";};
nixtheplanet.url = "github:matthewcroughan/nixtheplanet"; nixtheplanet.url = "github:matthewcroughan/nixtheplanet";
codex-cli-nix = {
url = "github:sadjow/codex-cli-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
claude-code-nix = {
url = "github:sadjow/claude-code-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
}; };
outputs = inputs @ { outputs = inputs @ {
@@ -125,13 +156,18 @@
nix, nix,
agenix, agenix,
imalison-taffybar, imalison-taffybar,
hyprland,
hy3,
hyprland-plugins,
org-agenda-api,
flake-utils,
... ...
}: let }: let
# Nixpkgs PR patches - just specify PR number and hash # Nixpkgs PR patches - just specify PR number and hash
nixpkgsPRPatches = [ nixpkgsPRPatches = [
{ {
pr = 434160; # git-sync-rs package pr = 434160; # git-sync-rs package
hash = "sha256-zjzjmC1XJmwfHr/YXFyYsqUFR5MHSoxWWyxIR35YNbM="; hash = "sha256-0j0IcyHd7rE+MXc0SHu8UixW7Jbtzu1NnzSjEVeZmTA=";
} }
# claude-code # claude-code
# { # {
@@ -194,7 +230,7 @@
mkConfigurationParams = filename: { mkConfigurationParams = filename: {
name = machineNameFromFilename filename; name = machineNameFromFilename filename;
value = { value = {
modules = [ baseModules = [
(machinesFilepath + ("/" + filename)) (machinesFilepath + ("/" + filename))
agenix.nixosModules.default agenix.nixosModules.default
nixtheplanet.nixosModules.macos-ventura nixtheplanet.nixosModules.macos-ventura
@@ -203,6 +239,24 @@
}; };
defaultConfigurationParams = defaultConfigurationParams =
builtins.listToAttrs (map mkConfigurationParams machineFilenames); builtins.listToAttrs (map mkConfigurationParams machineFilenames);
# Build org-agenda-api container for a given system
mkOrgAgendaApiContainerInfo = system: let
pkgs = import nixpkgs { inherit system; };
orgApiRev = builtins.substring 0 7 (org-agenda-api.rev or "unknown");
dotfilesRev = builtins.substring 0 7 (self.rev or self.dirtyRev or "dirty");
dotfilesOrgApi = import ./org-agenda-api.nix {
inherit pkgs system inputs;
};
tangledConfig = dotfilesOrgApi.org-agenda-custom-config;
containerLib = import ../org-agenda-api/container.nix {
inherit pkgs system tangledConfig org-agenda-api orgApiRev dotfilesRev;
};
tag = "colonelpanic-${orgApiRev}-${dotfilesRev}";
in {
imageFile = containerLib.containers.colonelpanic;
imageName = "org-agenda-api:${tag}";
};
customParams = { customParams = {
biskcomp = { biskcomp = {
system = "aarch64-linux"; system = "aarch64-linux";
@@ -210,6 +264,14 @@
air-gapped-pi = { air-gapped-pi = {
system = "aarch64-linux"; system = "aarch64-linux";
}; };
railbird-sf = {
specialArgs = let
containerInfo = mkOrgAgendaApiContainerInfo "x86_64-linux";
in {
orgAgendaApiContainer = containerInfo.imageFile;
orgAgendaApiImageName = containerInfo.imageName;
};
};
}; };
mkConfig = { mkConfig = {
system ? "x86_64-linux", system ? "x86_64-linux",
@@ -286,8 +348,6 @@
(_: value: (builtins.elem "isNormalUser" (builtins.attrNames value)) && value.isNormalUser) (_: value: (builtins.elem "isNormalUser" (builtins.attrNames value)) && value.isNormalUser)
usersInfo.users.users) usersInfo.users.users)
); );
mapAllKeysToValue = keys: value: builtins.listToAttrs (map (name: {inherit name value;}) keys);
forEachUser = mapAllKeysToValue realUsers;
} }
// specialArgs; // specialArgs;
}; };
@@ -302,10 +362,16 @@
extra-substituters = [ extra-substituters = [
"http://192.168.1.26:5050" "http://192.168.1.26:5050"
"https://cache.flox.dev" "https://cache.flox.dev"
"https://org-agenda-api.cachix.org"
"https://codex-cli.cachix.org"
"https://claude-code.cachix.org"
]; ];
extra-trusted-public-keys = [ extra-trusted-public-keys = [
"1896Folsom.duckdns.org:U2FTjvP95qwAJo0oGpvmUChJCgi5zQoG1YisoI08Qoo=" "1896Folsom.duckdns.org:U2FTjvP95qwAJo0oGpvmUChJCgi5zQoG1YisoI08Qoo="
"flox-cache-public-1:7F4OyH7ZCnFhcze3fJdfyXYLQw/aV7GEed86nQ7IsOs=" "flox-cache-public-1:7F4OyH7ZCnFhcze3fJdfyXYLQw/aV7GEed86nQ7IsOs="
"org-agenda-api.cachix.org-1:liKFemKkOLV/rJt2txDNcpDjRsqLuBneBjkSw/UVXKA="
"codex-cli.cachix.org-1:1Br3H1hHoRYG22n//cGKJOk3cQXgYobUel6O8DgSing="
"claude-code.cachix.org-1:YeXf2aNu7UTX8Vwrze0za1WEDS+4DuI2kVeWEE4fsRk="
]; ];
}; };
nixosConfigurations = nixosConfigurations =
@@ -319,5 +385,55 @@
mkConfig (params // machineParams) mkConfig (params // machineParams)
) )
defaultConfigurationParams; defaultConfigurationParams;
}; } // flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs { inherit system; };
# Get short revs for tagging
orgApiRev = builtins.substring 0 7 (org-agenda-api.rev or "unknown");
dotfilesRev = builtins.substring 0 7 (self.rev or self.dirtyRev or "dirty");
# Get tangled config files from org-agenda-api.nix
dotfilesOrgApi = import ./org-agenda-api.nix {
inherit pkgs system;
inherit inputs;
};
tangledConfig = dotfilesOrgApi.org-agenda-custom-config;
# Import container build logic
containerLib = import ../org-agenda-api/container.nix {
inherit pkgs system tangledConfig org-agenda-api orgApiRev dotfilesRev;
};
in {
packages = {
colonelpanic-org-agenda-api = containerLib.containers.colonelpanic;
kat-org-agenda-api = containerLib.containers.kat;
};
# Dev shell for org-agenda-api deployment
devShells.org-agenda-api = pkgs.mkShell {
buildInputs = [
pkgs.flyctl
agenix.packages.${system}.default
pkgs.age
pkgs.ssh-to-age
pkgs.git
pkgs.jq
pkgs.just
pkgs.curl
];
shellHook = ''
echo ""
echo "org-agenda-api deployment shell"
echo ""
echo "Commands:"
echo " just --list - Show available API commands"
echo " ./deploy.sh <instance> - Deploy to Fly.io (colonelpanic or kat)"
echo " flyctl - Fly.io CLI"
echo " agenix -e <file> - Edit encrypted secrets"
echo ""
'';
};
}
);
} }

View File

@@ -14,6 +14,8 @@ makeEnable config "myModules.gitea-runner" false {
}; };
container = { container = {
workdir_parent = "${gitea-runner-directory}/workspace"; workdir_parent = "${gitea-runner-directory}/workspace";
# Increase shared memory for containers (default 64MB is too small for Metro/Gradle)
options = "--shm-size=2g";
}; };
host = { host = {
workdir_parent = "${gitea-runner-directory}/action-cache-dir"; workdir_parent = "${gitea-runner-directory}/action-cache-dir";
@@ -40,7 +42,7 @@ makeEnable config "myModules.gitea-runner" false {
url = "https://dev.railbird.ai"; url = "https://dev.railbird.ai";
tokenFile = config.age.secrets.gitea-runner-token.path; tokenFile = config.age.secrets.gitea-runner-token.path;
labels = [ labels = [
"nixos-${pkgs.system}:host" "nixos-${pkgs.stdenv.hostPlatform.system}:host"
"nix:docker://localhost:5921/nix-runner" "nix:docker://localhost:5921/nix-runner"
]; ];
}; };

View File

@@ -1,5 +1,25 @@
{ pkgs, ... }: { pkgs, ... }:
{ {
# Automatic garbage collection of old home-manager generations
nix.gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 7d";
};
xdg.configFile."greenclip.toml".text = ''
[greenclip]
history_file = "~/.cache/greenclip.history"
max_history_length = 50
max_selection_size_bytes = 0
trim_space_from_selection = true
use_primary_selection_as_input = false
blacklisted_applications = []
enable_image_support = true
image_cache_directory = "~/.cache/greenclip"
static_history = []
'';
xsession = { xsession = {
enable = true; enable = true;
preferStatusNotifierItems = true; preferStatusNotifierItems = true;
@@ -40,22 +60,6 @@
''; '';
}; };
systemd.user.services.setxkbmap = {
Unit = {
Description = "Set up keyboard in X";
After = [ "graphical-session-pre.target" ];
PartOf = [ "graphical-session.target" ];
};
Install = { WantedBy = [ "graphical-session.target" ]; };
Service = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = "/usr/bin/env load_xkb_map";
};
};
gtk = { gtk = {
enable = true; enable = true;
iconTheme = { iconTheme = {

58
nixos/hyprland.nix Normal file
View File

@@ -0,0 +1,58 @@
{ config, pkgs, lib, makeEnable, inputs, ... }:
makeEnable config "myModules.hyprland" true {
programs.hyprland = {
enable = true;
# Use Hyprland from the flake for proper plugin compatibility
package = inputs.hyprland.packages.${pkgs.stdenv.hostPlatform.system}.hyprland;
# Let UWSM manage the Hyprland session targets
withUWSM = true;
};
home-manager.sharedModules = [
{
programs.waybar.enable = true;
systemd.user.services.waybar = {
Unit = {
Description = "Waybar";
PartOf = [ "wayland-session@Hyprland.target" ];
After = [ "wayland-session@Hyprland.target" ];
};
Service = {
ExecStartPre = "${pkgs.bash}/bin/bash -lc 'uid=$(id -u); for i in $(seq 1 50); do runtime_dir=\"$XDG_RUNTIME_DIR\"; if [ -z \"$runtime_dir\" ]; then runtime_dir=\"/run/user/$uid\"; fi; if [ -n \"$WAYLAND_DISPLAY\" ] && [ -S \"$runtime_dir/$WAYLAND_DISPLAY\" ]; then exit 0; fi; sleep 0.1; done; exit 1'";
ExecStart = "${pkgs.waybar}/bin/waybar";
Restart = "always";
RestartSec = 1;
};
Install = {
WantedBy = [ "wayland-session@Hyprland.target" ];
};
};
}
];
# Hyprland-specific packages
environment.systemPackages = with pkgs; [
# Hyprland utilities
hyprpaper # Wallpaper
hypridle # Idle daemon
hyprlock # Screen locker
hyprcursor # Cursor themes
wl-clipboard # Clipboard for Wayland
wtype # Wayland input typing
cliphist # Clipboard history
grim # Screenshot utility
slurp # Region selection
swappy # Screenshot annotation
wlsunset # Night light / blue light filter
# hy3 plugin from flake (properly built against matching Hyprland)
inputs.hy3.packages.${pkgs.stdenv.hostPlatform.system}.hy3
# Hyprexpo plugin from hyprland-plugins (workspace overview)
inputs.hyprland-plugins.packages.${pkgs.stdenv.hostPlatform.system}.hyprexpo
# For scripts
jq
];
}

View File

@@ -3,12 +3,3 @@ switch *args:
fix-local-path-issue: fix-local-path-issue:
nix flake update imalison-taffybar nix flake update imalison-taffybar
expire-home-manager-generations:
#!/usr/bin/env bash
set -euxo pipefail
for user in $(awk -F':' '{ if ($3 >= 1000 && $7 !~ /nologin|false|sync|shutdown|halt/) print $1 }' /etc/passwd); do
echo $user
sudo su - $user -c 'home-manager expire-generations -1days'
done

View File

@@ -1,5 +1,5 @@
{ forEachUser, ... }: { { ... }: {
home-manager.users = forEachUser { home-manager.sharedModules = [
services.kbfs.enable = true; { services.kbfs.enable = true; }
}; ];
} }

39
nixos/keyd.nix Normal file
View File

@@ -0,0 +1,39 @@
{ config, lib, makeEnable, ... }:
makeEnable config "myModules.keyd" true {
services.keyd = {
enable = true;
# Base remap applied to all keyboards.
keyboards.default = {
# Exclude the Glove80 (MoErgo) by vendor:product ID.
ids = [ "*" "-16c0:27db" ];
settings = {
main = {
# Caps Lock -> Control
capslock = "leftcontrol";
# Swap Left Alt and Left Super
leftalt = "leftmeta";
leftmeta = "leftalt";
# Right Alt -> Hyper chord
rightalt = "layer(hyper)";
};
# Hyper = Ctrl+Alt+Meta while held (matches $hyper = SUPER CTRL ALT)
"hyper:C-A-M" = { };
};
};
# TODO: Add per-keyboard overrides here once device IDs are known.
# Example:
# keyboards.externalKinesis = {
# ids = [ "1ea7:0907" ];
# settings = {
# main = {
# leftalt = "leftmeta";
# leftmeta = "leftalt";
# rightalt = "layer(hyper)";
# };
# "hyper:C-A-M-S" = { };
# };
# };
};
}

View File

@@ -1,4 +1,4 @@
{ lib, pkgs, inputs, forEachUser, ... }: { lib, pkgs, inputs, ... }:
{ {
imports = [ imports = [
@@ -71,9 +71,11 @@
powerManagement.cpuFreqGovernor = lib.mkDefault "performance"; powerManagement.cpuFreqGovernor = lib.mkDefault "performance";
home-manager.users = forEachUser { home-manager.sharedModules = [
home.stateVersion = "23.05"; {
}; home.stateVersion = "23.05";
}
];
system.stateVersion = "23.05"; system.stateVersion = "23.05";
} }

View File

@@ -1,4 +1,4 @@
{ lib, pkgs, config, inputs, forEachUser, ... }: { lib, pkgs, config, inputs, ... }:
{ {
imports = [ imports = [
../configuration.nix ../configuration.nix
@@ -18,9 +18,11 @@
wsl.defaultUser = "ben"; wsl.defaultUser = "ben";
system.stateVersion = "22.05"; system.stateVersion = "22.05";
home-manager.users = forEachUser { home-manager.sharedModules = [
home.stateVersion = "22.05"; {
}; home.stateVersion = "22.05";
}
];
users.users.ben = { users.users.ben = {
extraGroups = [ extraGroups = [

View File

@@ -1,4 +1,4 @@
{ pkgs, lib, forEachUser, config, ... }: { pkgs, lib, config, ... }:
let biskcomp-nginx-hostnames = "192.168.1.44 railbird.ai 1896Folsom.duckdns.org biskcomp.local 0.0.0.0 67.162.131.71"; let biskcomp-nginx-hostnames = "192.168.1.44 railbird.ai 1896Folsom.duckdns.org biskcomp.local 0.0.0.0 67.162.131.71";
in in
{ {
@@ -100,41 +100,12 @@ in
database.ignorePostgresqlVersion = true; database.ignorePostgresqlVersion = true;
}; };
systemd.services.emacs-org-api = {
description = "Emacs org api";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = ''${pkgs.runtimeShell} -l -c "${lib.getExe' pkgs.emacs "emacs"} --load /home/imalison/.emacs.d/org-api.el --daemon=org-api"'';
RemainAfterExit = true;
Restart = "on-failure";
User = "imalison";
};
};
age.secrets.org-api-passwords = {
file = ../secrets/org-api-passwords.age;
owner = "nginx";
};
services.nginx = { services.nginx = {
enable = true; enable = true;
recommendedProxySettings = true; recommendedProxySettings = true;
recommendedGzipSettings = true; recommendedGzipSettings = true;
recommendedTlsSettings = true; recommendedTlsSettings = true;
virtualHosts = { virtualHosts = {
"org-mode.1896Folsom.duckdns.org" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://localhost:2025";
basicAuthFile = config.age.secrets.org-api-passwords.path;
extraConfig = ''
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'POST, PUT, DELETE, GET, PATCH, OPTIONS' always;
'';
};
};
"gitlab.railbird.ai" = { "gitlab.railbird.ai" = {
enableACME = true; enableACME = true;
forceSSL = true; forceSSL = true;
@@ -186,7 +157,9 @@ in
networking.hostName = "biskcomp"; networking.hostName = "biskcomp";
system.stateVersion = "23.11"; system.stateVersion = "23.11";
home-manager.users = forEachUser { home-manager.sharedModules = [
home.stateVersion = "23.11"; {
}; home.stateVersion = "23.11";
}
];
} }

View File

@@ -1,4 +1,4 @@
{ config, lib, pkgs, forEachUser, ... }: { config, lib, pkgs, ... }:
{ {
imports = [ imports = [
@@ -53,9 +53,11 @@
networking.hostName = "david-blade"; networking.hostName = "david-blade";
home-manager.users = forEachUser { home-manager.sharedModules = [
home.stateVersion = "24.05"; {
}; home.stateVersion = "24.05";
}
];
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
system.stateVersion = "24.05"; system.stateVersion = "24.05";

View File

@@ -1,4 +1,4 @@
{ lib, pkgs, config, inputs, forEachUser, ... }: { lib, pkgs, config, inputs, ... }:
{ {
imports = [ imports = [
../configuration.nix ../configuration.nix
@@ -15,7 +15,9 @@
wsl.defaultUser = "dean"; wsl.defaultUser = "dean";
system.stateVersion = "22.05"; system.stateVersion = "22.05";
home-manager.users = forEachUser { home-manager.sharedModules = [
home.stateVersion = "22.05"; {
}; home.stateVersion = "22.05";
}
];
} }

View File

@@ -1,4 +1,4 @@
{ lib, pkgs, config, inputs, forEachUser, ... }: { lib, pkgs, config, inputs, ... }:
{ {
imports = [ imports = [
../configuration.nix ../configuration.nix
@@ -12,7 +12,9 @@
wsl.defaultUser = "kat"; wsl.defaultUser = "kat";
system.stateVersion = "22.05"; system.stateVersion = "22.05";
home-manager.users = forEachUser { home-manager.sharedModules = [
home.stateVersion = "22.05"; {
}; home.stateVersion = "22.05";
}
];
} }

View File

@@ -1,4 +1,4 @@
{ config, lib, pkgs, forEachUser, ... }: { config, lib, pkgs, ... }:
{ {
imports = [ imports = [
@@ -55,7 +55,9 @@
system.stateVersion = "23.05"; system.stateVersion = "23.05";
home-manager.users = forEachUser { home-manager.sharedModules = [
home.stateVersion = "23.05"; {
}; home.stateVersion = "23.05";
}
];
} }

View File

@@ -1,4 +1,4 @@
{ config, lib, pkgs, forEachUser, ... }: { config, lib, pkgs, ... }:
{ {
imports = [ imports = [
@@ -106,9 +106,11 @@
{ device = "/dev/disk/by-uuid/598e9aa1-4940-4410-a2fa-3dfd8b7d2c0d"; } { device = "/dev/disk/by-uuid/598e9aa1-4940-4410-a2fa-3dfd8b7d2c0d"; }
]; ];
home-manager.users = forEachUser { home-manager.sharedModules = [
home.stateVersion = "23.11"; {
}; home.stateVersion = "23.11";
}
];
networking.hostName = "jimi-hendnix"; networking.hostName = "jimi-hendnix";

View File

@@ -1,4 +1,4 @@
{ config, lib, pkgs, forEachUser, ... }: { config, lib, pkgs, ... }:
{ {
imports = [ imports = [
@@ -201,7 +201,9 @@
system.stateVersion = "23.05"; system.stateVersion = "23.05";
home-manager.users = forEachUser { home-manager.sharedModules = [
home.stateVersion = "23.05"; {
}; home.stateVersion = "23.05";
}
];
} }

View File

@@ -1,4 +1,4 @@
{ config, lib, pkgs, inputs, forEachUser, ... }: { config, lib, pkgs, inputs, ... }:
{ {
imports = [ imports = [
../configuration.nix ../configuration.nix
@@ -62,9 +62,11 @@
services.xrdp.defaultWindowManager = "startplasma-x11"; services.xrdp.defaultWindowManager = "startplasma-x11";
services.xrdp.openFirewall = true; services.xrdp.openFirewall = true;
home-manager.users = forEachUser { home-manager.sharedModules = [
home.stateVersion = "23.11"; {
}; home.stateVersion = "23.11";
}
];
system.stateVersion = "23.11"; system.stateVersion = "23.11";
} }

View File

@@ -1,11 +1,32 @@
{ config, lib, pkgs, forEachUser, ... }: { config, lib, pkgs, inputs, orgAgendaApiContainer ? null, orgAgendaApiImageName ? "org-agenda-api", ... }:
{ {
imports = [ imports = [
../configuration.nix ../configuration.nix
inputs.agenix.nixosModules.default
]; ];
networking.hostName = "railbird-sf"; networking.hostName = "railbird-sf";
# org-agenda-api hosting with nginx + Let's Encrypt
# Separate secrets for org-agenda-api: auth password (env format) and SSH key (raw file)
age.secrets.org-api-auth-password = {
file = ../secrets/org-api-auth-password.age;
};
age.secrets.org-api-ssh-key = {
file = ../secrets/org-api-ssh-key.age;
mode = "0400"; # Restrictive permissions for SSH key
};
services.org-agenda-api-host = {
enable = true;
domain = "rbsf.tplinkdns.com";
extraDomains = [ "org-agenda-api.rbsf.railbird.ai" ];
containerImage = orgAgendaApiImageName;
containerImageFile = orgAgendaApiContainer;
secretsFile = config.age.secrets.org-api-auth-password.path;
sshKeyFile = config.age.secrets.org-api-ssh-key.path;
};
hardware.enableRedistributableFirmware = true; hardware.enableRedistributableFirmware = true;
boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ]; boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ];
boot.initrd.kernelModules = [ ]; boot.initrd.kernelModules = [ ];
@@ -65,9 +86,11 @@
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
home-manager.users = forEachUser { home-manager.sharedModules = [
home.stateVersion = "23.11"; {
}; home.stateVersion = "23.11";
}
];
system.stateVersion = "23.11"; system.stateVersion = "23.11";
} }

View File

@@ -1,4 +1,4 @@
{ lib, pkgs, forEachUser, ... }: { lib, pkgs, ... }:
{ {
imports = [ imports = [
@@ -93,9 +93,11 @@
# services.xrdp.openFirewall = true; # services.xrdp.openFirewall = true;
system.stateVersion = "20.03"; system.stateVersion = "20.03";
home-manager.users = forEachUser { home-manager.sharedModules = [
home.stateVersion = "21.05"; {
}; home.stateVersion = "21.05";
}
];
# users.extraUsers.dean.home = "/shared/dean"; # users.extraUsers.dean.home = "/shared/dean";
} }

View File

@@ -1,4 +1,4 @@
{ lib, pkgs, config, inputs, forEachUser, ... }: { lib, pkgs, config, inputs, ... }:
{ {
imports = [ imports = [
../configuration.nix ../configuration.nix
@@ -18,7 +18,9 @@
wsl.defaultUser = "imalison"; wsl.defaultUser = "imalison";
system.stateVersion = "22.05"; system.stateVersion = "22.05";
home-manager.users = forEachUser { home-manager.sharedModules = [
home.stateVersion = "22.05"; {
}; home.stateVersion = "22.05";
}
];
} }

View File

@@ -1,4 +1,4 @@
{ lib, pkgs, forEachUser, ... }: { lib, pkgs, ... }:
{ {
imports = [ imports = [
@@ -83,9 +83,11 @@
# services.xrdp.openFirewall = true; # services.xrdp.openFirewall = true;
system.stateVersion = "20.03"; system.stateVersion = "20.03";
home-manager.users = forEachUser { home-manager.sharedModules = [
home.stateVersion = "21.05"; {
}; home.stateVersion = "21.05";
}
];
# users.extraUsers.dean.home = "/shared/dean"; # users.extraUsers.dean.home = "/shared/dean";
} }

View File

@@ -1,4 +1,4 @@
{ lib, pkgs, config, inputs, forEachUser, ... }: { lib, pkgs, config, inputs, ... }:
{ {
imports = [ imports = [
../configuration.nix ../configuration.nix
@@ -11,9 +11,11 @@
wsl.defaultUser = "imalison"; wsl.defaultUser = "imalison";
system.stateVersion = "23.11"; # Did you read the comment? system.stateVersion = "23.11"; # Did you read the comment?
home-manager.users = forEachUser { home-manager.sharedModules = [
home.stateVersion = "23.11"; {
}; home.stateVersion = "23.11";
}
];
programs.gnupg = { programs.gnupg = {
agent = { agent = {

View File

@@ -1,4 +1,4 @@
{ config, lib, pkgs, inputs, forEachUser, ... }: { config, lib, pkgs, inputs, ... }:
{ {
imports = [ imports = [
@@ -28,6 +28,8 @@
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
android-studio android-studio
gimp
inkscape
]; ];
services.synergy.server = { services.synergy.server = {
@@ -55,6 +57,8 @@
boot.kernelModules = [ "kvm-intel" ]; boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ]; boot.extraModulePackages = [ ];
hardware.nvidia.powerManagement.enable = true; hardware.nvidia.powerManagement.enable = true;
hardware.nvidia.prime.offload.enable = lib.mkForce false;
hardware.nvidia.prime.sync.enable = lib.mkForce true;
boot.loader.systemd-boot.enable = true; boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true; boot.loader.efi.canTouchEfiVariables = true;
@@ -72,6 +76,7 @@
swapDevices = [ swapDevices = [
{ device = "/dev/disk/by-uuid/27f277a0-b552-43a0-904d-625e48922bb9"; } { device = "/dev/disk/by-uuid/27f277a0-b552-43a0-904d-625e48922bb9"; }
{ device = "/swapfile"; size = 16384; } # size is in MiB (adds 16 GiB)
]; ];
networking.hostName = "strixi-minaj"; networking.hostName = "strixi-minaj";
@@ -79,9 +84,15 @@
powerManagement.cpuFreqGovernor = lib.mkDefault "performance"; powerManagement.cpuFreqGovernor = lib.mkDefault "performance";
hardware.cpu.intel.updateMicrocode = lib.mkDefault true; hardware.cpu.intel.updateMicrocode = lib.mkDefault true;
home-manager.users = forEachUser { home-manager.sharedModules = [
home.stateVersion = "23.05"; {
}; home.stateVersion = "23.05";
xdg.configFile."waybar/disks".text = ''
# One mountpoint per line (comments with # are ignored).
/
'';
}
];
system.stateVersion = "23.05"; system.stateVersion = "23.05";
} }

View File

@@ -1,4 +1,4 @@
{ inputs, specialArgs, config, lib, ... }: { inputs, specialArgs, config, lib, realUsers, ... }:
{ {
imports = [ imports = [
inputs.home-manager.nixosModules.home-manager inputs.home-manager.nixosModules.home-manager
@@ -11,6 +11,7 @@
}; };
}; };
config = { config = {
home-manager.users = lib.genAttrs realUsers (_: {});
home-manager.extraSpecialArgs = { home-manager.extraSpecialArgs = {
nixos = { nixos = {
inherit specialArgs config; inherit specialArgs config;
@@ -19,6 +20,7 @@
home-manager.useGlobalPkgs = true; home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true; home-manager.useUserPackages = true;
home-manager.backupFileExtension = "backup"; home-manager.backupFileExtension = "backup";
home-manager.sharedModules = [ ./home-manager.nix ];
nix = rec { nix = rec {
extraOptions = '' extraOptions = ''
@@ -32,11 +34,15 @@
"https://cache.nixos.org" "https://cache.nixos.org"
"https://cuda-maintainers.cachix.org" "https://cuda-maintainers.cachix.org"
"https://ai.cachix.org" "https://ai.cachix.org"
"https://codex-cli.cachix.org"
"https://claude-code.cachix.org"
]; ];
trusted-public-keys = [ trusted-public-keys = [
"cache.railbird.ai:KhnvcouxtIU2zxUcjJsm4bUK3o1S3p8xMf9qfZGF7/A=" "cache.railbird.ai:KhnvcouxtIU2zxUcjJsm4bUK3o1S3p8xMf9qfZGF7/A="
"cuda-maintainers.cachix.org-1:0dq3bujKpuEPMCX6U4WylrUDZ9JyUG0VpVZa7CNfq5E=" "cuda-maintainers.cachix.org-1:0dq3bujKpuEPMCX6U4WylrUDZ9JyUG0VpVZa7CNfq5E="
"ai.cachix.org-1:N9dzRK+alWwoKXQlnn0H6aUx0lU/mspIoz8hMvGvbbc=" "ai.cachix.org-1:N9dzRK+alWwoKXQlnn0H6aUx0lU/mspIoz8hMvGvbbc="
"codex-cli.cachix.org-1:1Br3H1hHoRYG22n//cGKJOk3cQXgYobUel6O8DgSing="
"claude-code.cachix.org-1:YeXf2aNu7UTX8Vwrze0za1WEDS+4DuI2kVeWEE4fsRk="
]; ];
nix-path = nixPath; nix-path = nixPath;
}; };
@@ -50,6 +56,11 @@
# (import ./nvidia-container-toolkit-overlay.nix) # (import ./nvidia-container-toolkit-overlay.nix)
(import ./runc-overlay.nix) (import ./runc-overlay.nix)
(import ./overlay.nix) (import ./overlay.nix)
# Use codex and claude-code from dedicated flakes with cachix
(final: prev: {
codex = inputs.codex-cli-nix.packages.${prev.stdenv.hostPlatform.system}.default;
claude-code = inputs.claude-code-nix.packages.${prev.stdenv.hostPlatform.system}.default;
})
] ++ (if config.imalison.nixOverlay.enable then [ inputs.nix.overlays.default ] else []); ] ++ (if config.imalison.nixOverlay.enable then [ inputs.nix.overlays.default ] else []);
# Allow all the things # Allow all the things

View File

@@ -0,0 +1,159 @@
# org-agenda-api-host.nix - Host org-agenda-api container with nginx + Let's Encrypt
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.org-agenda-api-host;
# Random high port to avoid conflicts
containerPort = 51847;
in
{
options.services.org-agenda-api-host = {
enable = mkEnableOption "org-agenda-api container hosting";
domain = mkOption {
type = types.str;
default = "rbsf.tplinkdns.com";
description = "Base domain name (service will be at org-agenda-api.<domain>)";
};
extraDomains = mkOption {
type = types.listOf types.str;
default = [];
description = "Additional full domain names to serve (each gets its own ACME cert)";
example = [ "org-agenda-api.example.com" ];
};
acmeEmail = mkOption {
type = types.str;
default = "IvanMalison@gmail.com";
description = "Email for Let's Encrypt certificate notifications";
};
containerImageFile = mkOption {
type = types.nullOr types.path;
default = null;
description = "Nix-built container image (tarball from dockerTools)";
};
containerImage = mkOption {
type = types.str;
default = "colonelpanic-org-agenda-api";
description = "Container image name (used when imageFile is provided)";
};
gitSyncRepository = mkOption {
type = types.str;
default = "git@github.com:colonelpanic8/org.git";
description = "Git repository to sync org files from";
};
gitUserEmail = mkOption {
type = types.str;
default = "IvanMalison@gmail.com";
description = "Git user email for commits";
};
gitUserName = mkOption {
type = types.str;
default = "Ivan Malison";
description = "Git user name for commits";
};
authUser = mkOption {
type = types.str;
default = "imalison";
description = "Basic auth username";
};
secretsFile = mkOption {
type = types.path;
description = "Path to agenix-decrypted secrets file containing AUTH_PASSWORD";
};
sshKeyFile = mkOption {
type = types.nullOr types.path;
default = null;
description = "Path to agenix-decrypted SSH private key file (mounted at /secrets/ssh_key in container)";
};
timezone = mkOption {
type = types.str;
default = "America/Los_Angeles";
description = "Timezone for the container";
};
};
config = mkIf cfg.enable {
# Enable ACME for Let's Encrypt
security.acme = {
acceptTerms = true;
defaults.email = cfg.acmeEmail;
};
# Nginx reverse proxy with TLS
services.nginx = {
enable = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
recommendedOptimisation = true;
recommendedGzipSettings = true;
virtualHosts = let
mkVirtualHost = domain: {
name = domain;
value = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString containerPort}";
proxyWebsockets = true;
extraConfig = ''
proxy_read_timeout 300s;
proxy_connect_timeout 75s;
'';
};
};
};
allDomains = [ "org-agenda-api.${cfg.domain}" ] ++ cfg.extraDomains;
in builtins.listToAttrs (map mkVirtualHost allDomains);
};
# Open firewall for HTTP/HTTPS
networking.firewall.allowedTCPPorts = [ 80 443 ];
# Container service using podman
virtualisation.oci-containers = {
backend = "podman";
containers.org-agenda-api = {
image = cfg.containerImage;
imageFile = cfg.containerImageFile;
autoStart = true;
ports = [ "127.0.0.1:${toString containerPort}:80" ];
environment = {
TZ = cfg.timezone;
GIT_SYNC_REPOSITORY = cfg.gitSyncRepository;
GIT_USER_EMAIL = cfg.gitUserEmail;
GIT_USER_NAME = cfg.gitUserName;
AUTH_USER = cfg.authUser;
};
environmentFiles = [ cfg.secretsFile ];
volumes = lib.optionals (cfg.sshKeyFile != null) [
"${cfg.sshKeyFile}:/secrets/ssh_key:ro"
];
extraOptions = [
"--pull=never" # Image is from nix store, don't try to pull
];
};
};
# Ensure container restarts on failure
systemd.services.podman-org-agenda-api = {
serviceConfig = {
Restart = "always";
RestartSec = "10s";
};
};
};
}

34
nixos/org-agenda-api.nix Normal file
View File

@@ -0,0 +1,34 @@
# org-agenda-api.nix - Tangled org-config for org-agenda-api container
{ pkgs, inputs, system }:
let
# Path to org-config.org in the dotfiles
orgConfigOrg = ../dotfiles/emacs.d/org-config.org;
# Tangle org-config.org to produce elisp files
orgAgendaCustomConfig = pkgs.runCommand "org-agenda-custom-config" {
buildInputs = [ pkgs.emacs-nox ];
} ''
mkdir -p $out
mkdir -p work
# Copy org file to writable location (tangle writes to same directory)
cp ${orgConfigOrg} work/org-config.org
# Tangle org-config.org
emacs --batch \
--eval '(require (quote org))' \
--eval '(org-babel-tangle-file "work/org-config.org")'
# Copy all tangled files to output, stripping :straight keywords
# (straight.el is not available in the minimal container Emacs)
for f in work/org-config-*.el; do
if [ -f "$f" ]; then
# Remove :straight nil and :straight t from use-package declarations
sed -e 's/:straight nil//g' -e 's/:straight t//g' "$f" > "$out/$(basename "$f")"
fi
done
'';
in {
org-agenda-custom-config = orgAgendaCustomConfig;
}

View File

@@ -1,20 +1,74 @@
final: prev: final: prev:
let let
# Claude Code version override - update these values to bump the version # XXX: codex and claude-code are now provided by dedicated flakes in nix.nix:
claudeCodeVersion = { # - inputs.codex-cli-nix (github:sadjow/codex-cli-nix)
version = "2.0.67"; # - inputs.claude-code-nix (github:sadjow/claude-code-nix)
hash = "sha256-HwT9YfoX44b18Sr1VdXMo0X7nIBrai1AAGPbV9l0zv8="; # These use cachix caches for pre-built binaries.
npmDepsHash = "sha256-DNdRkN/rpCsN8fnZbz18r2KRUTl5HCur+GyrofH+T/Y="; # The old manual version override code is preserved below for reference.
};
# # Enable/disable version overrides (set to false to use nixpkgs versions)
# enableCodexOverride = true; # Override to get 0.93.0
# enableClaudeCodeOverride = false; # Disabled - needs proper buildNpmPackage override
# # Codex version override - update these values to bump the version
# codexVersion = {
# version = "0.93.0";
# hash = "sha256-JwCwFPa4+BAMUSp567s9l2QdanL7XEhtGSR8mvlws6Q=";
# # Using importCargoLock requires outputHashes for git dependencies
# outputHashes = {
# "crossterm-0.28.1" = "sha256-6qCtfSMuXACKFb9ATID39XyFDIEMFDmbx6SSmNe+728=";
# "nucleo-0.5.0" = "sha256-Hm4SxtTSBrcWpXrtSqeO0TACbUxq3gizg1zD/6Yw/sI=";
# "nucleo-matcher-0.3.1" = "sha256-Hm4SxtTSBrcWpXrtSqeO0TACbUxq3gizg1zD/6Yw/sI=";
# "ratatui-0.29.0" = "sha256-HBvT5c8GsiCxMffNjJGLmHnvG77A6cqEL+1ARurBXho=";
# "runfiles-0.1.0" = "sha256-uJpVLcQh8wWZA3GPv9D8Nt43EOirajfDJ7eq/FB+tek=";
# "tokio-tungstenite-0.28.0" = "sha256-vJZ3S41gHtRt4UAODsjAoSCaTksgzCALiBmbWgyDCi8=";
# "tungstenite-0.28.0" = "sha256-CyXZp58zGlUhEor7WItjQoS499IoSP55uWqr++ia+0A=";
# };
# };
# claudeCodeVersion = {
# version = "2.1.22";
# hash = "sha256-OqvLiwB5TwZaxDvyN/+/+eueBdWNaYxd81cd5AZK/mA=";
# npmDepsHash = "sha256-vy7osk3UAOEgsJx9jdcGe2wICOk5Urzxh1WLAHyHM+U=";
# };
placeholder = null; # Dummy binding to keep let block valid
in in
{ {
# claude-code = prev.claude-code.overrideAttrs (oldAttrs: { # Fix poetry pbs-installer version constraint issue
poetry = prev.poetry.overrideAttrs (oldAttrs: {
dontCheckRuntimeDeps = true;
});
# XXX: codex and claude-code are now provided by flakes in nix.nix
# See the overlay at the end of nixpkgs.overlays in nix.nix
# # XXX: Don't remove this code - use enableCodexOverride flag instead.
# # nixpkgs often lags behind and codex moves extremely quickly
# codex = if enableCodexOverride then prev.codex.overrideAttrs (oldAttrs: rec {
# inherit (codexVersion) version;
# src = prev.fetchFromGitHub {
# owner = "openai";
# repo = "codex";
# tag = "rust-v${codexVersion.version}";
# inherit (codexVersion) hash;
# };
# # Use importCargoLock instead of fetchCargoVendor to avoid workspace parsing issues
# cargoDeps = prev.rustPlatform.importCargoLock {
# lockFile = "${src}/codex-rs/Cargo.lock";
# outputHashes = codexVersion.outputHashes or {};
# };
# cargoHash = null; # Not used with importCargoLock
# }) else prev.codex;
# # XXX: Don't remove this code - use enableClaudeCodeOverride flag instead.
# # nixpkgs often lags behind and claude-code moves extremely quickly
# claude-code = if enableClaudeCodeOverride then prev.claude-code.overrideAttrs (oldAttrs: {
# inherit (claudeCodeVersion) version npmDepsHash; # inherit (claudeCodeVersion) version npmDepsHash;
# src = prev.fetchurl { # src = prev.fetchurl {
# url = "https://registry.npmjs.org/@anthropic-ai/claude-code/-/claude-code-${claudeCodeVersion.version}.tgz"; # url = "https://registry.npmjs.org/@anthropic-ai/claude-code/-/claude-code-${claudeCodeVersion.version}.tgz";
# inherit (claudeCodeVersion) hash; # inherit (claudeCodeVersion) hash;
# }; # };
# }); # }) else prev.claude-code;
# nvidia-container-toolkit = prev.nvidia-container-toolkit.overrideAttrs(old: { # nvidia-container-toolkit = prev.nvidia-container-toolkit.overrideAttrs(old: {
# postInstall = '' # postInstall = ''
# ${old.postInstall or ""} # ${old.postInstall or ""}
@@ -78,6 +132,10 @@ in
meta = prev.runc.meta // {}; meta = prev.runc.meta // {};
}; };
synergy = prev.synergy.overrideAttrs (old: {
patches = (old.patches or []) ++ [ ./synergy-cstdint.patch ];
});
rofi-systemd = prev.rofi-systemd.overrideAttrs (_: { rofi-systemd = prev.rofi-systemd.overrideAttrs (_: {
src = prev.fetchFromGitHub { src = prev.fetchFromGitHub {
repo = "rofi-systemd"; repo = "rofi-systemd";
@@ -87,6 +145,42 @@ in
}; };
}); });
rofi-pass = prev.rofi-pass.overrideAttrs (_: {
version = "git-0fb508a";
src = prev.fetchFromGitHub {
owner = "colonelpanic8";
repo = "rofi-pass";
rev = "0fb508a93ab5f653b63d68ce569e79c8bb27e87b";
sha256 = "sha256-49kdaqCp6O4RrZMbAKYJKDJaAzHBUqYZT2O7OjtQ8W0=";
};
fixupPhase = ''
runHook preFixup
patchShebangs $out/bin
wrapProgram $out/bin/rofi-pass \
--prefix PATH : "${prev.lib.makeBinPath [
prev.coreutils
prev.findutils
prev.gawk
prev.gnugrep
prev.gnused
prev.libnotify
prev.pwgen
prev.rofi
prev."util-linuxMinimal"
(prev.pass.withExtensions (ext: [ ext.pass-otp ]))
prev.xclip
prev.xdotool
(prev."pass-wayland".withExtensions (ext: [ ext.pass-otp ]))
prev."wl-clipboard"
prev.wtype
]}"
runHook postFixup
'';
});
wyoming-satellite = prev.wyoming-satellite.overridePythonAttrs (oldAttrs: { wyoming-satellite = prev.wyoming-satellite.overridePythonAttrs (oldAttrs: {
src = prev.fetchFromGitHub { src = prev.fetchFromGitHub {
owner = "colonelpanic8"; owner = "colonelpanic8";
@@ -110,16 +204,17 @@ in
}; };
}); });
# Using mainline picom with spring physics + animation fixes
# Branch: my-picom on colonelpanic8/picom
# Includes: spring physics curve, adaptive settling threshold, position detection fix
picom = prev.picom.overrideAttrs (old: { picom = prev.picom.overrideAttrs (old: {
version = "13";
src = prev.fetchFromGitHub { src = prev.fetchFromGitHub {
repo = "picom"; repo = "picom";
owner = "dccsillag"; owner = "colonelpanic8";
rev = "51b21355696add83f39ccdb8dd82ff5009ba0ae5"; rev = "my-picom";
sha256 = "sha256-crCwRJd859DCIC0pEerpDqdX2j8ZrNAzVaSSB3mTPN8=="; sha256 = "sha256-XeciIK5q6WE9wirWEHdevfGiNzRANudFcRcRhouWTFE=";
}; };
nativeBuildInputs = old.nativeBuildInputs ++ [final.pcre final.gnugrep.pcre2 final.asciidoc];
buildInputs = old.buildInputs ++ [final.pcre];
nativeInstallCheckInputs = [];
doCheck = false; doCheck = false;
dontCheck = true; dontCheck = true;
}); });
@@ -131,6 +226,13 @@ in
}; };
}); });
# Local Waybar for workspace taskbar support.
waybar = prev.waybar.overrideAttrs (old: {
src = final.lib.cleanSource /home/imalison/Projects/waybar;
version = old.version;
mesonFlags = (old.mesonFlags or []) ++ [ "-Dcava=disabled" ];
});
gnupg_2_4_0 = prev.gnupg.overrideAttrs (_: rec { gnupg_2_4_0 = prev.gnupg.overrideAttrs (_: rec {
pname = "gnupg"; pname = "gnupg";
# 2.4.1 breaks emacs # 2.4.1 breaks emacs
@@ -141,7 +243,7 @@ in
}; };
}); });
emacs = prev.emacs30.override { emacs = prev."emacs30-pgtk".override {
withNativeCompilation = true; withNativeCompilation = true;
withTreeSitter = true; withTreeSitter = true;
}; };

View File

@@ -3,7 +3,7 @@
imports = [ inputs.agenix.homeManagerModules.default ]; imports = [ inputs.agenix.homeManagerModules.default ];
age.identityPaths = [ "${config.home.homeDirectory}/.ssh/id_ed25519" ]; age.identityPaths = [ "${config.home.homeDirectory}/.ssh/id_ed25519" ];
home.packages = [ home.packages = [
inputs.agenix.packages."${pkgs.system}".default inputs.agenix.packages."${pkgs.stdenv.hostPlatform.system}".default
]; ];
age.secrets.gpg-keys.file = ./secrets/gpg-keys.age; age.secrets.gpg-keys.file = ./secrets/gpg-keys.age;
age.secrets.gpg-passphrase.file = ./secrets/gpg-passphrase.age; age.secrets.gpg-passphrase.file = ./secrets/gpg-passphrase.age;

View File

@@ -1,56 +1,57 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 ZgrTqA +u18TitbmPrZLwLNMT5C9wbkXPeROgHrh3Tb1RpE52s -> ssh-ed25519 ZgrTqA QZXdy40bVCgD80Q3wYLEAxxnk57LFXSJoi7OyLOaaCg
WcIdsXKxuTOEeja8mh5qoZ38hSlyS2K0WFS4sB/yKv8 LJSy/MEx2B96Ud/Zha1jcWSCRKLWxWCk368vXQxr+5s
-> ssh-ed25519 ZaBdSg f9kJeTDYYwQLbfL0lfSZjAkRj/8i7MOzp9MQ8ojEl0s -> ssh-ed25519 ZaBdSg NZPnWz53PicDlXpAMsWP0T5b7SUS9cdEXWrJMmbbRj4
Ez8Pmw5sLZUNWE6nIswzE6mQxZiAhKERLbD7MT/RTN4 wfQivncFKzPKSIU8dy8TNIUzP3xu/64x1tgZOFxQJbI
-> ssh-ed25519 MHZylw P/KulIF/w8YmSUpXObabu0El/rGAuETPvMGHLdfpR10 -> ssh-ed25519 MHZylw 5xEvH8tWQccfwvNeD9B3T/ke6BoyfHT7ug3kIxiVKVA
Mz9S83bVirlz+pjOrEsJP8oRIBz6PdneMopEshYbj/I RKHjJ6+77iaMNsEibggE3jL3ad1AIxBBqV9RiOxzXj0
-> ssh-ed25519 sIUg6g mobkna3lBZAMq7IwqR4uV5Bg6c353po4/+YY8Iqg/Bg -> ssh-ed25519 sIUg6g c++CCRbX+xtuBAwDWHPiHEy6gNYaCHeazfxwGMf0mA0
rCyfVkXKoPotBEEb6r3T56sRdjn9fC+taxrnRZuUSvc AQh9rpxKAHk8o4K5gMTkcL7NDSshzSd6wxlGfFSfTh8
-> ssh-ed25519 TnanwQ hCPpi8mAGltRM8bpl5OoFGVToPy58Pia9ElyCIi1enM -> ssh-ed25519 TnanwQ BCMQw9hPCzJGbREmPcYJTwu/+ySgOVdUvUyJoEBHTy0
o9m5Zzl+8kDPEFkQ/evupeGJG6S4aiZk+PaUxlvMTSU fNpMDE7ZuCD8thNVAZkF3KpXBosMXZYg0Kw7O5mJxhg
-> ssh-ed25519 cH4aug mR6lvjeeWSUmK50rsOjGGG6ccwzTpGVt97dW1rEEqQo -> ssh-ed25519 cH4aug tIihAQnC7+2Gjb4qz9PdNYV8ejCNijRoNkD15AbIVx4
AQvUomG2XgQo6dFIkZ24N97l8/B3F9WnN/KVGzITcz8 Bqn/loVjuBd0mzxM1WF9V6SYo7aUfBvfHw3Lfx/puCo
-> ssh-ed25519 ggrAFQ lYeue71aHAhUsy/LOgDPCNmavQEl9VIVnOVC/W/VoWk -> ssh-ed25519 ggrAFQ oT+ognMN1RRITMjzfRTR2jtcF7dOu5M8d5HRKfhTSyA
SwYzh1DpS5WHSdX2e16wkDUwm1Sa3ARHPF9UBycdHUg gkRnUIBRlmXW/slZRbF83h+JJKYDjtMSWYk4yr1DYag
-> ssh-rsa gwJx0Q -> ssh-rsa gwJx0Q
fbU+nVFbxpVC0D1rxouGi8aOirZ5CYaMlmm+pLmpI81WZRweyi/8j16IvRSqV9CB UJhHEui4WlmkCK9DXpCWCjZSRwZPC5l7GLmYxjZpkdhX7DDcBSnTWtOxNembGgHK
T4uLqBcpsYKVroPIvkIzy1LBUE0LrYj4tVAoAtPWUOk+Z3+pSs9MpTf4nhxjj2UJ BlkbRlkiHS7D/dRoMOSSbrFlG8/h5Td3WApZwJMRwfHLoNJoDCPo/zb12U2kWUp4
xXw+Kjw0rlAIy48cG8UssI3MAvF17m3JUG4xJxDmM/69J428tE1xa0JMjMXf/E7s 6M6lYZr7cd5rRCrBUPprzq/w5P8ewmyQ+xjc6PjtYrYtc7hujchAFqExkiqVC+uK
g/RSO7cx+Pcn2ClrFdMOVEkVNIKUkJdpymRSdOpwQnwzgOo4NNwBowFv/6OpfFdP BEHlT/HCzAGRfO+aputXndDO1u4DIG8bBudoeTsy9vFIrY0pccXzJkryVvZYc0nN
tS9zX9ZgpcOLKdCV463afYCbZ9z6lsw4KnEUL+bg0QAz8PtlRpF56LUnmBRSWPNN 8hI78YRtJ0aCkjcfiwLe5flstrHA2thu37XZx9zzcfKPJBstkGkIY3vPTON9ZSiX
nl002m6a+uZZQl1HizgR9Q yms1roAehbujMBWgSicEag
-> ssh-ed25519 YFIoHA Q8+eEd7maA4f64SGQfyk0pRuxY2WiD3UzHuLmzIPvVc -> ssh-ed25519 YFIoHA Rc5CuK/FriAAVF8ZEVh9ElLQm1C5io72Y1Tx6Z3xux0
XWV6IuKDftDStCgj4brPMaTvea+kIlYg7JGnkyX1+Ps CyGX0Yc2MiQSSVPW88IpSVNM2q3jSuGt+99kGrTLVhw
-> ssh-ed25519 KQfiow rra4AZqxS0duGI0GrMAGt1KnUVRyBbnGcZhsu2QeCxM -> ssh-ed25519 KQfiow uzHn7ponamlnmdeXTBn8L9bRjMR0a9hOcSvxJyzkXTw
jaIThcqxxxh9atSgrVEzMFsDip5aNTxWaekgIw+lLKw x4UQuy1gE+5IOyHReEH/pZOFrj+xMwhMTf6qS7JSdEs
-> ssh-ed25519 kScIxg NBVuAT7UXhPMu1THkAXJ1QYNwSnFIgvjQB6jYD7t4AI -> ssh-ed25519 kScIxg RH4PePSDsHRuGAF1oFeff1G0QbG3YL8qQXHDs207ImM
xs+x0xP/jRBsvr2IMhEBrpP0o1Ian9Guw1yuMT0b5XA WC3rNCJI9QU3/s4zcS9u4h6vQGuSdimRK2/oduzTVB0
-> ssh-ed25519 HzX1zw yyjdUbfty0hE0jIc2MMYvRkq/c/DABHJczH/CqyOkRw -> ssh-ed25519 HzX1zw UBj19kRz1WjrNwyEs5ZCaj+53+/41IoVI+yef4HuOl0
c5lkqMwaxsojqx/jYJhMbgWuN0qdgf3VlBYnUHpc/OE kfrvWmkMuo0rBYPAQJQDZDeOyml3AAavu1tG2wqUHIA
-> ssh-ed25519 KQfiow 70CAriiLnPXfh3a7HJnjRk0K5vYPc24AKjEWjiD/bSM -> ssh-ed25519 KQfiow Jw51VIARt0MBMrLtp5wBVAnPXsJIk+dW5TFWV4jl8V4
Sp/hULrynhI79p/zh96sD3rIYMTMzGD6CvN+6Dmxhhg Ynw7AbLj7sroUz2PhobMcXwrpC7G31gkF8ZIv4GSx3U
-> ssh-ed25519 1o2X0w +xLXrJLT2PITsHGkhak6M6/1ifd32sEHcNtI9xdTNTE -> ssh-ed25519 1o2X0w uQNYX4mbadB+7NqUvqw4Fnllz7SJfLIZVR0P0iwc/lA
PI80gCMGaR24FRiOmNeReTXrUecgCNJZMInKGNfQHic QpIfeoapsl1dvH4gPTRAHYHDf5AudGHt7bZHhbqCRcY
-> ssh-ed25519 KQ5iUA J2rBvdYjd9RYlQtVfaV50ZN0naHT58e3rZrnhgEszkg -> ssh-ed25519 KQ5iUA XcDXqvgiz9jDF5xXuC8jwJAc7K2rxZ9swj/S3H4XBg0
/iG3OU/HVraqegvrTgZz5/gp1HZwyGgGkXhjGYJXAoY LyLuGXAh5nZEkEgVcHn4MaJ1+5hTHb2JNpioYEU3itc
-> ssh-ed25519 AKGkDw 7gJhihE5rASMzycK4rzrSj3oll5hHqzXNQo1qzoqnwE -> ssh-ed25519 AKGkDw S6kq5/2emBk2lBCr4rCExk9HOb2z8WygDN10V/1MVT0
zlisCc+y2x028mosTHDQjrMDAX2lF3HAJ8LLtzuwwZ4 HxVZGkkKYkXmuGrRnmxkc9cnRorI/anhjp5D4JIM1jA
-> ssh-ed25519 0eS5+A sLIAQR51fxFZatgc7CCJYgjCtfdqYFLBnL4Qs9WmbyM -> ssh-ed25519 0eS5+A RlLt+aZCm7CLYWksDdAvcKoYvGxaaK1LWgYlIVBbiFA
CgeHGN6+/ZE/RrQoPlaizGtu3bEz8lPfWEfFYY9wzrA ZQR7sBnJBVRiyg6KGW2zRYETckQlM69gNztkIvgts0M
-> ssh-ed25519 9/4Prw uytvwSpCRE/5xDu/Og60k6jBF3wyBanyZMWhEjzcf1E -> ssh-ed25519 9/4Prw LFs0+eoJgS42LwutqY4NYOjJaFDEWlEpsyXJA1hMpxU
CM37OOCnORhdGDPXLJ7VIRYJhvMXKxfs6oK9WnHycV4 UUsPedbVPTIptio018GTKC9T97ghYJrgp/HpCfw0SFQ
-> ssh-ed25519 gAk3+Q hqrzZ+KHXT7mfI/6332ZymbDTQmjS2m7jDhtqNQ44no -> ssh-ed25519 gAk3+Q iELBrtN9sWAPkpqIOXrlrCp/Dv243ywAj/4S0Uqu8AY
n/k8+t4BcmPy5Tgkl9e8/CSoCcmVp2lkU8rCRlSGfZU 2cSwgLATmiRfiT8OQCFAENv9XFzIJ4lC7vElgfz3S6c
-> ssh-ed25519 X6eGtQ kO2cKtxVcAIRA3xC4zLLuj2cfZ6CKlOq3aTrB9cqhg8 -> ssh-ed25519 X6eGtQ VIgFiZjr94ufD1d/yzpCUWgx5e1NHjZO/g4iXflIqCY
tG5GtTne/45DqNkJ8XjOlfbbDGLfTxweUKG1+f7aXNU v6cbckXOb3FgGEW7oarOuhSLhU7m8Oj34SGoDKRDOcY
-> ssh-ed25519 0ma8Cw /PwKBNkRtj0mWkG3fJZOIjdLkhWlxxtowVABKjxShG0 -> ssh-ed25519 0ma8Cw KRNJBjm1QWdCXzGgq+5Uk/zQvC1N0yXqPe8jxTyQiRc
OSfm0wSpyrd8bb836wbFi1BrWHkuZ4DuWw9ZwfMP5b0 AW8vvFilLCf6ywXTF4+dJ/D6ZhvNgCFsX73gSCkyDNk
-> ssh-ed25519 Tp0Z1Q qJqv47mimbpQkdiYO5sDqj+Qyi7Nq+y9Bb/EuxneXQg -> ssh-ed25519 Tp0Z1Q o3O41oBK/L/N6BmhIOlMjqULPWKNmc5ePfAWUpR/hQI
F+b8rEY9rxDdPe+mVy0h7AggugMvGi9lvwKDfe/rjJs Z3En9bGjVpsSPmIeJ7m672y/PyReiPFd9mTphjI2jqs
-> ssh-ed25519 ePNWZQ MO3gceW2gDffFS/Tr2F2BkMSKD6Ydn/mRXHqYckGOnU -> ssh-ed25519 ePNWZQ uEn2jffxpfeVOjrbdu7hvWgJoCvebF/oe731wcIvVRs
3CxqL9EwDQ99T7pN6b/NU0NQungyh2EHE56L8Stuj/U uvLDUX/PaCJKgptAwDvglh/RmqPi8rl+pgtosEcYC74
-> ssh-ed25519 hILzzA AIf5pdaRPGOtKKV/gY5GM/PNtqSXVhoxB69t5JEgUlA -> ssh-ed25519 hILzzA S7zCnXsA40E0ZExfoEY8OPcKCDwy9sKwBhuoP9XXvCU
d6TC0L2OpbhvaREkVc+rNzY7U8VIQMG0in0UHFsGSUY 59l/zPqsJ2gzfQC1FtuTKYpaU8BmZBjWRxvHiia1zKY
--- 6QUiesVdF1mNKhzpT/tPTMDvL7MAkEbXR2CHau5/SHE --- 3fEsWUppaCEgE8I/y0eDHcHp+oguYmZvuKb28u5+b7Q
<EFBFBD>ڙM<EFBFBD><EFBFBD> x<>0<EFBFBD><30>_<EFBFBD><5F>v<EFBFBD><76><EFBFBD><EFBFBD>uA<75><41>u1ON<4F>* ݩQJ<14><>E@<40>ϚȬ<0E><><EFBFBD>b<EFBFBD>Clg<6C><67><EFBFBD>j<EFBFBD><6A><EFBFBD><EFBFBD>ǘ<EFBFBD><C798>F+6"C<><43><EFBFBD><EFBFBD><08>/Ya<59>#<23>l<EFBFBD>p<EFBFBD><08><18><>E4w<34>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>3<>i<><11>L<EFBFBD>?<3F><>v:2<><1C>ߖY<><59>l<EFBFBD><6C>s<EFBFBD><73><EFBFBD>
o`<60>m<EFBFBD>Md\<1A>5<7F><35><18> <09>_<EFBFBD><5F><EFBFBD>pU"i<><69>

Some files were not shown because too many files have changed in this diff Show More