chore: advance workstation workflow pilots

This commit is contained in:
kiri committed 2026-09-05 21:18:34 +02:00
1 parent 2c0338329b
commit c9ee688537
18 files changed
+328 -553

No files matched your search

+120 -20
View File
@@ -8,15 +8,19 @@ and add no abstraction without a demonstrated repeated need.
## Current checkpoint ## Current checkpoint
- Tranche: repository contracts and Yookr workbench - Tranche: desktop, agents, and notes
- State: active - State: waiting for Zenith activation
- Branch: `chore/workflow-system` - Branch: `chore/workflow-system`
- Baseline: `nix flake check --no-build --quiet` passed on 2026-09-05; only - Baseline: `nix flake check --no-build --quiet` and a no-link Zenith system
the existing dirty-tree and unknown `modules` output warnings were emitted. build passed on 2026-09-05 after the desktop, agent, runtime, and note changes;
- Next: activate the NetworkManager OpenVPN plugin on Zenith and Polaris, then only the expected dirty-tree and unknown `modules` warnings were emitted.
import the existing profile as the root-owned `Yookr VPN` connection on each The generated project menu finds 30 live repositories without `.archive` or
host and run its route, DNS, reconnect, suspend, and reboot gates. Keep `.worktrees` entries, and the generated daily-note configuration passes an
OpenVPN 3 until both hosts pass. isolated same-day idempotence test.
- Next: the user runs
`sudo nixos-rebuild switch --flake /home/kiri/.config/nixos#zenith` and reports
whether it succeeds. Then the agent verifies live ownership before asking for
one bounded interactive gate at a time.
## Progress ## Progress
@@ -24,9 +28,13 @@ and add no abstraction without a demonstrated repeated need.
| --- | --- | --- | | --- | --- | --- |
| Bootstrap and repository ownership | Waiting for user | Repository and dashboard reconciliation complete; credential cleanup remains | | Bootstrap and repository ownership | Waiting for user | Repository and dashboard reconciliation complete; credential cleanup remains |
| Declarative workstation foundation | Complete | All-host builds pass with one Nixpkgs pin, `just`, and an explicit Podman Compose provider | | Declarative workstation foundation | Complete | All-host builds pass with one Nixpkgs pin, `just`, and an explicit Podman Compose provider |
| Repository contracts and workbench | Active | Three contracts are checkpointed and the read-only test Kubernetes gate passed; API, database, and report evidence remain | | Repository contracts and workbench | Waiting externally | Three contracts and read-only Kubernetes pass; API deployment/access evidence is externally blocked, while database/report scaffolding is deferred until a real investigation |
| Desktop, agents, notes, PIM, transcription | Pending | Independent pilots follow foundation changes | | Desktop navigation and interaction | Active | Project discovery, Niri vocabulary cleanup, and stable Actual/WhatsApp launchers build; activation, Outlook, and two-output checks remain |
| Conditional retirement and completion | Pending | Requires per-pilot evidence | | Agent workflow | Active | The instruction-only `nixos-maintainer` skill validates and builds; the Herdr pilot remains |
| Notes | Active | Authored work notes are copied and verified in the single notebook; daily-note configuration builds, while source retirement awaits one activated sanity check |
| PIM | Active | Evolution 3.60.2 with its native Microsoft 365 backend builds beside Thunderbird; account and daily-use gates await activation and credentials |
| Transcription | Pending | Requires a real Fossify recording-transfer pilot before implementation moves from Zenith to Orion |
| Conditional retirement and completion | Active | OpenVPN 3, Zed, Helix, Foot, global Node.js, and global Bun are removed declaratively; other removals remain gated separately |
## Repository checkpoints ## Repository checkpoints
@@ -43,7 +51,38 @@ and add no abstraction without a demonstrated repeated need.
| `traceability-data-model` | `chore/workflow-contract` | `33cb7ff` | Establish the database and schema contract | | `traceability-data-model` | `chore/workflow-contract` | `33cb7ff` | Establish the database and schema contract |
| `yookr-workbench` | `main` | `badc61c` | Create the workbench and isolate its Garden session | | `yookr-workbench` | `main` | `badc61c` | Create the workbench and isolate its Garden session |
## Human actions ## Deferred or externally blocked actions
None of these block work on independent pilots. Surface the exact applicable
step to the user only when it blocks the current task.
- Activate the verified Zenith generation with
`sudo nixos-rebuild switch --flake /home/kiri/.config/nixos#zenith`. The agent
attempted this non-interactively, but `sudo` requires the user's password.
- After activation, open Walker with `Super+Space`, search for a repository,
launch it, exit Neovim, and confirm the same Kitty window leaves a usable
shell in that repository. Also launch Actual and WhatsApp once from Walker.
- Press `Super+N`, confirm today's file opens under `sync/notes/daily` with the
cursor at the append position, and briefly check the copied work notes and
merged `sync/notes/todo.md`. Then tell the agent whether the old
`sync/work/notes` rollback copy may be removed.
- Run the bounded Pinta trial using a recent real edit: clipboard/open,
selection, crop/resize/canvas, text/drawing/shapes, layers/transparency,
basic adjustments, and PNG/JPEG export. Tell the agent whether it fully
replaces GIMP; one of the two will then be removed.
- Install Outlook from its signed-in page as a Vivaldi web app, then tell the
agent so its generated desktop entry can be identified and replaced by a
stable Home Manager owner.
- During a docked Zenith session, tell the agent the external display is
attached so its stable identity and the two-output `Super+A` pilot can be
completed. The current session exposes only `eDP-1`.
- After activation, launch Evolution and add accounts without removing any
existing client or changing authority: personal and old-personal through
their existing IMAP/SMTP service, university and work through the
`Microsoft 365` account type, and Radicale through native CalDAV, CardDAV,
and VTODO. Complete tenant consent/sign-in when prompted, then tell the agent
which accounts connected; the full mail/calendar/contact/task gate remains
a daily-use pilot rather than a one-time setup claim.
- Rotate the exposed Context7 key and provide `CONTEXT7_API_KEY` through a - Rotate the exposed Context7 key and provide `CONTEXT7_API_KEY` through a
mode-0600 machine-local environment file on each workstation before removing mode-0600 machine-local environment file on each workstation before removing
@@ -59,16 +98,27 @@ and add no abstraction without a demonstrated repeated need.
`just openapi-refresh test`; the current test deployment returns 404. `just openapi-refresh test`; the current test deployment returns 404.
- Populate the ignored API HTTP credentials and perform the planned login plus - Populate the ignored API HTTP credentials and perform the planned login plus
harmless administrator read; no credential-bearing request has been made. harmless administrator read; no credential-bearing request has been made.
- Activate the follow-up Garden shell fix. The Nix-owned `gardenctl`, - The next Zenith switch also activates the follow-up Garden shell fix. The
`gardenlogin`, and `kubectl-gardenlogin` are verified under Nix-owned `gardenctl`, `gardenlogin`, and `kubectl-gardenlogin` are verified
`~/.nix-profile/bin`; afterward remove the duplicate mutable binaries under `~/.nix-profile/bin`; afterward remove the duplicate mutable binaries
`~/.garden/gardenctl` and `~/.local/bin/{gardenctl,gardenlogin,kubectl-gardenlogin}`. `~/.garden/gardenctl` and `~/.local/bin/{gardenctl,gardenlogin,kubectl-gardenlogin}`.
- Restrict `~/sync/yookr-vpn.ovpn` to mode 0600, then import it separately on
Zenith and Polaris as the root-owned NetworkManager connection `Yookr VPN`
with autoconnect disabled. The profile contents have not been inspected.
- Destructive cleanup, credentials, activation, and empirical pilot decisions - Destructive cleanup, credentials, activation, and empirical pilot decisions
will be surfaced here before use. will be surfaced here before use.
## Deferred Polaris replication
Do not access or test Polaris during this implementation. Treat a Zenith pass
as representative, but retain these machine-local steps for later execution on
Polaris:
1. Activate this NixOS configuration so `networkmanager-openvpn` is installed.
2. Run `chmod 600 ~/sync/yookr-vpn.ovpn`.
3. Run `nmcli connection import type openvpn file ~/sync/yookr-vpn.ovpn`.
4. Rename the imported `yookr-vpn` connection to `Yookr VPN`, disable
autoconnect, and add the required legacy cipher:
`nmcli connection modify yookr-vpn connection.id "Yookr VPN" connection.autoconnect no +vpn.data data-ciphers=AES-256-CBC`.
5. Connect with `nmcli connection up "Yookr VPN"`.
## Decisions and discoveries ## Decisions and discoveries
- Use `/home/kiri/work/repos/yookr-dashboard-new` as the reconciliation base; - Use `/home/kiri/work/repos/yookr-dashboard-new` as the reconciliation base;
@@ -136,8 +186,58 @@ and add no abstraction without a demonstrated repeated need.
`KUBECONFIG`. Completion is now store-owned, and the child recipe initializes `KUBECONFIG`. Completion is now store-owned, and the child recipe initializes
Garden's session-local `KUBECONFIG` before targeting instead of unsetting it. Garden's session-local `KUBECONFIG` before targeting instead of unsetting it.
- NetworkManager's native OpenVPN plugin is declared on Zenith and Polaris; - NetworkManager's native OpenVPN plugin is declared on Zenith and Polaris;
no profile is embedded in Nix or imported automatically. OpenVPN 3 remains no profile is embedded in Nix or imported automatically.
available as the migration fallback until both hosts pass the VPN gate. - Zenith's initial NetworkManager activation never established a tunnel:
OpenVPN 2.6 preserved the profile's legacy `cipher=AES-256-CBC` setting but
excluded it from cipher negotiation. Adding `data-ciphers=AES-256-CBC` to
the imported connection fixes the negotiation; NetworkManager then installs
the pushed tunnel address, default route, private routes, and DNS servers.
Company database access, disconnect/reconnect, suspend, and reboot pass on
Zenith, so OpenVPN 3 is retired.
- For the entire workflow implementation, do not access or test Polaris.
Zenith results are accepted for both workstations; preserve exact deferred
Polaris replication steps instead.
- OpenVPN 3 is removed from the configuration. A full Zenith system build
passes; the next password-authorized system switch removes it from the live
generation.
- Walker's native cached Lua menu scans the four identity roots and refreshes
when their top level changes. Its default action pipes the selected path to
one Nix-owned `open-project` command, which starts Neovim in a detached Kitty
window and leaves an interactive shell after Neovim exits. The generated
Walker configuration extends, rather than copies or replaces, the pinned
default provider list and prefixes.
- Removed the decided Niri arrow/Page Up/Down/numbered duplicates, direct quit
and monitor-power bindings, extra screenshot modes, first/last and centering
actions, repeated resize families, and their four shortcut-only scripts. The
existing `Super+A` helper remains until a two-output session can validate its
bounded name-based replacement.
- Home Manager now owns the existing Vivaldi launcher filenames for Actual and
WhatsApp, so both invoke the current package with the `Default` profile and
stable app ID. Outlook is not installed yet, so no ID was guessed.
- The first `nixos-maintainer` skill is instruction-only, Nix-owned, and passes
the skill-creator validator. It encodes repository-specific ownership,
research, formatting, no-switch, and affected-host validation behavior
without duplicating generic agent guidance or adding scripts.
- Removed Zed, the inactive Helix modules and note integration, Helix's cache
settings and complete lock subgraph, and inactive Foot modules. Neovim and
Kitty remain the sole declared editor and terminal. A repository-wide search
found no configured npm caller, so global Node.js and Bun are also removed;
project shells retain language runtimes where needed.
- Pinta is added beside GIMP only for its bounded trial; neither outcome is
preselected before real editing evidence.
- `sync/notes` is now the sole declarative notebook owner, with `daily`,
`meetings`, and `transcripts` directories, a native `zk daily` alias, and a
`Super+N` dedicated Kitty/Neovim launcher. The five unique authored work notes
were copied byte-for-byte, and both distinct todo lists were merged without
dropping an item. Syncthing returned to idle with no needed files, pull
errors, or new conflicts. The entire source notebook remains as rollback;
pre-merge todo copies are also retained in `/tmp/workflow-notes-todo-before.md`
and `/tmp/workflow-work-notes-todo-before.md` until the activated check passes.
- Evolution 3.60.2 is composed through Nixpkgs with `evolution-ews` 3.60.2,
whose pinned source contains the separate native Microsoft 365 mail,
calendar, contacts, recurrence, and OAuth backends. It is installed only as
a pilot beside Thunderbird; no account is preconfigured and no authority is
changed.
- Named database connections and a Marimo-to-HTML report remain workbench - Named database connections and a Marimo-to-HTML report remain workbench
evaluation evidence, not scaffolding requirements. Add them only for a real evaluation evidence, not scaffolding requirements. Add them only for a real
cross-system investigation that gives the queries and report durable value. cross-system investigation that gives the queries and report durable value.
Generated
+9 -66
View File
@@ -114,25 +114,6 @@
"type": "github" "type": "github"
} }
}, },
"helix": {
"inputs": {
"nixpkgs": "nixpkgs",
"rust-overlay": "rust-overlay"
},
"locked": {
"lastModified": 1784822617,
"narHash": "sha256-IYDL6Vnf13Sa+wbeXZTAxvdLA4h8Ew5ha0spcJy/Yk0=",
"owner": "helix-editor",
"repo": "helix",
"rev": "079a789e8cb08ead67f19e1971a1b7438b37354b",
"type": "github"
},
"original": {
"owner": "helix-editor",
"repo": "helix",
"type": "github"
}
},
"home-manager": { "home-manager": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@@ -234,7 +215,7 @@
}, },
"nixos-hardware": { "nixos-hardware": {
"inputs": { "inputs": {
"nixpkgs": "nixpkgs_2" "nixpkgs": "nixpkgs"
}, },
"locked": { "locked": {
"lastModified": 1788335262, "lastModified": 1788335262,
@@ -253,18 +234,15 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1775036866, "lastModified": 1767892417,
"narHash": "sha256-ZojAnPuCdy657PbTq5V0Y+AHKhZAIwSIT2cb8UgAz/U=", "narHash": "sha256-8bW3q88CEg2u4hSP66Vf4lpbLonHz7hqDNBMcCY7E9U=",
"owner": "nixos", "rev": "3497aa5c9457a9d88d71fa93a4a8368816fbeeba",
"repo": "nixpkgs", "type": "tarball",
"rev": "6201e203d09599479a3b3450ed24fa81537ebc4e", "url": "https://releases.nixos.org/nixos/unstable/nixos-26.05pre924538.3497aa5c9457/nixexprs.tar.xz"
"type": "github"
}, },
"original": { "original": {
"owner": "nixos", "type": "tarball",
"ref": "nixos-unstable", "url": "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz"
"repo": "nixpkgs",
"type": "github"
} }
}, },
"nixpkgs-lib": { "nixpkgs-lib": {
@@ -283,19 +261,6 @@
} }
}, },
"nixpkgs_2": { "nixpkgs_2": {
"locked": {
"lastModified": 1767892417,
"narHash": "sha256-8bW3q88CEg2u4hSP66Vf4lpbLonHz7hqDNBMcCY7E9U=",
"rev": "3497aa5c9457a9d88d71fa93a4a8368816fbeeba",
"type": "tarball",
"url": "https://releases.nixos.org/nixos/unstable/nixos-26.05pre924538.3497aa5c9457/nixexprs.tar.xz"
},
"original": {
"type": "tarball",
"url": "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz"
}
},
"nixpkgs_3": {
"locked": { "locked": {
"lastModified": 1788400875, "lastModified": 1788400875,
"narHash": "sha256-v4ZEET1Ah1K9+wMaIwPH/JTQK3MwW/gZC/SyjnlBX74=", "narHash": "sha256-v4ZEET1Ah1K9+wMaIwPH/JTQK3MwW/gZC/SyjnlBX74=",
@@ -333,40 +298,18 @@
"disko": "disko", "disko": "disko",
"elephant": "elephant", "elephant": "elephant",
"flake-parts": "flake-parts", "flake-parts": "flake-parts",
"helix": "helix",
"home-manager": "home-manager", "home-manager": "home-manager",
"import-tree": "import-tree", "import-tree": "import-tree",
"llm-agents": "llm-agents", "llm-agents": "llm-agents",
"nix-index-database": "nix-index-database", "nix-index-database": "nix-index-database",
"nix-wrapper-modules": "nix-wrapper-modules", "nix-wrapper-modules": "nix-wrapper-modules",
"nixos-hardware": "nixos-hardware", "nixos-hardware": "nixos-hardware",
"nixpkgs": "nixpkgs_3", "nixpkgs": "nixpkgs_2",
"noctalia": "noctalia", "noctalia": "noctalia",
"sops-nix": "sops-nix", "sops-nix": "sops-nix",
"walker": "walker" "walker": "walker"
} }
}, },
"rust-overlay": {
"inputs": {
"nixpkgs": [
"helix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1775358767,
"narHash": "sha256-f2eC+WIfhjevCPQILuV08i/kmKZzYZpUvkom/33VxCA=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "20fd44bc663daa53a2575e01293e24e681d62244",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"sops-nix": { "sops-nix": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
-1
View File
@@ -7,7 +7,6 @@
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
flake-parts.url = "github:hercules-ci/flake-parts"; flake-parts.url = "github:hercules-ci/flake-parts";
helix.url = "github:helix-editor/helix";
home-manager = { home-manager = {
url = "github:nix-community/home-manager"; url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
+2
View File
@@ -132,5 +132,7 @@ in
Every action must justify its context. Minimize tools and skills; prefer targeted queries and bounded output. Ask for readily available large output instead of retrieving it. Every action must justify its context. Minimize tools and skills; prefer targeted queries and bounded output. Ask for readily available large output instead of retrieving it.
''; '';
home.file.".codex/skills/nixos-maintainer/SKILL.md".source = ./skills/nixos-maintainer/SKILL.md;
}; };
} }
+37 -2
View File
@@ -23,9 +23,17 @@
}; };
flake.modules.homeManager.vivaldi = flake.modules.homeManager.vivaldi =
{ lib, pkgs, ... }: {
config,
lib,
pkgs,
...
}:
let let
command = lib.getExe pkgs.vivaldi; command = lib.getExe pkgs.vivaldi;
appCommand = id: "${command} --profile-directory=Default --app-id=${id}";
actualId = "ahoihnifhakgijcmjlhbcgehigihinlo";
whatsappId = "hnpfjngllnobngcgfapefoaidbinmjnm";
in in
{ {
desktop.commands.browser = [ command ]; desktop.commands.browser = [ command ];
@@ -33,7 +41,33 @@
packages = [ pkgs.vivaldi ]; packages = [ pkgs.vivaldi ];
sessionVariables.BROWSER = command; sessionVariables.BROWSER = command;
}; };
xdg.mimeApps.defaultApplicationPackages = [ pkgs.vivaldi ]; xdg = {
desktopEntries = {
"vivaldi-${actualId}-Default" = {
name = "Actual";
exec = appCommand actualId;
icon = "vivaldi-${actualId}-Default";
settings.StartupWMClass = "crx_${actualId}";
actions = {
Accounts.exec = "${appCommand actualId} --app-launch-url-for-shortcuts-menu-item=${config.facts.services.actual.origin}/accounts";
"Add-Transaction" = {
name = "Add Transaction";
exec = "${appCommand actualId} --app-launch-url-for-shortcuts-menu-item=${config.facts.services.actual.origin}/transactions/new";
};
Reports.exec = "${appCommand actualId} --app-launch-url-for-shortcuts-menu-item=${config.facts.services.actual.origin}/reports";
};
};
"vivaldi-${whatsappId}-Default" = {
name = "WhatsApp Web";
exec = appCommand whatsappId;
icon = "vivaldi-${whatsappId}-Default";
settings.StartupWMClass = "crx_${whatsappId}";
};
};
mimeApps.defaultApplicationPackages = [ pkgs.vivaldi ];
};
}; };
flake.modules.homeManager.nautilus = flake.modules.homeManager.nautilus =
@@ -120,6 +154,7 @@
dbeaver-bin dbeaver-bin
onlyoffice-desktopeditors onlyoffice-desktopeditors
obsidian obsidian
pinta
]; ];
}; };
-2
View File
@@ -43,7 +43,6 @@
kubelogin-oidc kubelogin-oidc
mongodb-compass mongodb-compass
scc scc
nodejs
mariadb mariadb
just just
gardenctl gardenctl
@@ -57,7 +56,6 @@
programs.jujutsu.enable = true; programs.jujutsu.enable = true;
programs.jq.enable = true; programs.jq.enable = true;
programs.bun.enable = true;
programs.ripgrep.enable = true; programs.ripgrep.enable = true;
programs.k9s.enable = true; programs.k9s.enable = true;
-170
View File
@@ -1,170 +0,0 @@
{ config, inputs, ... }:
let
homeModules = config.flake.modules.homeManager;
in
{
flake.modules.nixos.helix-cache = {
nix.settings = {
extra-substituters = [ "https://helix.cachix.org" ];
extra-trusted-public-keys = [
"helix.cachix.org-1:ejp9KQpR1FBI2onstMQ34yogDm4OgU2ru6lIwPvuCVs="
];
};
};
flake.modules.homeManager.helix =
{ pkgs, ... }:
let
svelteLanguageServer = (import ./_svelte-language-server.nix { inherit pkgs; }).overrideAttrs (
_: previousAttrs: {
postInstall = (previousAttrs.postInstall or "") + ''
# @vscode/emmet-helper only enables JSX expansion for JSX syntax;
# Helix's Svelte HTML regions also need it for HTML syntax.
substituteInPlace \
"$out/lib/node_modules/svelte-language-server/packages/language-server/node_modules/@vscode/emmet-helper/lib/cjs/emmetHelper.js" \
--replace-fail \
"'jsx.enabled': syntax === 'jsx'," \
"'jsx.enabled': syntax === 'jsx' || syntax === 'html',"
'';
}
);
in
{
programs.helix = {
enable = true;
package = inputs.helix.packages.${pkgs.stdenv.hostPlatform.system}.default;
extraPackages = with pkgs; [
vtsls
svelteLanguageServer
tailwindcss-language-server
nixd
nixfmt
oxfmt
simple-completion-language-server
odin
ols
rust-analyzer
rustfmt
cargo
zig
zls
lldb
];
settings = {
theme = "kanagawa-custom";
editor = {
soft-wrap.enable = true;
lsp = {
auto-document-highlight = true;
display-inlay-hints = false;
};
rainbow-brackets = true;
line-number = "relative";
cursorline = true;
gutters = [
"code-action-hint"
"diagnostics"
"spacer"
"line-numbers"
"spacer"
"diff"
];
color-modes = true;
cursor-shape = {
insert = "bar";
normal = "block";
select = "underline";
};
};
};
themes.kanagawa-custom = {
inherits = "kanagawa";
"ui.highlight".underline = {
color = "dragonBlue";
style = "line";
};
};
languages = {
language-server.scls = {
command = "simple-completion-language-server";
environment.SNIPPETS_PATH = "${pkgs.vimPlugins.friendly-snippets}/snippets";
};
language-server.vtsls.config.vtsls.autoUseWorkspaceTsdk = true;
language = [
{
name = "javascript";
language-servers = [
"vtsls"
"scls"
];
auto-format = true;
}
{
name = "jsx";
language-servers = [
"vtsls"
"scls"
];
auto-format = true;
}
{
name = "typescript";
language-servers = [
"vtsls"
"scls"
];
auto-format = true;
}
{
name = "tsx";
language-servers = [
"vtsls"
"scls"
];
auto-format = true;
}
{
name = "svelte";
formatter = {
command = "${pkgs.coreutils}/bin/env";
args = [
"NODE_PATH=%{workspace_directory}/node_modules"
"oxfmt"
"--stdin-filepath=%{buffer_name}"
];
};
auto-format = true;
language-servers = [
"scls"
"svelteserver"
"tailwindcss-ls"
];
}
{
name = "nix";
auto-format = true;
}
{
name = "rust";
auto-format = true;
}
];
};
};
};
flake.modules.homeManager.primary-editor-helix = {
imports = [ homeModules.helix ];
programs.helix.defaultEditor = true;
};
}
-1
View File
@@ -15,7 +15,6 @@ in
{ pkgs, ... }: { pkgs, ... }:
{ {
networking.networkmanager.plugins = [ pkgs.networkmanager-openvpn ]; networking.networkmanager.plugins = [ pkgs.networkmanager-openvpn ];
programs.openvpn3.enable = true;
services.resolved.enable = true; services.resolved.enable = true;
}; };
+4 -82
View File
@@ -14,31 +14,15 @@
spawn = browser; spawn = browser;
_props.hotkey-overlay-title = "Browser"; _props.hotkey-overlay-title = "Browser";
}; };
"Mod+N" = {
spawn-sh = "open-daily-note";
_props.hotkey-overlay-title = "Daily Note";
};
"Mod+Space" = { "Mod+Space" = {
_props.repeat = false; _props.repeat = false;
spawn = launcher; spawn = launcher;
_props.hotkey-overlay-title = "App Launcher"; _props.hotkey-overlay-title = "App Launcher";
}; };
"Mod+Ctrl+Return" = {
_props.repeat = false;
spawn = shortcutCommands.nixosTerminal;
_props.hotkey-overlay-title = "NixOS Config Terminal";
};
"Mod+Ctrl+Shift+Return" = {
_props.repeat = false;
spawn = shortcutCommands.nixosSwitch;
_props.hotkey-overlay-title = "NixOS Switch";
};
"Mod+Ctrl+E" = {
_props.repeat = false;
spawn = shortcutCommands.editSecrets;
_props.hotkey-overlay-title = "Edit Secrets";
};
"Mod+Ctrl+C" = {
_props.repeat = false;
spawn = shortcutCommands.pickColor;
_props.hotkey-overlay-title = "Pick Color";
};
# Hardware media, volume, and brightness keys # Hardware media, volume, and brightness keys
"XF86AudioPlay" = { "XF86AudioPlay" = {
@@ -84,11 +68,8 @@
# Screenshots # Screenshots
"Mod+S".screenshot = { }; "Mod+S".screenshot = { };
"Mod+Ctrl+S".screenshot-screen = { };
"Mod+Alt+S".screenshot-window = { };
# Session and compositor controls # Session and compositor controls
"Mod+Shift+Slash".show-hotkey-overlay = { };
"Mod+Escape" = { "Mod+Escape" = {
toggle-keyboard-shortcuts-inhibit = { }; toggle-keyboard-shortcuts-inhibit = { };
_props.allow-inhibiting = false; _props.allow-inhibiting = false;
@@ -97,9 +78,6 @@
spawn-sh = "loginctl lock-session"; spawn-sh = "loginctl lock-session";
_props.hotkey-overlay-title = "Lock Screen"; _props.hotkey-overlay-title = "Lock Screen";
}; };
"Mod+Ctrl+Shift+Q".quit = { };
"Ctrl+Alt+Delete".quit = { };
"Mod+Shift+P".power-off-monitors = { };
# Overview and window close # Overview and window close
"Mod+O" = { "Mod+O" = {
@@ -112,31 +90,17 @@
}; };
# Keyboard focus movement # Keyboard focus movement
"Mod+Left".focus-column-or-monitor-left = { };
"Mod+Down".focus-window-down = { };
"Mod+Up".focus-window-up = { };
"Mod+Right".focus-column-or-monitor-right = { };
"Mod+H".focus-column-or-monitor-left = { }; "Mod+H".focus-column-or-monitor-left = { };
"Mod+J".focus-window-down = { }; "Mod+J".focus-window-down = { };
"Mod+K".focus-window-up = { }; "Mod+K".focus-window-up = { };
"Mod+L".focus-column-or-monitor-right = { }; "Mod+L".focus-column-or-monitor-right = { };
# Keyboard window and column movement # Keyboard window and column movement
"Mod+Alt+Left".move-column-left-or-to-monitor-left = { };
"Mod+Alt+Down".move-window-down-or-to-workspace-down = { };
"Mod+Alt+Up".move-window-up-or-to-workspace-up = { };
"Mod+Alt+Right".move-column-right-or-to-monitor-right = { };
"Mod+Alt+H".move-column-left-or-to-monitor-left = { }; "Mod+Alt+H".move-column-left-or-to-monitor-left = { };
"Mod+Alt+J".move-window-down-or-to-workspace-down = { }; "Mod+Alt+J".move-window-down-or-to-workspace-down = { };
"Mod+Alt+K".move-window-up-or-to-workspace-up = { }; "Mod+Alt+K".move-window-up-or-to-workspace-up = { };
"Mod+Alt+L".move-column-right-or-to-monitor-right = { }; "Mod+Alt+L".move-column-right-or-to-monitor-right = { };
# First and last column navigation
"Mod+Home".focus-column-first = { };
"Mod+End".focus-column-last = { };
"Mod+Alt+Home".move-column-to-first = { };
"Mod+Alt+End".move-column-to-last = { };
# Move focus, columns, and workspaces across monitors # Move focus, columns, and workspaces across monitors
"Mod+Tab".focus-monitor-next = { }; "Mod+Tab".focus-monitor-next = { };
"Mod+A" = { "Mod+A" = {
@@ -147,26 +111,15 @@
"Mod+Alt+Tab".move-column-to-monitor-next = { }; "Mod+Alt+Tab".move-column-to-monitor-next = { };
"Mod+Shift+Tab".move-workspace-to-monitor-next = { }; "Mod+Shift+Tab".move-workspace-to-monitor-next = { };
"Mod+Shift+Left".focus-monitor-left = { };
"Mod+Shift+Down".focus-monitor-down = { };
"Mod+Shift+Up".focus-monitor-up = { };
"Mod+Shift+Right".focus-monitor-right = { };
# Linear workspace navigation # Linear workspace navigation
"Mod+Page_Down".focus-workspace-down = { };
"Mod+Page_Up".focus-workspace-up = { };
"Mod+U".focus-workspace-down = { }; "Mod+U".focus-workspace-down = { };
"Mod+I".focus-workspace-up = { }; "Mod+I".focus-workspace-up = { };
# Move columns between adjacent workspaces # Move columns between adjacent workspaces
"Mod+Alt+Page_Down".move-column-to-workspace-down = { };
"Mod+Alt+Page_Up".move-column-to-workspace-up = { };
"Mod+Alt+U".move-column-to-workspace-down = { }; "Mod+Alt+U".move-column-to-workspace-down = { };
"Mod+Alt+I".move-column-to-workspace-up = { }; "Mod+Alt+I".move-column-to-workspace-up = { };
# Reorder workspaces # Reorder workspaces
"Mod+Shift+Page_Down".move-workspace-down = { };
"Mod+Shift+Page_Up".move-workspace-up = { };
"Mod+Shift+U".move-workspace-down = { }; "Mod+Shift+U".move-workspace-down = { };
"Mod+Shift+I".move-workspace-up = { }; "Mod+Shift+I".move-workspace-up = { };
@@ -196,28 +149,6 @@
"Mod+Shift+WheelScrollDown".focus-column-or-monitor-right = { }; "Mod+Shift+WheelScrollDown".focus-column-or-monitor-right = { };
"Mod+Shift+WheelScrollUp".focus-column-or-monitor-left = { }; "Mod+Shift+WheelScrollUp".focus-column-or-monitor-left = { };
# Direct workspace focus
"Mod+1".focus-workspace = 1;
"Mod+2".focus-workspace = 2;
"Mod+3".focus-workspace = 3;
"Mod+4".focus-workspace = 4;
"Mod+5".focus-workspace = 5;
"Mod+6".focus-workspace = 6;
"Mod+7".focus-workspace = 7;
"Mod+8".focus-workspace = 8;
"Mod+9".focus-workspace = 9;
# Move columns to numbered workspaces
"Mod+Ctrl+1".move-column-to-workspace = 1;
"Mod+Ctrl+2".move-column-to-workspace = 2;
"Mod+Ctrl+3".move-column-to-workspace = 3;
"Mod+Ctrl+4".move-column-to-workspace = 4;
"Mod+Ctrl+5".move-column-to-workspace = 5;
"Mod+Ctrl+6".move-column-to-workspace = 6;
"Mod+Ctrl+7".move-column-to-workspace = 7;
"Mod+Ctrl+8".move-column-to-workspace = 8;
"Mod+Ctrl+9".move-column-to-workspace = 9;
# Add and remove windows from columns # Add and remove windows from columns
"Mod+BracketLeft".consume-or-expel-window-left = { }; "Mod+BracketLeft".consume-or-expel-window-left = { };
"Mod+BracketRight".consume-or-expel-window-right = { }; "Mod+BracketRight".consume-or-expel-window-right = { };
@@ -226,23 +157,14 @@
# Column and window presentation modes # Column and window presentation modes
"Mod+R".switch-preset-column-width = { }; "Mod+R".switch-preset-column-width = { };
"Mod+Shift+R".switch-preset-column-width-back = { };
"Mod+Ctrl+R".reset-window-height = { };
"Mod+Ctrl+Shift+R".switch-preset-window-height = { };
"Mod+F".maximize-column = { }; "Mod+F".maximize-column = { };
"Mod+Shift+F".fullscreen-window = { }; "Mod+Shift+F".fullscreen-window = { };
"Mod+M".maximize-window-to-edges = { };
"Mod+C".center-column = { };
# Manual column width and window height adjustments # Manual column width and window height adjustments
"Mod+Shift+H".set-column-width = "-10%"; "Mod+Shift+H".set-column-width = "-10%";
"Mod+Shift+L".set-column-width = "+10%"; "Mod+Shift+L".set-column-width = "+10%";
"Mod+Shift+J".set-window-height = "+10%"; "Mod+Shift+J".set-window-height = "+10%";
"Mod+Shift+K".set-window-height = "-10%"; "Mod+Shift+K".set-window-height = "-10%";
"Mod+Minus".set-column-width = "-10%";
"Mod+Equal".set-column-width = "+10%";
"Mod+Shift+Minus".set-window-height = "-10%";
"Mod+Shift+Equal".set-window-height = "+10%";
# Floating and tabbed layout toggles # Floating and tabbed layout toggles
"Mod+Alt+V".toggle-window-floating = { }; "Mod+Alt+V".toggle-window-floating = { };
-92
View File
@@ -1,101 +1,9 @@
{ {
config,
lib, lib,
pkgs, pkgs,
}: }:
let
nixosConfigDir = config.facts.account.nixosConfigurationPath;
mkTerminalScript =
{
name,
workdir ? nixosConfigDir,
command ? null,
runtimeInputs ? [ ],
}:
let
args = lib.optionals (command != null) [
"--"
"${pkgs.bash}/bin/bash"
"-lc"
command
];
argString = lib.concatMapStringsSep " " lib.escapeShellArg args;
in
pkgs.writeShellApplication {
inherit name runtimeInputs;
checkPhase = "";
text = lib.concatStringsSep "\n" [
"# shellcheck disable=SC2016"
"cd ${lib.escapeShellArg workdir}"
"exec ${lib.escapeShellArgs config.desktop.commands.terminal} ${argString}"
];
};
in
rec { rec {
scripts = { scripts = {
nixosTerminal = mkTerminalScript {
name = "niri-shortcut-nixos-terminal";
};
nixosSwitch = mkTerminalScript {
name = "niri-shortcut-nixos-switch";
runtimeInputs = [
pkgs.coreutils
pkgs.nh
];
command = ''
set -o pipefail
log_dir="''${XDG_STATE_HOME:-$HOME/.local/state}/nixos-switch"
mkdir -p "$log_dir"
log="$log_dir/$(date +%Y%m%d-%H%M%S).log"
status_file="$(mktemp)"
printf 'Running nh os switch in %s\n\n' ${lib.escapeShellArg nixosConfigDir}
(
cd ${lib.escapeShellArg nixosConfigDir}
nh os switch
printf '%s' "$?" > "$status_file"
) 2>&1 | tee "$log"
status="$(cat "$status_file")"
rm -f "$status_file"
printf '\nLog: %s\n' "$log"
if [ "$status" -eq 0 ]; then
printf 'NixOS switch completed successfully.\n'
else
printf 'NixOS switch failed with exit code %s.\n' "$status"
fi
printf 'Press Enter to close...'
read -r _
exit "$status"
'';
};
editSecrets = mkTerminalScript {
name = "niri-shortcut-edit-secrets";
runtimeInputs = [ pkgs.sops ];
command = ''
sops edit ${lib.escapeShellArg "${nixosConfigDir}/modules/secrets/secrets.yaml"}
'';
};
pickColor = pkgs.writeShellApplication {
name = "niri-shortcut-pick-color";
runtimeInputs = [
pkgs.libnotify
pkgs.niri
pkgs.wl-clipboard
];
text = ''
color="$(niri msg pick-color)"
printf '%s' "$color" | wl-copy
notify-send 'Color picked' "$color"
'';
};
swapMonitorWorkspaces = pkgs.writeShellApplication { swapMonitorWorkspaces = pkgs.writeShellApplication {
name = "niri-shortcut-swap-monitor-workspaces"; name = "niri-shortcut-swap-monitor-workspaces";
runtimeInputs = [ runtimeInputs = [
-1
View File
@@ -31,7 +31,6 @@ in
palette = kanagawa.palette; palette = kanagawa.palette;
shortcuts = import ./_shortcuts.nix { shortcuts = import ./_shortcuts.nix {
inherit inherit
config
lib lib
pkgs pkgs
; ;
+27 -26
View File
@@ -19,6 +19,17 @@ in
[tool] [tool]
fzf-preview = "bat --plain --color=always {-1}" fzf-preview = "bat --plain --color=always {-1}"
[group.daily]
paths = ["daily"]
[group.daily.note]
filename = "{{format-date now '%Y-%m-%d'}}"
extension = "md"
template = "daily.md"
[alias]
daily = 'nvim + "$(zk new --no-input --print-path "$ZK_NOTEBOOK_DIR/daily")"'
''; '';
noteTemplate = '' noteTemplate = ''
--- ---
@@ -27,49 +38,39 @@ in
# {{title}} # {{title}}
''; '';
openDailyNote = pkgs.writeShellApplication {
name = "open-daily-note";
text = ''
exec ${lib.getExe config.programs.kitty.package} --detach \
--directory "${home}/sync/notes" \
${lib.getExe pkgs.zsh} -lic 'zk daily'
'';
};
in in
{ {
home.packages = with pkgs; [ home.packages = [
ripgrep-all openDailyNote
zk pkgs.ripgrep-all
pkgs.zk
]; ];
home.file = { home.file = {
"sync/notes/.zk/config.toml".text = zkConfig; "sync/notes/.zk/config.toml".text = zkConfig;
"sync/notes/.zk/templates/daily.md".text = "";
"sync/notes/.zk/templates/default.md".text = noteTemplate; "sync/notes/.zk/templates/default.md".text = noteTemplate;
"sync/work/notes/.zk/config.toml".text = zkConfig;
"sync/work/notes/.zk/templates/default.md".text = noteTemplate;
}; };
home.activation.createNotesLayout = lib.hm.dag.entryAfter [ "writeBoundary" ] '' home.activation.createNotesLayout = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
${pkgs.coreutils}/bin/mkdir -p \ ${pkgs.coreutils}/bin/mkdir -p \
"${home}/sync/notes/daily" \
"${home}/sync/notes/meetings" \
"${home}/sync/notes/transcripts" \ "${home}/sync/notes/transcripts" \
"${home}/sync/recordings/inbox" \ "${home}/sync/recordings/inbox" \
"${home}/sync/recordings/processing" \ "${home}/sync/recordings/processing" \
"${home}/sync/recordings/archive" \ "${home}/sync/recordings/archive" \
"${home}/sync/recordings/failed" \ "${home}/sync/recordings/failed"
"${home}/sync/work/notes/meetings" \
"${home}/sync/work/notes/transcripts" \
"${home}/sync/work/recordings/inbox" \
"${home}/sync/work/recordings/processing" \
"${home}/sync/work/recordings/archive" \
"${home}/sync/work/recordings/failed"
''; '';
programs.helix.languages = {
language-server.zk = {
command = lib.getExe pkgs.zk;
args = [ "lsp" ];
};
language = [
{
name = "markdown";
roots = [ ".zk" ];
language-servers = [ "zk" ];
}
];
};
}; };
flake.modules.nixos.notes = flake.modules.nixos.notes =
+7
View File
@@ -12,6 +12,7 @@ in
{ {
config, config,
lib, lib,
pkgs,
... ...
}: }:
let let
@@ -66,6 +67,12 @@ in
}; };
in in
{ {
home.packages = [
(pkgs.evolutionWithPlugins.override {
plugins = [ pkgs.evolution-ews ];
})
];
programs.thunderbird = { programs.thunderbird = {
enable = true; enable = true;
profiles.${config.home.username} = { profiles.${config.home.username} = {
@@ -0,0 +1,29 @@
---
name: nixos-maintainer
description: Maintain this NixOS and Home Manager flake by inspecting, changing, simplifying, or validating its configuration. Use for system configuration work in the NixOS repository, not generic Nix questions or unrelated projects.
---
# NixOS Maintainer
Read the applicable `AGENTS.md` and the complete current owner of the behavior
before editing. Trace its imports through the host, profile, and capability
modules so the change lands at the narrowest shared level that matches its real
scope.
Prefer an existing module or native NixOS/Home Manager option. Keep mutable,
secret, credential, and application-owned state outside the Nix store. Verify
unfamiliar pinned interfaces against the exact package source or current primary
documentation.
Preserve unrelated work in a dirty tree. Make the smallest complete change,
format touched Nix files with the repository formatter, and validate only the
affected hosts. Ordinarily run:
```sh
nix flake check --no-build --quiet
nix build --no-link --quiet .#nixosConfigurations.<host>.config.system.build.toplevel
```
Start with a narrower evaluation when it can fail faster. Inspect targeted
failure logs only. Do not switch or boot a generation unless the user explicitly
requests activation.
-77
View File
@@ -19,70 +19,6 @@ let
in in
{ {
flake.modules.homeManager.terminal-foot =
{
lib,
pkgs,
...
}:
let
palette = kanagawa.palette;
hex = lib.removePrefix "#";
in
{
programs.foot = {
enable = true;
settings = {
main = {
font = "JetBrains Mono:style=Medium:size=11:fontfeatures=-liga:fontfeatures=-calt";
font-bold = "JetBrains Mono:style=Bold:size=11:fontfeatures=-liga:fontfeatures=-calt";
font-italic = "JetBrains Mono:style=Medium Italic:size=11:fontfeatures=-liga:fontfeatures=-calt";
font-bold-italic = "JetBrains Mono:style=Bold Italic:size=11:fontfeatures=-liga:fontfeatures=-calt";
gamma-correct-blending = "yes";
pad = "3x3";
};
tweak.box-drawing-base-thickness = 0.1;
bell.system = "no";
scrollback.lines = 10000;
text-bindings."\\x0a" = "Shift+Return Shift+KP_Enter";
colors-dark = {
background = hex palette.background;
foreground = hex palette.foreground;
selection-background = hex palette.selectionBackground;
selection-foreground = hex palette.selectionForeground;
urls = hex palette.url;
cursor = "${hex palette.background} ${hex palette.cursor}";
regular0 = hex palette.terminal.color0;
regular1 = hex palette.terminal.color1;
regular2 = hex palette.terminal.color2;
regular3 = hex palette.terminal.color3;
regular4 = hex palette.terminal.color4;
regular5 = hex palette.terminal.color5;
regular6 = hex palette.terminal.color6;
regular7 = hex palette.terminal.color7;
bright0 = hex palette.terminal.color8;
bright1 = hex palette.terminal.color9;
bright2 = hex palette.terminal.color10;
bright3 = hex palette.terminal.color11;
bright4 = hex palette.terminal.color12;
bright5 = hex palette.terminal.color13;
bright6 = hex palette.terminal.color14;
bright7 = hex palette.terminal.color15;
"16" = hex palette.terminal.color16;
"17" = hex palette.terminal.color17;
};
};
};
};
flake.modules.homeManager.terminal-kitty = flake.modules.homeManager.terminal-kitty =
{ pkgs, ... }: { pkgs, ... }:
let let
@@ -166,19 +102,6 @@ in
}; };
}; };
flake.modules.homeManager.primary-terminal-foot =
{ config, lib, ... }:
{
imports = [ homeModules.terminal-foot ];
desktop.commands.terminal = [ (lib.getExe config.programs.foot.package) ];
xdg.terminal-exec = {
enable = true;
settings.default = [ "foot.desktop" ];
};
};
flake.modules.homeManager.primary-terminal-kitty = flake.modules.homeManager.primary-terminal-kitty =
{ config, lib, ... }: { config, lib, ... }:
{ {
+93 -7
View File
@@ -19,8 +19,28 @@ in
}; };
flake.modules.homeManager.walker = flake.modules.homeManager.walker =
{ lib, pkgs, ... }: {
config,
lib,
pkgs,
...
}:
let let
homeDir = config.home.homeDirectory;
projectRoots =
map
(scope: {
inherit scope;
path = "${homeDir}/dev/${scope}";
})
[
"work"
"own"
"ext"
"forks"
];
walkerDefaults = builtins.fromTOML (builtins.readFile "${inputs.walker}/resources/config.toml");
launcher = pkgs.writeShellApplication { launcher = pkgs.writeShellApplication {
name = "walker-launcher"; name = "walker-launcher";
runtimeInputs = [ pkgs.libressl.nc ]; runtimeInputs = [ pkgs.libressl.nc ];
@@ -28,22 +48,88 @@ in
exec nc -U "$XDG_RUNTIME_DIR/walker/walker.sock" exec nc -U "$XDG_RUNTIME_DIR/walker/walker.sock"
''; '';
}; };
openProject = pkgs.writeShellApplication {
name = "open-project";
text = ''
project_path="''${1:-}"
if [[ -z "$project_path" ]]; then
IFS= read -r project_path
fi
cd -- "$project_path"
exec ${lib.getExe config.programs.kitty.package} --detach --directory "$PWD" \
${lib.getExe pkgs.zsh} -lic 'nvim; exec zsh -l'
'';
};
in in
{ {
imports = [ inputs.walker.homeManagerModules.default ]; imports = [ inputs.walker.homeManagerModules.default ];
desktop.commands.launcher = [ (lib.getExe launcher) ]; desktop.commands.launcher = [ (lib.getExe launcher) ];
home.packages = [ openProject ];
xdg.configFile."elephant/menus/projects.lua".text = ''
Name = "projects"
NamePretty = "Projects"
Description = "Git repositories"
Icon = "folder"
Action = "${lib.getExe openProject}"
SearchName = true
RefreshOnChange = {
${lib.concatMapStringsSep "\n " (root: ''"${root.path}",'') projectRoots}
}
local roots = {
${lib.concatMapStringsSep "\n " (
root: ''{ scope = "${root.scope}", path = "${root.path}" },''
) projectRoots}
}
local function repositories(root)
return io.popen(
"${lib.getExe pkgs.findutils} " .. root ..
" -mindepth 1 \\( -type d \\( -name .archive -o -name .worktrees \\) -prune \\)" ..
" -o \\( -name .git -print \\) 2>/dev/null"
)
end
function GetEntries()
local entries = {}
for _, root in ipairs(roots) do
local handle = repositories(root.path)
if handle then
for git_path in handle:lines() do
local project = git_path:gsub("/%.git$", "")
local relative = project:sub(#root.path + 2)
table.insert(entries, {
Text = project:match("([^/]+)$"),
Subtext = root.scope .. " · " .. relative,
Value = project,
Keywords = { root.scope, relative, project },
})
end
handle:close()
end
end
return entries
end
'';
programs.walker = { programs.walker = {
enable = true; enable = true;
runAsService = true; runAsService = true;
config.providers.prefixes = [ config.providers = {
{ default = walkerDefaults.providers.default ++ [ "menus:projects" ];
provider = "bitwarden"; prefixes = walkerDefaults.providers.prefixes ++ [
prefix = "?"; {
} provider = "bitwarden";
]; prefix = "?";
}
];
};
}; };
}; };
} }
-5
View File
@@ -1,5 +0,0 @@
{
flake.modules.homeManager.zed = {
programs.zed-editor.enable = true;
};
}
-1
View File
@@ -46,7 +46,6 @@ in
homeModules.clipboard homeModules.clipboard
homeModules.desktop-commands homeModules.desktop-commands
homeModules.dev-tools homeModules.dev-tools
homeModules.zed
homeModules.xdg homeModules.xdg
homeModules.workstation-apps homeModules.workstation-apps
homeModules.vivaldi homeModules.vivaldi