Compare commits

..

19 Commits

Author SHA1 Message Date
6d3bb1bef5 [altair] Remove some unused programs 2026-07-28 20:11:57 -07:00
e9e868a4c5 [xpadneo] Moved to it's own config. Adds an env var for steam. 2026-07-28 20:02:08 -07:00
bc39d60a00 [Altair] Enable the xone controller. 2026-07-28 20:02:08 -07:00
62f8ba323e [eww] Adds delay properly this time. [Shell] Adds some network utilities like lsof and netstat 2026-07-26 21:02:18 -07:00
7aace1daba [Eww] Add delay to eww. 2026-07-26 20:47:23 -07:00
7f77140d89 [Claude] Add better-documents skill 2026-07-25 10:37:34 -07:00
8474a8c6ca [Flake] Update. [Claude] Adds claude to dev tools 2026-07-25 10:28:54 -07:00
01e93097ba [SearXNG] Update and fix config 2026-07-20 20:24:59 -07:00
3f44096a1f [Altair] Disable device auto-sleep for xpadneo/bluetooth. 2026-07-09 16:57:04 -07:00
2451cb9726 [Altair] Adds virtualbox for xbox controller updating. 2026-07-09 16:56:22 -07:00
1782e6329f [Altair] Sets up xpadneo and bluetooth. 2026-07-09 16:16:46 -07:00
be1752a5c7 [neovim] Try to get rid of astro warnings. [shell] Adds comma for Nix. 2026-07-09 16:16:46 -07:00
724d77dc57 [Shell] Fix capitalization typo in stay-awake alias
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-06 16:17:47 -07:00
fb95bcb6cf [Eww] Clean up shell scripts
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-06 16:17:44 -07:00
e6e4c5a683 [Hyprland] Simplify verbose float literals
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-06 16:17:41 -07:00
f2b0a1e850 [Hyprland] Fix mouse resize binding typo
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-06 16:17:39 -07:00
a914bd4e90 [Neovim] Simplify window navigation keymaps into a loop
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-06 16:17:36 -07:00
7af382fcfd [Neovim] Fix obsidian note_id_func generating only one random char
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-06 16:17:33 -07:00
26de8e0076 [Neovim] Fix snacks opts silently discarding merged config
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-06 16:17:30 -07:00
26 changed files with 499 additions and 68 deletions

24
flake.lock generated
View File

@@ -83,11 +83,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1779726825, "lastModified": 1784350909,
"narHash": "sha256-RUkMrREjKDQrA+dA9+xZviGAxM5W1aVdyOr/bSYpHrE=", "narHash": "sha256-ZWyzLbS1yKUTeFJLmdVuWNnHttL333/ldJbEE+KzCrM=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "b179bde238977f7d4454fc770b1a727eaf55111c", "rev": "4ce190229c73d44536caa7072f6308fb2d8feeb3",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -311,11 +311,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1779414137, "lastModified": 1781205112,
"narHash": "sha256-XpwuFhwnfwPbzImZeUWWns///UEpoKNkpl1hN90C3Ag=", "narHash": "sha256-PaoUtmk+qIP/ESdxkxnY7mUMpMHjix88qu22R5GLQqE=",
"owner": "shezdy", "owner": "shezdy",
"repo": "hyprsplit", "repo": "hyprsplit",
"rev": "0fc01e7930625ecb3e069f5dc8e1d61eab929f3b", "rev": "6b00b677d8905fb38779c91e12d6294e0e586a44",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -487,11 +487,11 @@
}, },
"nixpkgs_2": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1779971959, "lastModified": 1784707089,
"narHash": "sha256-R5nauXyqyfRUFiZycFFZdkF7wl6eaUpPLst35+2nJQY=", "narHash": "sha256-2V/6imsUgB7mPZlHY54oeVBRDoZbPKnvzwkAHUSSufk=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "ec942ba042dad5ef097e2ef3a3effc034241f011", "rev": "b3fe9581c9061c749abef42b6d4ee7b7c05c33fa",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -540,11 +540,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1777944972, "lastModified": 1783174389,
"narHash": "sha256-VfGRo1qTBKOe3s2gOv8LSoA6Fk19PvBlwQ1ECN0Evn8=", "narHash": "sha256-aCWC8ngycU7OdJrU2+Je3qf+1a2ykuBvpPhZT/9tXMc=",
"owner": "Mic92", "owner": "Mic92",
"repo": "sops-nix", "repo": "sops-nix",
"rev": "c591bf665727040c6cc5cb409079acb22dcce33c", "rev": "f1406619a3884cd5c47992a70b8b35c9c0fcb4c9",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@@ -14,21 +14,21 @@ let
''; '';
}; };
bambu-studio-wrapped = pkgs.symlinkJoin { # bambu-studio-wrapped = pkgs.symlinkJoin {
name = "bambu-studio-wrapped"; # name = "bambu-studio-wrapped";
paths = [ pkgs.bambu-studio ]; # paths = [ pkgs.bambu-studio ];
buildInputs = [ pkgs.makeWrapper ]; # buildInputs = [ pkgs.makeWrapper ];
postBuild = '' # postBuild = ''
wrapProgram $out/bin/bambu-studio \ # wrapProgram $out/bin/bambu-studio \
--prefix MESA_LOADER_DRIVER_OVERRIDE : zink \ # --prefix MESA_LOADER_DRIVER_OVERRIDE : zink \
--prefix __EGL_VENDOR_LIBRARY_FILENAMES : ${pkgs.mesa}/share/glvnd/egl_vendor.d/50_mesa.json # --prefix __EGL_VENDOR_LIBRARY_FILENAMES : ${pkgs.mesa}/share/glvnd/egl_vendor.d/50_mesa.json
''; # '';
}; # };
in in
{ {
home.packages = with pkgs; [ home.packages = with pkgs; [
bambu-studio-wrapped # bambu-studio-wrapped
lycheeslicer lycheeslicer
orca-slicer orca-slicer

View File

@@ -0,0 +1,14 @@
_: {
programs.claude-code = {
enable = true;
settings = {
effortLevel = "medium";
skipAutoPermissionsPrompt = true;
includeCoAuthoredBy = false;
skills = ./claude/skills;
};
};
}

View File

@@ -0,0 +1,291 @@
---
name: better-documents
description: >
Apply communication best practices when generating or reviewing any document,
presentation, report, memo, slide deck, proposal, or email. Use this skill when
asked to write, create, draft, or generate a document or presentation — apply
the principles at generation time, not as an afterthought. Also use when asked
to "review my doc," "look at this deck," "does this make sense," "is this clear,"
"improve this proposal," "check this before I send it," "make this more effective,"
or any request to evaluate whether a document will land with its audience. Use
this skill even when the request seems minor — a "quick look" or a "short memo"
is exactly when these principles matter most.
---
# Document Review
Apply communication best practices when generating or reviewing any business
document — whether the right message reaches the right audience in the right order.
This skill applies the principles from Anil Dash's [Make better documents](https://www.anildash.com/2024/03/10/make-better-documents/).
## Scope
This skill covers **business documents**: presentations, slide decks, proposals,
reports, memos, briefs, one-pagers, and emails. It does not cover UI, web
components, or frontend applications — use the `frontend-design` skill for those.
The design principles here differ from frontend design in important ways:
- **Restraint over expression.** UI benefits from bold aesthetic commitment and
distinctive visual personality. Business documents benefit from getting out of
the way of the content. Most people reading a board deck or a client proposal
are not there to appreciate the typography.
- **The audience can't interact.** A web interface rewards exploration. A
document gets one read, often skimmed, often on a small screen or printed.
Every design choice that draws attention to itself is attention stolen from
the message.
- **Non-designers are both authors and audiences.** UI is built and consumed
with design context nearby. Business documents are built by operators, analysts,
executives, and founders — and read by the same. Complexity that a designer
handles intuitively becomes noise for everyone else.
## Modes
| Mode | When to use | What you do |
|---|---|---|
| **generate** | "write me a proposal," "create a deck," "draft a memo" | Apply all five principles while producing the document; no separate report needed |
| **full-review** | "review this doc," "look at this deck" | Run all five passes on an existing document, produce a structured report |
| **rewrite** | "fix this," "make this better" | Apply all passes and return a revised version |
| **targeted** | "is the ask clear," "check the formatting" | Run only the relevant pass(es) |
| **quick** | "quick look," "does this work" | Run passes 1 and 2 only, flag the top 3 issues |
Default to **generate** when producing a new document from scratch. Default to
**full-review** when given an existing document with no other instruction.
---
## The Five Passes
Apply these in order. Each targets a different failure mode.
### Pass 1 — Audience and Purpose
The most common reason documents fail: they were written for the author, not the reader.
Check for:
- **Missing context**: Does the document assume knowledge the audience may not have?
Flag any jargon, backstory, or acronyms that aren't explained.
- **Buried ask**: Is there a request, decision, or action needed? If so, is it
stated clearly in the first third of the document — not saved for the end?
- **Author-centered opening**: Does the document open with the author's anxieties,
backstory, or credentials rather than shared context? Flag and suggest reordering
to start from common ground.
- **Missing deadline or stakes**: If a decision or response is needed, is the
timeline stated? Is the reason for that timeline explained from the *audience's*
perspective, not just the author's?
Severity guide:
- **CRITICAL** — The core ask or decision is absent or appears only at the end
- **MAJOR** — The audience is unclear; the document would read differently to
different readers
- **MINOR** — Context gaps that could be filled with a sentence
---
### Pass 2 — Structure and Sequencing
Order signals importance. Audiences assume the first thing is the most important.
If it isn't, they'll be confused or dismissive before they reach the part that matters.
Check for:
- **Creation-order sequencing**: Is the document structured in the order it was
*written* (background → analysis → conclusion) rather than the order the
audience needs (conclusion → supporting logic → call to action)?
- **Murder mystery structure**: Does the document build to a reveal rather than
stating the point upfront? Flag any document where the key conclusion or request
appears in the second half.
- **Unannounced ordering**: If the document is ordered chronologically, by category,
or by any logic other than importance, is that explicitly stated? If not, the
audience will hunt for meaning in the sequence.
- **Key information in the wrong channel**: Is anything critical only in speaker
notes, appendices, or footnotes? Central points belong in the main body.
Severity guide:
- **CRITICAL** — The document's conclusion or core request is in the second half
- **MAJOR** — Ordering is non-obvious and unexplained
- **MINOR** — Supporting points could be reordered for better flow
---
### Pass 3 — Formatting Restraint
Over-formatting is the most visible symptom of unclear thinking. When everything
is emphasized, nothing is.
Check for:
- **Emphasis overload**: Are bold, italic, underline, and color being combined
on the same text? Flag any instance of two or more emphasis types on a single
element.
- **Underlines on non-links**: Flag every underline that isn't a hyperlink.
Underlines exist to signal clickability; using them decoratively confuses readers.
- **Color proliferation**: Count distinct colors in use (excluding images). More
than two is almost always a problem. More than three is always a problem.
- **Border clutter**: Flag tables and sections with heavy borders. White space
separates content more clearly than lines.
- **Filler visuals**: Flag images, icons, or clip art that aren't specific to
the content's message. A blank space is better than a stock photo.
- **Formatting inconsistency**: Do headings, titles, or labels vary in size,
weight, or color across the document without clear reason? Flag inconsistencies
that will read as meaningful to an audience even if they weren't intentional.
Severity guide:
- **CRITICAL** — Formatting inconsistencies that will be read as semantic signals
(e.g., random font changes mid-document)
- **MAJOR** — Overuse of emphasis that makes it impossible to identify what's
actually important
- **MINOR** — Minor decoration that adds noise without adding meaning
---
### Pass 4 — Wayfinding and Density
Audiences need to know where they are in the story, and how far they have to go.
Check for:
- **No orientation**: Is there any indication of structure — a brief outline,
section headers, or progress markers — for documents longer than one page or
five slides? If not, flag.
- **Unsummarized data**: Does any chart, table, or data display appear without
a title or caption that states what it shows? Readers shouldn't have to interpret
data cold. Flag every chart or table whose title doesn't answer "what does this show?"
- **Unanswerable questions**: Are there open-ended questions in the document
(as headers or prompts) that can't actually be answered with a choice? Flag
any question that could lead to a philosophical discussion instead of a decision.
Good: "Do we go with Option A or Option B?" Bad: "How do we improve?"
- **Dense, unbroken prose**: Are there paragraphs longer than ~6 lines where
bullet points would make the content more skimmable without losing meaning?
Severity guide:
- **CRITICAL** — Data presented without any interpretive framing
- **MAJOR** — Long documents with no structural signposts
- **MINOR** — Questions that could be made more answerable
---
### Pass 5 — Naming and Versioning
The title is information. Most document names throw it away.
Check for:
- **Generic or auto-generated title**: Does the document have a title like
"Untitled," "Draft," "Meeting Notes," or the name of the person it's addressed
to? Flag and suggest a title that includes: topic, date, and context/owner.
- **Recipient-first naming**: If the document is *for* someone at another
organization, is it named after *them* rather than the author or topic?
They'll search for it by *your* name, not theirs.
- **Version ambiguity**: Does the filename or title use `_v2`, `_final`,
`_final_final`, or sequential numbers without dates? Flag and suggest
date-based versioning.
- **Meeting invites named after participants**: If the document is tied to a
meeting, flag any invite titled "Meeting with [Name]" — it tells the recipient
nothing about what the conversation is for.
Severity guide:
- **CRITICAL** — Untitled or generic title on a document intended for external sharing
- **MAJOR** — Version ambiguity on any document with multiple drafts
- **MINOR** — Suboptimal naming that could make retrieval difficult later
---
## Output Format
### Generate mode
Produce the document applying all five principles as first-order constraints —
not as a post-hoc checklist. Specifically:
- State the conclusion or ask in the opening, not the closing
- Order content by importance to the audience, not by how it was assembled
- Use the minimum formatting necessary: one emphasis type at a time, no decorative
underlines, no more than two colors, white space over borders
- Include structural signposts if the document is longer than one page or five slides
- Give the document a title that includes topic, date, and relevant context
**Override default visual style.** Claude's default document aesthetic — warm
cream backgrounds, serif display type (Georgia, Fraunces, Playfair), terracotta
or amber accents, and a "small all-caps label over a body copy block" slide
layout — is recognizable as AI-generated and inappropriate for most professional
contexts. Do not apply it.
Instead, before generating any document with visual styling:
1. **Ask about brand or visual constraints first.** Does the user have brand
colors, a template, or a font they use? If so, follow those exactly.
2. **If no brand guidance is given**, default to neutral: black text on white,
one sans-serif typeface throughout, no decorative color. The content should
do the work, not the palette.
3. **If the user explicitly wants visual styling**, offer 23 distinct directions
in one sentence each (e.g. "neutral/minimal," "bold/high-contrast," "warm/
editorial") and let them choose before proceeding. Do not pick for them.
No review report is needed in generate mode. The principles are baked in.
---
### Full-review and targeted mode
```
## Document Review: [Title or description]
### Summary
[23 sentences: what the document is trying to do, how well it's set up to succeed,
the one or two changes that would most improve it]
### Pass 1 — Audience and Purpose [N issues]
[Each issue: location → what the problem is → suggested fix → severity]
### Pass 2 — Structure and Sequencing [N issues]
[Same format]
### Pass 3 — Formatting Restraint [N issues]
[Same format]
### Pass 4 — Wayfinding and Density [N issues]
[Same format]
### Pass 5 — Naming and Versioning [N issues]
[Same format]
### Top 3 Changes
[The three revisions that would most improve this document's effectiveness,
ranked by impact]
```
### Rewrite mode
Return the revised document with a brief note after explaining what was changed
in each pass and why. Do not explain every small edit — only the structural
decisions that changed meaning or order.
### Quick mode
Return only the top 3 issues found across passes 1 and 2, with a one-line
suggested fix for each. No full report.
---
## Constraints
- **Don't alter the author's voice.** In review and rewrite modes, improve
structure and clarity, not style. If a sentence is clear and effective, leave it.
- **Don't invent content.** If information is missing (a deadline, a decision
option, context for the audience), flag the gap — don't fill it in.
- **Ask before generating if the audience is unclear.** In generate mode, if the
request doesn't specify who will read the document or what decision it needs to
drive, ask before writing. A document built for the wrong audience fails
regardless of how well it's structured.
- **Be specific.** Every finding must reference the actual text or location.
Never say "consider clarifying" without showing where and how.
- **Respect intentional choices.** If the document is explicitly a narrative
or a mystery-format pitch, flag the structural convention as a risk rather
than a violation.
---
*Based on [Make better documents](https://www.anildash.com/2024/03/10/make-better-documents/) by Anil Dash.*

View File

@@ -0,0 +1,57 @@
---
name: elegance
description: Iteratively study and apply elegant coding patterns. Each iteration - understand the code, research what simple and elegant code looks like, apply learnings, verify with CI. Use as a standalone refactoring pass or when the user asks to make code more elegant, simple, or idiomatic.
source: https://github.com/srid/emanote/tree/master/.claude/skills/elegance
---
# Elegance
Iteratively study and apply elegant coding patterns. Each iteration: understand the code, research what simple & elegant code looks like, apply learnings, verify with CI.
Run for **3 iterations** (or as specified by the user — can be a number or a duration like `2h`).
## 0. Determine Scope
- Before starting, use the `AskUserQuestion` tool to ask: should this operate on the **whole codebase** or only on **changes in the current branch/PR**?
- If scoped to current branch/PR, use `git diff main...HEAD` (or the appropriate base branch) to identify changed files and limit all subsequent steps to those files only.
## For each iteration (1 to N)
### 1. Understand
- Read through the relevant source files.
- Note patterns, repetition, unnecessary complexity, non-idiomatic code.
### 2. Research
- Use WebSearch/WebFetch to research what simple, elegant (yet readable!) code looks like for the relevant technology.
- Look for idiomatic patterns, standard simplifications, and community best practices.
- Focus on: simplicity, readability, removing unnecessary abstraction, leveraging language features.
### 3. Apply
- Refactor based on what you learned.
- This can include: edits, code reorganization, or even rewrites where simplicity demands it.
- Prefer fewer lines, clearer intent, and idiomatic style.
- Don't add abstractions — remove them.
### 4. Verify
- Run tests/CI to check edits.
- If CI fails, fix the issues before proceeding to the next iteration.
### 5. Log Progress
- Briefly note what changed in this iteration and why.
## After all iterations
- Do **not** git commit. Leave all changes in the working directory for the user to review.
- Present a summary of what changed across all iterations.
## Principles
- **Simple over clever**: Elegant code is simple code.
- **Readable over terse**: Brevity is good, but not at the cost of clarity.
- **Idiomatic over generic**: Use the language's strengths. Write TypeScript like TypeScript, not like Java.
- **Each iteration builds on the last**: Don't undo previous improvements. Deepen them.

View File

@@ -11,6 +11,9 @@
./nix.nix ./nix.nix
./lua.nix ./lua.nix
./sh.nix ./sh.nix
# Claude Code
./claude.nix
]; ];
home.packages = with pkgs; [ home.packages = with pkgs; [

View File

@@ -4,7 +4,7 @@
# Useful for getting the import information from github info for flakes. # Useful for getting the import information from github info for flakes.
nix-prefetch-github nix-prefetch-github
nixfmt-rfc-style # Formatter nixfmt # Formatter
nil # Language Server nil # Language Server
statix # Lints and suggestions for Nix statix # Lints and suggestions for Nix
]; ];

View File

@@ -5,8 +5,7 @@ set -e
handle_event() { handle_event() {
case $1 in case $1 in
focusedmon*) active_workspace;; focusedmon* | workspace*) active_workspace;;
workspace*) active_workspace;;
esac esac
} }

View File

@@ -12,8 +12,8 @@ handle_event() {
} }
list_workspaces() { list_workspaces() {
focused=`hyprctl activeworkspace -j | jq '.id'` focused=$(hyprctl activeworkspace -j | jq '.id')
active=`hyprctl monitors -j | jq 'map(select(.name == "'$monitor'")) | .[0].activeWorkspace.id'` active=$(hyprctl monitors -j | jq 'map(select(.name == "'$monitor'")) | .[0].activeWorkspace.id')
# Explanation # Explanation
# 1. Select only workspaces on the current monitor. # 1. Select only workspaces on the current monitor.
# 2. Remove duplicates (might be a bug with split-monitor-workspaces # 2. Remove duplicates (might be a bug with split-monitor-workspaces

View File

@@ -36,6 +36,8 @@
Service = { Service = {
Type = "oneshot"; Type = "oneshot";
RemainAfterExit = true; RemainAfterExit = true;
# Eww won't start right if Hyprland hasn't finished initializing.
ExecStartPre = "${pkgs.coreutils}/bin/sleep 2";
ExecStart = "${pkgs.eww}/bin/eww open-many ${lib.concatStringsSep " " config.programs.eww.widgets}"; ExecStart = "${pkgs.eww}/bin/eww open-many ${lib.concatStringsSep " " config.programs.eww.widgets}";
ExecStop = "${pkgs.eww}/bin/eww kill"; ExecStop = "${pkgs.eww}/bin/eww kill";
}; };

View File

@@ -95,5 +95,5 @@ hl.bind(" + XF86AudioPrev", function()
hl.exec_cmd("playerctl previous") hl.exec_cmd("playerctl previous")
end, { locked = true }) end, { locked = true })
hl.bind("SUPER + mouse:272", hl.dsp.window.drag(), { mouse = true }) hl.bind("SUPER + mouse:272", hl.dsp.window.drag(), { mouse = true })
hl.bind("SUPER + mouse:273", hl.dsp.window.resize(), { mouce = true }) hl.bind("SUPER + mouse:273", hl.dsp.window.resize(), { mouse = true })
-- hl.bind(" + mouse:272", hl.dsp.hy3:focustab({ mouse })) --, { non_consuming = true } -- hl.bind(" + mouse:272", hl.dsp.hy3:focustab({ mouse })) --, { non_consuming = true }

View File

@@ -25,14 +25,14 @@ hl.config({
resize_on_border = true, resize_on_border = true,
}, },
decoration = { decoration = {
active_opacity = 1.000000, active_opacity = 1.0,
blur = { blur = {
enabled = true, enabled = true,
passes = 1, passes = 1,
size = 3, size = 3,
vibrancy = 0.169600, vibrancy = 0.169600,
}, },
inactive_opacity = 1.000000, inactive_opacity = 1.0,
rounding = 5, rounding = 5,
shadow = { shadow = {
color = "rgba(1a1a1aee)", color = "rgba(1a1a1aee)",
@@ -81,7 +81,7 @@ hl.config({
hl.device({ hl.device({
name = "logitech-g502-1", name = "logitech-g502-1",
sensitivity = -0.200000, sensitivity = -0.2,
}) })
-- Additional configs -- Additional configs

View File

@@ -2,7 +2,6 @@
-- Default keymaps that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/keymaps.lua -- Default keymaps that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/keymaps.lua
-- Add any additional keymaps here -- Add any additional keymaps here
vim.keymap.set("n", "<C-up>", "<C-w>k", { noremap = true, silent = true }) for _, map in ipairs({ { "<C-up>", "k" }, { "<C-down>", "j" }, { "<C-left>", "h" }, { "<C-right>", "l" } }) do
vim.keymap.set("n", "<C-down>", "<C-w>j", { noremap = true, silent = true }) vim.keymap.set("n", map[1], "<C-w>" .. map[2], { noremap = true, silent = true })
vim.keymap.set("n", "<C-left>", "<C-w>h", { noremap = true, silent = true }) end
vim.keymap.set("n", "<C-right>", "<C-w>l", { noremap = true, silent = true })

View File

@@ -17,7 +17,9 @@ return {
-- Haskell -- Haskell
hls = {}, hls = {},
-- Copilot -- Copilot
copilot = { enabled = true }, copilot = {
enabled = true,
},
}, },
codelens = { codelens = {
enable = true, enable = true,

View File

@@ -58,9 +58,11 @@ return {
return title:gsub("[^A-Za-z0-9-_]", ""):lower() return title:gsub("[^A-Za-z0-9-_]", ""):lower()
else else
-- If title is nil, just put the date and four random characters -- If title is nil, just put the date and four random characters
local suffix = ""
for _ = 1, 4 do for _ = 1, 4 do
return os.date("%Y-%m-%d ") .. string.char(math.random(65, 90)) suffix = suffix .. string.char(math.random(65, 90))
end end
return os.date("%Y-%m-%d") .. "-" .. suffix
end end
end, end,
}, },

View File

@@ -1,7 +1,7 @@
return { return {
"folke/snacks.nvim", "folke/snacks.nvim",
opts = function(_, opts) opts = function(_, opts)
vim.tbl_deep_extend("force", opts, { opts = vim.tbl_deep_extend("force", opts, {
styles = { styles = {
notification = { notification = {
wo = { wrap = true }, -- wrap notifications wo = { wrap = true }, -- wrap notifications
@@ -57,6 +57,7 @@ return {
end end
end, end,
}):map("<leader>ut", { desc = "Toggle Color Column" }) }):map("<leader>ut", { desc = "Toggle Color Column" })
return opts
end, end,
keys = { keys = {
{ {

View File

@@ -2,7 +2,6 @@ return {
"nvim-treesitter/nvim-treesitter", "nvim-treesitter/nvim-treesitter",
opts = { opts = {
ensure_installed = { ensure_installed = {
"astro",
"bash", "bash",
"html", "html",
"css", "css",

View File

@@ -11,10 +11,14 @@
# a system or working with other shell commands. Packages more specific to # a system or working with other shell commands. Packages more specific to
# development can be in development configs. # development can be in development configs.
home.packages = with pkgs; [ home.packages = with pkgs; [
# Package management
comma # Runs commands without having to install them
# System # System
htop htop
btop btop
psmisc # fuser, killal, pstree psmisc # fuser, killall, pstree
lsof
# Session management # Session management
tmux tmux
@@ -42,6 +46,7 @@
# Networking # Networking
dnsutils dnsutils
inetutils inetutils
net-tools
socat socat
xh xh
@@ -65,7 +70,7 @@
"du" = "echo 'Do you mean: dust or dua?'"; "du" = "echo 'Do you mean: dust or dua?'";
"ranger" = "echo 'Do you mean: yazi'"; "ranger" = "echo 'Do you mean: yazi'";
"stay-awake" = '' "stay-awake" = ''
tmux new-session -d -A -s keep-awake 'systemd-inhibit --who="DRew" --why="Manual keep awake" --what=sleep sleep infinity' tmux new-session -d -A -s keep-awake 'systemd-inhibit --who="Drew" --why="Manual keep awake" --what=sleep sleep infinity'
''; '';
"allow-sleep" = "tmux kill-session -t keep-awake"; "allow-sleep" = "tmux kill-session -t keep-awake";
}; };

View File

@@ -27,10 +27,11 @@ tandoor:
secret_key: ENC[AES256_GCM,data:nl7S2fS1wENrT5k2iZfLEAGc99lCUktgwR5L5KklF69BNVKQkW1rUgb3aIv50VpXZa+3OxV/vdPmG9NhKMy96I5+Dno=,iv:FFyGQBARz0B5zrONZELzUMsOIn8TWrDNTKGsAHPlS7w=,tag:/c4MnDfLXQpBZDqVxZ0DTg==,type:str] secret_key: ENC[AES256_GCM,data:nl7S2fS1wENrT5k2iZfLEAGc99lCUktgwR5L5KklF69BNVKQkW1rUgb3aIv50VpXZa+3OxV/vdPmG9NhKMy96I5+Dno=,iv:FFyGQBARz0B5zrONZELzUMsOIn8TWrDNTKGsAHPlS7w=,tag:/c4MnDfLXQpBZDqVxZ0DTg==,type:str]
immich: immich:
database: ENC[AES256_GCM,data:1fjOQsLZcq/T+r+AkzomWwCQWw==,iv:c4pn2rC+3xkxLJ7uAdhnTE6zVTRQkfuKK3tjUyDhfAw=,tag:kvk7DOv6X/+RDxfPxVak7w==,type:str] database: ENC[AES256_GCM,data:1fjOQsLZcq/T+r+AkzomWwCQWw==,iv:c4pn2rC+3xkxLJ7uAdhnTE6zVTRQkfuKK3tjUyDhfAw=,tag:kvk7DOv6X/+RDxfPxVak7w==,type:str]
searxng:
secret: ENC[AES256_GCM,data:Dg/6TAKY7fyhw8LJ6E4ZYN85zs/ItcetCYHETFbOMvHkGsflE3ngQNyIPVY=,iv:z3y2vXjJWCGhXYjfj963Nhiw6K0i/M8bVvwO/L3zgzk=,tag:yO9NtYMLjSazHQmToSR3fA==,type:str]
sops: sops:
age: age:
- recipient: age1dstsz5g4qthwt2sssu5wp787ku7rnfqm02mqaefsaueswhvqzpmsyft4p4 - enc: |
enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBVZnYrVnR1MlBjdzFpQnVi YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBVZnYrVnR1MlBjdzFpQnVi
RXFUcEN2N0Zoc2ZUUnprdXc0aElFaXU5c1VBCkxxcGd4QUhOaTl4K0paOTZ3d2Ez RXFUcEN2N0Zoc2ZUUnprdXc0aElFaXU5c1VBCkxxcGd4QUhOaTl4K0paOTZ3d2Ez
@@ -38,8 +39,8 @@ sops:
b2NVRnVFNmF6a2hjRE9OOUxVMGpjSWcKA6Do+oddwMjc2XNJUCeGXY985gJZ4f2v b2NVRnVFNmF6a2hjRE9OOUxVMGpjSWcKA6Do+oddwMjc2XNJUCeGXY985gJZ4f2v
Dyo0/Oyuwz1jFMrjLmnmnmtyn079mT9wsm28KlaEEvzDIxOBnLjx6A== Dyo0/Oyuwz1jFMrjLmnmnmtyn079mT9wsm28KlaEEvzDIxOBnLjx6A==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1yvdzvuvu5wqztcx6ll2xk6x547uuyqy735tjjdd7zftkz53jsf9qf5ahue recipient: age1dstsz5g4qthwt2sssu5wp787ku7rnfqm02mqaefsaueswhvqzpmsyft4p4
enc: | - enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBKeGhvQWp6WWx6N1JDdm1J YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBKeGhvQWp6WWx6N1JDdm1J
UWlWZTV5ellMd2ZIRWpkRnJDT2s4UVZJMEM4Cll2MnVNTnFWYit2bHpCVzcwbysy UWlWZTV5ellMd2ZIRWpkRnJDT2s4UVZJMEM4Cll2MnVNTnFWYit2bHpCVzcwbysy
@@ -47,8 +48,8 @@ sops:
OHlxaytJTWlNSFRCd2dDaFVsUU1CbUkKp7J+mDnGFS9upV6QWi40ptG85+UZ5y1G OHlxaytJTWlNSFRCd2dDaFVsUU1CbUkKp7J+mDnGFS9upV6QWi40ptG85+UZ5y1G
9ic/sQEMHQe9VeAutVz1GPYWbF3Vt5iawXmtVxN+zx/bLAYGglv5yg== 9ic/sQEMHQe9VeAutVz1GPYWbF3Vt5iawXmtVxN+zx/bLAYGglv5yg==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1jrk4h7x4qzhr6z5m4d099mlfyjc4n5n9s52r4gfsdz0slnqlqa9sss735v recipient: age1yvdzvuvu5wqztcx6ll2xk6x547uuyqy735tjjdd7zftkz53jsf9qf5ahue
enc: | - enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkM0RRaFhGKytkSjNMU3cy YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkM0RRaFhGKytkSjNMU3cy
d1dlcms4TVMzU2xsSHBqcDJWQTdCU1dZcERJCktHRVZiWkZrbzk4QXRNSmpyY25X d1dlcms4TVMzU2xsSHBqcDJWQTdCU1dZcERJCktHRVZiWkZrbzk4QXRNSmpyY25X
@@ -56,7 +57,8 @@ sops:
QlE3cFYxUXNVam1aMlJEVTRGV2xsN1kKXMeSXiEdXyb6c+dcxX3G/Q+s78lfi90g QlE3cFYxUXNVam1aMlJEVTRGV2xsN1kKXMeSXiEdXyb6c+dcxX3G/Q+s78lfi90g
dvKJPDYvGb/8JXSkZNkLlWvHEVnsAJ1mJFb1idenYzeQvJlsX07rYA== dvKJPDYvGb/8JXSkZNkLlWvHEVnsAJ1mJFb1idenYzeQvJlsX07rYA==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2026-02-25T00:28:13Z" recipient: age1jrk4h7x4qzhr6z5m4d099mlfyjc4n5n9s52r4gfsdz0slnqlqa9sss735v
mac: ENC[AES256_GCM,data:hDmqObrtfoVkQqz8JPkqlyXMbiuyBophjdZNLvTFrZw3pAVNCuzsH4zxFBOaxJttkzLc65DWDHDeEIBY5YZam1GLFFXUQ5E3Dxno7hnyzOoM2ipgDTOacI0gbKJAWgGUF3LNDdqVoREA9LC91LoNUJoNmzpTSFtuLb7ORuwCrH4=,iv:8+W3n1Cr6woEiPU9ECaMYM64HNmFHr2AIw6UohCJi00=,tag:7drkZiPAUHaEx5PagXA9JQ==,type:str] lastmodified: "2026-07-21T02:59:55Z"
mac: ENC[AES256_GCM,data:0v26ceptPmbVdee70AOMdZHOarPDRuxKi+QP3Ci+wyJQJdQVriKKUnN3Zv/MKjZ3Sg2M/C5XtsdhGwXJpPsfwdDhWIRip6UYWXIKkVyZcxOs6E2zlK3xCAk/eTKhAsmL7Y6yFV+hpYwlT/hFnzOHXt1xbxGVJiKnO98OH0+6hnk=,iv:f94wd227bM0SniUuY+CFg2deEfITzUGTGwDA/WQJhms=,tag:M0r4Vg480wWWYPH3PBB7qg==,type:str]
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.11.0 version: 3.13.1

View File

@@ -0,0 +1,10 @@
{ pkgs, ... }:
{
# Enable bluetooth.
hardware.bluetooth.enable = true;
# Install the management service and packages.
environment.systemPackages = with pkgs; [
bluez
];
}

View File

@@ -0,0 +1,4 @@
_: {
virtualisation.virtualbox.host.enable = true;
users.extraGroups.vboxusers.members = [ "drew" ];
}

View File

@@ -0,0 +1,26 @@
_: {
hardware = {
# Wireless xbox controllers
xpadneo = {
enable = true;
settings = {
disable_mouse = 1;
};
};
# Hardwired xbox controllers.
xone.enable = true;
};
# disable_ertm is required for xpadneo to connect properly and establish a
# data connection. enable_autosuspend is to prevent Linux from putting the
# BT radio to sleep and causing a disconnect.
boot.extraModprobeConfig = ''
options bluetooth disable_ertm=1
options btusb enable_autosuspend=0
'';
# Steam also needs HID API to be off so SDL will read directly from evdev,
# otherwise it won't get any events from xpadneo.
environment.sessionVariables.SDL_JOYSTICK_HIDAPI = "0";
}

View File

@@ -6,7 +6,6 @@
pkgs, pkgs,
... ...
}: }:
{ {
networking.hostName = "altair"; # Define your hostname. networking.hostName = "altair"; # Define your hostname.

View File

@@ -1,17 +1,20 @@
{ ... }: { ... }:
{ {
imports = [ imports = [
../../authorized-keys.nix
../../features/android-dev.nix
../../features/appimage.nix
../../features/audio.nix
../../features/bluetooth.nix
../../features/container-dev.nix
../../features/flatpak.nix
../../features/gc.nix
../../features/gui.nix
../../features/virtualbox.nix
../../features/xpadneo.nix
./configuration.nix ./configuration.nix
./hardware-configuration.nix ./hardware-configuration.nix
./qmk.nix ./qmk.nix
../../authorized-keys.nix
../../features/appimage.nix
../../features/audio.nix
../../features/gc.nix
../../features/gui.nix
../../features/container-dev.nix
../../features/android-dev.nix
../../features/flatpak.nix
]; ];
nixpkgs.config.allowUnfree = true; nixpkgs.config.allowUnfree = true;

View File

@@ -8,7 +8,6 @@
"/features/development/haskell.nix" "/features/development/haskell.nix"
"/features/development/markdown.nix" "/features/development/markdown.nix"
"/features/development/typescript.nix" "/features/development/typescript.nix"
"/features/development/vscode.nix"
"/features/eww" "/features/eww"
"/features/email.nix" "/features/email.nix"
"/features/gaming.nix" "/features/gaming.nix"

View File

@@ -1,10 +1,24 @@
{ config, ... }: { config, ... }:
let inherit (import ./lib.nix config) havenisms mkContainer; in let
inherit (import ./lib.nix config) havenisms mkContainer;
in
{ {
sops = {
secrets = {
"searxng/secret" = { };
};
templates."searxng.env" = {
mode = "0400";
content = ''
SEARXNG_BASE_URL=https://search.${havenisms}
SEARXNG_VALKEY_URL=valkey://valkey:6379/0
SEARXNG_SECRET=${config.sops.placeholder."searxng/secret"}
'';
};
};
virtualisation.oci-containers.containers.searxng = mkContainer { virtualisation.oci-containers.containers.searxng = mkContainer {
hostName = "search"; hostName = "search";
image = "docker.io/searxng/searxng:latest"; image = "searxng/searxng:latest";
port = 8080; port = 8080;
public = true; public = true;
dependsOn = [ dependsOn = [
@@ -19,9 +33,9 @@ let inherit (import ./lib.nix config) havenisms mkContainer; in
volumes = [ volumes = [
"/tank/config/searxng:/etc/searxng" "/tank/config/searxng:/etc/searxng"
]; ];
environment = { environmentFiles = [
SEARXNG_BASE_URL = "https://search.${havenisms}"; config.sops.templates."searxng.env".path
SEARXNG_REDIS_URL = "redis://valkey:6379/0"; ];
}; extraOptions = [ "--pull=always" ];
}; };
} }