Compare commits

..
Author SHA1 Message Date
nix-update bot 81cffd22cb td: 0.38.0 -> 0.41.0
Update Nix Packages with nix-update / nix-update (push) Successful in 2m29s
Diff: https://github.com/marcus/td/compare/v0.38.0...v0.41.0
2026-03-01 03:02:14 +01:00
nix-update bot c2c0201295 sidecar: 0.74.1 -> 0.76.0
Diff: https://github.com/marcus/sidecar/compare/v0.74.1...v0.76.0

Changelog: https://github.com/marcus/sidecar/releases/tag/v0.76.0
2026-03-01 03:01:58 +01:00
nix-update bot 47cace3dd1 beads: 0.49.1 -> 0.56.1
Diff: https://github.com/steveyegge/beads/compare/v0.49.1...v0.56.1
2026-03-01 03:01:26 +01:00
nix-update bot bfa707c11d chore: update flake inputs - opencode(v1.2.15) 2026-03-01 03:00:59 +01:00
m3tm3re e22774539a chore: manual update until I find the time to fix CI/CD
Update Nix Packages with nix-update / nix-update (push) Successful in 18m47s
2026-02-25 18:52:11 +01:00
m3tm3re 166ed9e825 fix: n8n build error
Update Nix Packages with nix-update / nix-update (push) Failing after 3m13s
2026-02-21 18:30:27 +01:00
m3tm3re 5b55f47020 fix(n8n): restructure version handling for nix-update compatibility
Update Nix Packages with nix-update / nix-update (push) Failing after 4m29s
- Store version without 'n8n@' prefix (e.g., '2.8.3' not 'n8n@2.8.3')
- Construct tag with prefix: tag = "n8n@${version}"
- Update to version 2.8.3 with correct hashes

This allows nix-update to work correctly with the custom update.sh
script that strips the 'n8n@' prefix from GitHub release tags.
2026-02-20 09:47:23 +01:00
nix-update bot f95fe5bf6d td: 0.37.0 -> 0.38.0
Diff: https://github.com/marcus/td/compare/v0.37.0...v0.38.0
2026-02-20 09:03:52 +01:00
nix-update bot 34dda52d53 sidecar: 0.74.0 -> 0.74.1
Diff: https://github.com/marcus/sidecar/compare/v0.74.0...v0.74.1

Changelog: https://github.com/marcus/sidecar/releases/tag/v0.74.1
2026-02-20 09:03:38 +01:00
nix-update bot 06a40240ea notesmd-cli: 0.3.0 -> 0.3.1
Diff: https://github.com/Yakitrak/notesmd-cli/compare/v0.3.0...v0.3.1
2026-02-20 09:03:22 +01:00
nix-update bot ad0bc14461 mem0: 1.0.3 -> 1.0.4
Diff: https://github.com/mem0ai/mem0/compare/v1.0.3...v1.0.4

Changelog: https://github.com/mem0ai/mem0/releases/tag/v1.0.4
2026-02-20 09:03:04 +01:00
nix-update bot 6d262127e7 chore: update flake inputs - opencode(v1.2.9) 2026-02-20 09:02:42 +01:00
m3tm3re 839d7ae743 feat(ci): support custom update scripts for specific packages
Add detection logic to distinguish between:
- nix-update-script (standard packages like beads, td, mem0, etc.)
- Custom scripts (like n8n's update.sh that strips 'n8n@' prefix)

For custom scripts, run them directly with standard env vars:
- UPDATE_NIX_NAME, UPDATE_NIX_PNAME
- UPDATE_NIX_OLD_VERSION, UPDATE_NIX_ATTR_PATH

This ensures n8n only gets stable releases via its custom script.
2026-02-20 09:01:06 +01:00
m3tm3re 2e37c16ac7 fix(ci): resolve nix-update workflow issues
- Remove --use-update-script flag that breaks with flake-only repos
  (nix-update-script expects default.nix at repo root)
- Fix GitHub API jq filter for detecting prereleases
- Fix Summary step bash syntax for handling input variables
- Format lib/ files that were failing formatting check
2026-02-20 08:30:26 +01:00
m3tm3re 3b99d1215e fix: n8n update script 2026-02-20 08:13:46 +01:00
m3tm3re f05865972b fix(ci): dynamic flake input discovery and updateScript support
- Replace hardcoded opencode update step with dynamic discovery of all
  version-pinned flake inputs via nix flake metadata --json
- Add --use-update-script flag to nix-update command so packages with
  custom passthru.updateScript (like n8n) use their custom scripts
- Update output variables from update-opencode to update-flake-inputs
- Update Summary step to reflect new generic flake input handling
2026-02-20 07:51:21 +01:00
m3tm3re 58312b2ca2 feat: add openspec package
Update Nix Packages with nix-update / nix-update (push) Failing after 23s
2026-02-18 17:55:07 +01:00
m3tm3re dc206b13e2 feat(shells): add opencode dev shell with mkOpencodeRules demo
Update Nix Packages with nix-update / nix-update (push) Failing after 2m27s
2026-02-17 20:16:11 +01:00
m3tm3re d43bb33dcb feat(lib): add opencode-rules helper for per-project rule injection
- Create lib/opencode-rules.nix with mkOpencodeRules function
- Update lib/default.nix to import opencode-rules module
- Pattern follows ports.nix: {lib}: { mkOpencodeRules = ...; }

Refs: T2, T3 of rules-system plan
2026-02-17 18:59:43 +01:00
nix-update bot d2ec6a0474 sidecar: 0.73.1 -> 0.74.0
Update Nix Packages with nix-update / nix-update (push) Failing after 5m34s
Diff: https://github.com/marcus/sidecar/compare/v0.73.1...v0.74.0

Changelog: https://github.com/marcus/sidecar/releases/tag/v0.74.0
2026-02-17 03:18:11 +01:00
nix-update bot f69dd15474 chore: update opencode flake input to 1.2.6 2026-02-17 03:17:38 +01:00
nix-update bot c7935658e6 td: 0.36.0 -> 0.37.0
Update Nix Packages with nix-update / nix-update (push) Successful in 18m53s
Diff: https://github.com/marcus/td/compare/v0.36.0...v0.37.0
2026-02-16 03:29:20 +01:00
nix-update bot af56407296 sidecar: 0.72.0 -> 0.73.1
Diff: https://github.com/marcus/sidecar/compare/v0.72.0...v0.73.1

Changelog: https://github.com/marcus/sidecar/releases/tag/v0.73.1
2026-02-16 03:29:06 +01:00
nix-update bot 51dd2be6ea chore: update opencode flake input to 1.2.5 2026-02-16 03:28:33 +01:00
nix-update bot 6ebd7b94d5 td: 0.34.0 -> 0.36.0
Update Nix Packages with nix-update / nix-update (push) Successful in 30m36s
Diff: https://github.com/marcus/td/compare/v0.34.0...v0.36.0
2026-02-15 03:18:42 +01:00
nix-update bot 22bfba739d sidecar: 0.71.1 -> 0.72.0
Diff: https://github.com/marcus/sidecar/compare/v0.71.1...v0.72.0

Changelog: https://github.com/marcus/sidecar/releases/tag/v0.72.0
2026-02-15 03:18:28 +01:00
nix-update bot 9d27e48b2b chore: update opencode flake input to 1.2.4 2026-02-15 03:17:54 +01:00
nix-update bot 3f26c44b5a chore: update opencode flake input to 1.2.1
Update Nix Packages with nix-update / nix-update (push) Successful in 19m58s
2026-02-14 15:19:39 +01:00
m3tm3re 6775659538 chore: remove .sidecar-* files from tracking
Update Nix Packages with nix-update / nix-update (push) Successful in 20m2s
2026-02-14 07:34:08 +01:00
m3tm3re b80422c16e chore: ignore all .sidecar-* files 2026-02-14 07:31:57 +01:00
m3tm3re a6c1d7cf97 chore: add AI agent directories to gitignore 2026-02-14 07:30:35 +01:00
m3tm3re e6c22a04d7 feat: add notesmd-cli package and flake checks
- Add notesmd-cli package for Obsidian CLI interaction
- Add flake checks for package build verification
- Add documentation for notesmd-cli, sidecar, and td
- Update AGENTS.md to reference td instead of beads
- Format pkgs/default.nix with proper braces
2026-02-14 07:15:06 +01:00
nix-update bot 56a7a7bfa8 n8n: n8n@2.8.1 -> n8n@2.7.5
Diff: https://github.com/n8n-io/n8n/compare/n8n@2.8.1...n8n@2.7.5

Changelog: https://github.com/n8n-io/n8n/releases/tag/n8n@n8n@2.7.5
2026-02-14 03:02:08 +01:00
nix-update bot 42cd0849b4 n8n: n8n@2.7.4 -> n8n@2.8.1
Update Nix Packages with nix-update / nix-update (push) Successful in 8m45s
Diff: https://github.com/n8n-io/n8n/compare/n8n@2.7.4...n8n@2.8.1

Changelog: https://github.com/n8n-io/n8n/releases/tag/n8n@n8n@2.8.1
2026-02-13 06:56:31 +01:00
nix-update bot 47b622745d chore: update opencode flake input to 1.1.65 2026-02-13 06:54:31 +01:00
sascha.koenig fbeb39ec22 Merge branch 'bugfix-opencode-flake-input' 2026-02-13 06:51:03 +01:00
sascha.koenig 8ab5b4de8d fix: gitea runner opencode.url flake input 2026-02-13 06:50:44 +01:00
m3tm3re dc2f3b6802 feat: update opencode to v1.1.60 and re-enable opencode-desktop
Update Nix Packages with nix-update / nix-update (push) Failing after 1s
- Update opencode flake input to v1.1.60
- Add nixpkgs-master input for opencode (needs newer bun)
- Re-enable opencode-desktop with workaround for upstream issue #11755
- Add specta/tauri outputHashes for git dependencies
- Add .todos/ to gitignore
- Update AGENTS.md with td task management instructions
2026-02-12 19:42:11 +01:00
m3tm3re 909acf61d3 add opencode to sidecar deps
Update Nix Packages with nix-update / nix-update (push) Successful in 25s
2026-02-11 19:58:52 +01:00
m3tm3re 105629502a fix: add tmux to sidecar deps 2026-02-11 18:03:31 +01:00
nix-update bot f1fff4245f td: 0.33.0 -> 0.34.0
Diff: https://github.com/marcus/td/compare/v0.33.0...v0.34.0
2026-02-11 15:04:45 +01:00
nix-update bot d85f2df603 n8n: n8n@2.6.4 -> n8n@2.7.4
Diff: https://github.com/n8n-io/n8n/compare/n8n@2.6.4...n8n@2.7.4

Changelog: https://github.com/n8n-io/n8n/releases/tag/n8n@n8n@2.7.4
2026-02-11 15:04:27 +01:00
nix-update bot f6af27e960 chore: update opencode flake input to 1.1.57 2026-02-11 15:02:32 +01:00
nix-update bot 19456800ed sidecar: 0.71.0 -> 0.71.1
Update Nix Packages with nix-update / nix-update (push) Successful in 12m34s
Diff: https://github.com/marcus/sidecar/compare/v0.71.0...v0.71.1

Changelog: https://github.com/marcus/sidecar/releases/tag/v0.71.1
2026-02-11 03:03:29 +01:00
nix-update bot 8dac838645 chore: update opencode flake input to 1.1.56 2026-02-11 03:02:55 +01:00
sascha.koenig 644c7eac5d feat: add sidecar and td packages, fix neovim extraLuaConfig
Update Nix Packages with nix-update / nix-update (push) Successful in 4m18s
2026-02-10 08:33:38 +01:00
sascha.koenig 90a5344f62 flake.lock: Update
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/ffbc9f8cbaacfb331b6017d5a5abb21a492c9a38?narHash=sha256-1Sm77VfZh3mU0F5OqKABNLWxOuDeHIlcFjsXeeiPazs%3D' (2026-01-11)
  → 'github:NixOS/nixpkgs/d6c71932130818840fc8fe9509cf50be8c64634f?narHash=sha256-ub1gpAONMFsT/GU2hV6ZWJjur8rJ6kKxdm9IlCT0j84%3D' (2026-02-08)
2026-02-10 06:52:53 +01:00
nix-update bot 8751ef9b1f n8n: n8n@2.4.8 -> n8n@2.6.4
Update Nix Packages with nix-update / nix-update (push) Successful in 17s
Diff: https://github.com/n8n-io/n8n/compare/n8n@2.4.8...n8n@2.6.4

Changelog: https://github.com/n8n-io/n8n/releases/tag/n8n@n8n@2.6.4
2026-02-09 19:16:43 +01:00
nix-update bot de0bdd8ae3 mem0: 1.0.2 -> 1.0.3
Diff: https://github.com/mem0ai/mem0/compare/v1.0.2...v1.0.3

Changelog: https://github.com/mem0ai/mem0/releases/tag/v1.0.3
2026-02-09 19:13:14 +01:00
nix-update bot caa2fd57dd chore: update opencode flake input to 1.1.53 2026-02-09 19:12:57 +01:00
m3tm3re 62ce3dc646 fix(workflow): sequential updates with cleanup on failure
- Run nix-update sequentially instead of parallel to avoid race conditions
- Clean up uncommitted changes after failed updates (git checkout/clean)
- Simplify push logic by removing stash/pop complexity
- Remove upload-artifact@v4 (unsupported on Gitea Actions)
2026-02-09 19:12:22 +01:00
m3tm3re 3c87721011 docs: document opencode-desktop workaround (upstream #11755)
Update Nix Packages with nix-update / nix-update (push) Failing after 2m21s
2026-02-07 15:10:21 +01:00
m3tm3re 4c81a909a3 fix(workflow): add git stash and pre-push validation 2026-02-07 15:07:13 +01:00
m3tm3re 112db85fa1 fix: extraLuaConfig renamed initLua
Update Nix Packages with nix-update / nix-update (push) Successful in 2m21s
2026-02-04 20:01:54 +01:00
m3tm3re 0b08fb400e -opencode-desktop until upstream fixed 2026-02-04 19:54:06 +01:00
nix-update bot 51b8a8296c chore: update opencode flake input to 1.1.47
Update Nix Packages with nix-update / nix-update (push) Failing after 14s
2026-01-31 03:03:04 +01:00
nix-update bot be44229e5a chore: update opencode flake input to 1.1.44
Update Nix Packages with nix-update / nix-update (push) Successful in 3m11s
2026-01-30 15:02:21 +01:00
nix-update bot f203bb7463 n8n: n8n@2.4.7 -> n8n@2.4.8
Update Nix Packages with nix-update / nix-update (push) Successful in 2m29s
Diff: https://github.com/n8n-io/n8n/compare/n8n@2.4.7...n8n@2.4.8

Changelog: https://github.com/n8n-io/n8n/releases/tag/n8n@n8n@2.4.8
2026-01-30 03:03:30 +01:00
nix-update bot 12e8baadf2 chore: update opencode flake input to 1.1.43 2026-01-30 03:01:49 +01:00
nix-update bot 4232a5ccc9 n8n: n8n@2.4.6 -> n8n@2.4.7
Update Nix Packages with nix-update / nix-update (push) Successful in 9m48s
Diff: https://github.com/n8n-io/n8n/compare/n8n@2.4.6...n8n@2.4.7

Changelog: https://github.com/n8n-io/n8n/releases/tag/n8n@n8n@2.4.7
2026-01-29 15:03:48 +01:00
nix-update bot a8700a6e8c chore: update opencode flake input to 1.1.42 2026-01-29 15:02:03 +01:00
nix-update bot 2e31c2ff23 chore: update opencode flake input to 1.1.40
Update Nix Packages with nix-update / nix-update (push) Successful in 10m24s
2026-01-29 03:03:18 +01:00
nix-update bot 1323c91f1e chore: update opencode flake input to 1.1.39
Update Nix Packages with nix-update / nix-update (push) Successful in 3m25s
2026-01-28 15:02:49 +01:00
nix-update bot 9cff518954 beads: 0.49.0 -> 0.49.1
Update Nix Packages with nix-update / nix-update (push) Successful in 2m57s
Diff: https://github.com/steveyegge/beads/compare/v0.49.0...v0.49.1
2026-01-26 15:00:49 +01:00
m3tm3re 308a60888b fix: stt-ptt use pkill for better process management
Update Nix Packages with nix-update / nix-update (push) Successful in 2m34s
2026-01-26 05:16:29 +01:00
nix-update bot 932dffce51 chore: update opencode flake input to 1.1.36 2026-01-26 03:03:32 +01:00
nix-update bot 0a64f5cdc6 chore: update opencode flake input to 1.1.35
Update Nix Packages with nix-update / nix-update (push) Successful in 3m41s
2026-01-25 03:02:28 +01:00
nix-update bot ec315e0534 n8n: n8n@2.4.5 -> n8n@2.4.6
Update Nix Packages with nix-update / nix-update (push) Successful in 2m35s
Diff: https://github.com/n8n-io/n8n/compare/n8n@2.4.5...n8n@2.4.6

Changelog: https://github.com/n8n-io/n8n/releases/tag/n8n@n8n@2.4.6
2026-01-24 03:02:00 +01:00
m3tm3re b76fbefc4b feat: add opencode-desktop package with Wayland support
Update Nix Packages with nix-update / nix-update (push) Successful in 8m21s
2026-01-23 17:52:46 +01:00
nix-update bot 7a0f5bfd18 chore: update opencode flake input to 1.1.34 2026-01-23 15:02:09 +01:00
nix-update bot 7feaf3568f chore: update opencode flake input to 1.1.32
Update Nix Packages with nix-update / nix-update (push) Successful in 2m16s
2026-01-23 03:02:23 +01:00
nix-update bot 38e58702df n8n: n8n@2.4.4 -> n8n@2.4.5
Update Nix Packages with nix-update / nix-update (push) Successful in 2m31s
Diff: https://github.com/n8n-io/n8n/compare/n8n@2.4.4...n8n@2.4.5

Changelog: https://github.com/n8n-io/n8n/releases/tag/n8n@n8n@2.4.5
2026-01-22 18:34:04 +01:00
nix-update bot f91695eb38 beads: 0.47.1 -> 0.49.0
Diff: https://github.com/steveyegge/beads/compare/v0.47.1...v0.49.0
2026-01-22 18:33:03 +01:00
nix-update bot d4ba11c7a3 chore: update opencode flake input to 1.1.31 2026-01-22 18:32:09 +01:00
m3tm3re bd0e8f2785 chore: removed temporary fix for opencode bun version requirement 2026-01-22 18:30:40 +01:00
nix-update bot fb5f3e9447 beads: 0.48.0 -> 0.47.1
Update Nix Packages with nix-update / nix-update (push) Failing after 2m11s
Diff: https://github.com/steveyegge/beads/compare/v0.48.0...v0.47.1
2026-01-21 18:03:12 +01:00
nix-update bot a1d3de6370 chore: update opencode flake input to 1.1.28
Update Nix Packages with nix-update / nix-update (push) Successful in 6s
2026-01-21 07:19:27 +01:00
sascha.koenig 9c4853f5fb fix: nix fmt without arg in workflow 2026-01-21 07:17:01 +01:00
m3tm3re d674b2f02b fix: gitea workflow
Update Nix Packages with nix-update / nix-update (push) Waiting to run
2026-01-20 20:57:31 +01:00
m3tm3re 1c7a7f0c82 fix: remove deprecated opencode update logic 2026-01-20 19:36:51 +01:00
m3tm3re 4597384291 fix(opencode): patch bun version requirement to match upstream lockfile
- Upstream v1.1.27 requires Bun 1.3.5 but provides 1.3.6
- Patch package.json to accept Bun 1.3.6
- Propagate patched opencode to opencode-desktop
2026-01-20 18:49:18 +01:00
m3tm3re de3850fb1b feat: replace local opencode with upstream flake input v1.1.27
- Add `opencode` flake input pinned to v1.1.27 for stability
- Remove local `pkgs/opencode` derivation and overlay
- Add `opencode` and `opencode-desktop` to `pkgs/default.nix` from input
2026-01-20 18:32:28 +01:00
m3tm3re d3809a7b5e fix: arithmetic increment failing with set -e in nix-update workflow 2026-01-19 18:22:01 +01:00
m3tm3re 58868d0867 fix: remove magic-nix-cache-action causing platform mapping error
Update Nix Packages with nix-update / nix-update (push) Failing after 8s
Removed DeterminateSystems/magic-nix-cache-action to resolve "Cannot convert ArchOs (amd64-linux)" error in Gitea Actions. The action is GitHub-specific and doesn't work with act_runner's platform detection. Workflow will now use default cache.nixos.org substituter.

Note: Consider migrating to Attic binary cache for better performance in the future.
2026-01-18 19:44:58 +01:00
m3tm3re 286fa08b70 feat: optimize nix-update workflow with caching and parallel processing
- Add Magic Nix Cache for 3-9x faster builds
- Add --use-github-releases to only update stable versions
- Remove SKIP_PACKAGES, use dynamic discovery via passthru.updateScript
- Implement 4 concurrent update jobs for 4x speedup
- Add nix flake check for comprehensive validation
- Collect all build failures instead of failing on first
- Fix git reset bug that was destroying commits
- Add job timeout to prevent hanging
- Add detailed job summary and log artifacts
2026-01-18 19:11:46 +01:00
nix-update bot c8a987c43e n8n: 2.4.1 -> n8n@2.4.4
Update Nix Packages with nix-update / nix-update (push) Successful in 15s
Diff: https://github.com/n8n-io/n8n/compare/2.4.1...n8n@2.4.4

Changelog: https://github.com/n8n-io/n8n/releases/tag/n8n@n8n@2.4.4
2026-01-18 11:08:31 +01:00
nix-update bot 71ad8336ce beads: 0.47.1 -> 0.48.0
Diff: https://github.com/steveyegge/beads/compare/v0.47.1...v0.48.0
2026-01-18 11:06:47 +01:00
m3tm3re f64e6983ea feat: improve nix-update workflow and update packages
- Refactor nix-update.yml: push directly to master instead of PRs
- Add skip list for packages without upstream releases
- Add opencode subpackage handling for node_modules
- Add nix-update-script to beads, code2prompt, mem0
- Update mem0: 1.0.0 -> 1.0.2
- Update opencode: 1.1.18 -> 1.1.25
- Fix n8n tag format
- Add n8n update.sh helper script
2026-01-18 11:04:33 +01:00
m3tm3re 52d8cdee11 fixed n8n pnpm hash
Update Nix Packages with nix-update / nix-update (push) Failing after 29s
2026-01-14 20:53:10 +01:00
m3tm3re 60388970e0 bd sync: 2026-01-14 20:52:11 2026-01-14 20:52:11 +01:00
m3tm3re 6f2f1411a8 fix: correct jobs indentation in workflow 2026-01-14 20:43:18 +01:00
m3tm3re c5d5ff98f8 fix: use escaped newlines in PR body to avoid YAML parsing error 2026-01-14 20:39:40 +01:00
m3tm3re 0f4435ad93 chore: sync beads state 2026-01-14 20:36:09 +01:00
m3tm3re 36db58307a fix: resolve YAML syntax error in PR body 2026-01-14 20:32:51 +01:00
m3tm3re f2e0200568 ci: verify package builds before creating PR 2026-01-14 20:30:28 +01:00
m3tm3re 6221984a29 chore: sync beads state 2026-01-14 20:10:04 +01:00
m3tm3re 287bcfea8e ci: use self-hosted nixos runner and change schedule to daily 2026-01-14 20:09:41 +01:00
m3tm3re 42d94876d8 docs: add documentation for beads, n8n, opencode packages
- Update AGENTS.md header with current commit (366af12) and date (2026-01-13)
- Add beads, n8n, opencode to README.md Available Packages table
- Update docs/README.md packages list
- Create docs/packages/beads.md (220 lines)
- Create docs/packages/n8n.md (310 lines)
- Create docs/packages/opencode.md (346 lines)

Documentation now reflects commit bc75505 which added these three packages.
2026-01-13 21:09:02 +01:00
m3tm3re 366af129bd docs: update documentation for automated package updates workflow 2026-01-13 20:56:01 +01:00
m3tm3re b6d45cae4f feat: add Gitea Actions workflow for automated package updates with nix-update 2026-01-13 20:50:38 +01:00
m3tm3re dbc14838cd chore: update lock files and mods 2026-01-13 20:27:52 +01:00
m3tm3re bc75505ca3 feat: add n8n, beads, opencode packages
- Add pkgs/n8n/default.nix (v2.4.1)
- Add pkgs/beads/default.nix (v0.47.1, doCheck=false)
- Add pkgs/opencode/default.nix (v1.1.18)
- Include relax-bun-version-check.patch for opencode
- Register all packages in pkgs/default.nix
2026-01-13 20:26:30 +01:00
m3tm3re c67d663600 bd sync: 2026-01-13 20:26:21 2026-01-13 20:26:21 +01:00
m3tm3re 15b7b13ea1 opencode -> 1.1.18 2026-01-13 19:53:46 +01:00
m3tm3re 338aced3a8 opencode -> 1.1.14 2026-01-12 20:25:38 +01:00
m3tm3re 00b858fbbe docs: update documentation for latest changes
- Add stt-ptt language support documentation
- Add rofi-project-opener module documentation
- Add rofi-project-opener package documentation
- Update zellij-ps documentation
- Update guides and reference patterns
- Update AGENTS.md with latest commands
2026-01-10 19:12:45 +01:00
m3tm3re 6230c04a61 bd sync: 2026-01-10 19:12:32 2026-01-10 19:12:32 +01:00
m3tm3re 9f284a8c21 feat: add auto-language detection support to stt-ptt
- Add STT_LANGUAGE environment variable (default: auto)
- Modify whisper-cli call to use -l flag with language code
- Add language option to HM module (enum with 23 common languages + auto)
- Update help text to document STT_LANGUAGE variable
2026-01-10 09:36:21 +01:00
m3tm3re 3933e380c6 bd sync: 2026-01-10 08:44:29 2026-01-10 08:44:29 +01:00
m3tm3re 6af872107b opencode update 2026-01-10 06:14:21 +01:00
m3tm3re be7cd917a0 feat: update beads to v0.46.0 2026-01-08 04:19:43 +01:00
m3tm3re e146a79309 opencode -> 1.1.4 2026-01-07 17:45:42 +01:00
m3tm3re 6e6e819150 project-launcher changes 2026-01-06 05:54:39 +01:00
m3tm3re 5f8b5dbcdc bd sync: 2026-01-05 12:50:04 2026-01-05 12:50:04 +01:00
m3tm3re 586d199497 bd sync: 2026-01-05 12:46:30 2026-01-05 12:46:30 +01:00
m3tm3re 4b05e2c95f beads test 2026-01-05 12:05:39 +01:00
m3tm3re b275327469 +beads + opencode overlays 2026-01-04 04:07:00 +01:00
m3tm3re 2640d62142 +beads + opencode overlays 2026-01-04 04:03:11 +01:00
m3tm3re 0b4c2efc8f feat: add rofi-project-opener for rofi-based project launching
Adds package and HM module for quickly opening projects in terminals.
Uses XDG config file instead of environment variables for better
shell-independence and proper NixOS PATH sourcing.
2026-01-02 14:54:12 +01:00
m3tm3re de1301e08d feat: add stt-ptt package 2026-01-02 12:24:48 +01:00
m3tm3re 44485c4c72 docs: update zellij-ps to reflect project switcher functionality
- Update package description and fix mainProgram typo
- Rewrite documentation to describe project switching, not process viewing
- Add PROJECT_FOLDERS configuration and usage examples
- Update all references across docs (README, guides, module overviews)
2025-12-30 15:42:52 +01:00
m3tm3re 744b6a8243 refactor: switch formatter from nixpkgs-fmt to alejandra 2025-12-30 15:13:42 +01:00
m3tm3re 824ad97ef9 docs: add hierarchical AGENTS.md knowledge base
- Update root AGENTS.md with regenerative content (144 lines, telegraphic)
- Add pkgs/AGENTS.md for package registry conventions (33 lines)
- Add docs/AGENTS.md for documentation structure (34 lines)
- All files follow telegraphic style, no redundancy with parent
- Preserves existing modules/home-manager/AGENTS.md

Hierarchy:
  ./AGENTS.md (root)
  ├── pkgs/AGENTS.md
  ├── docs/AGENTS.md
  └── modules/home-manager/AGENTS.md (existing)
2025-12-30 15:02:58 +01:00
m3tm3re c5e161026d docs: expand AGENTS.md with comprehensive patterns and add HM module docs 2025-12-29 19:01:37 +01:00
m3tm3re 9092e6d18d +AGENTS.md 2025-12-27 10:16:52 +01:00
m3tm3re d7d64634ee n8n to 2.1.2, flake update 2025-12-23 09:26:11 +01:00
m3tm3re 0db161efac n8n to 2.0.1 2025-12-11 07:06:08 +01:00
m3tam3re a5f30c83b3 python env version fix for marimo 2025-10-14 20:45:04 +02:00
m3tam3re 11755d832f +devshell structure 2025-10-12 16:21:40 +02:00
m3tam3re 27d92a238b quckstart for port management 2025-10-05 12:44:21 +02:00
m3tam3re 8eb3693775 quckstart for port management 2025-10-05 12:43:41 +02:00
m3tam3re 735c22cf36 port module simplified 2025-10-05 12:37:57 +02:00
m3tam3re 62a85af9bc modules for ports 2025-10-05 09:44:40 +02:00
m3tam3re 56295f694d modules for ports 2025-10-05 09:19:29 +02:00
m3tam3re 4fa3a8b551 +lib +portshelper 2025-10-04 17:03:46 +02:00
m3tam3re 1ce83403bc first 2025-10-04 15:53:48 +02:00
93 changed files with 15758 additions and 7 deletions
+3
View File
@@ -0,0 +1,3 @@
# Use bd merge for beads JSONL files
.beads/issues.jsonl merge=beads
+541
View File
@@ -0,0 +1,541 @@
name: Update Nix Packages with nix-update
on:
schedule:
- cron: "0 2,14 * * *" # Every 12 hours at 2 AM and 2 PM
workflow_dispatch:
inputs:
package:
description: "Specific package to update (optional)"
required: false
type: string
concurrency:
group: nix-update-${{ github.ref }}
cancel-in-progress: true
env:
GIT_AUTHOR_NAME: "nix-update bot"
GIT_AUTHOR_EMAIL: "bot@m3ta.dev"
GIT_COMMITTER_NAME: "nix-update bot"
GIT_COMMITTER_EMAIL: "bot@m3ta.dev"
REPO_DIR: "/tmp/nixpkgs"
# Nix configuration
NIX_PATH: "nixpkgs=channel:nixos-unstable"
NIX_CONFIG: "experimental-features = nix-command flakes"
# Non-interactive mode
DEBIAN_FRONTEND: "noninteractive"
GIT_TERMINAL_PROMPT: "0"
jobs:
nix-update:
runs-on: nixos
timeout-minutes: 180
steps:
- name: Setup Environment and Authenticate
run: |
if [ -d "$REPO_DIR" ]; then rm -rf "$REPO_DIR"; fi
git config --global credential.helper store
echo "https://m3tam3re:${{ secrets.NIX_UPDATE_TOKEN }}@code.m3ta.dev" > ~/.git-credentials
chmod 600 ~/.git-credentials
git config --global user.name "$GIT_AUTHOR_NAME"
git config --global user.email "$GIT_AUTHOR_EMAIL"
git config --global init.defaultBranch master
- name: Checkout Repository
run: |
git clone --no-single-branch \
"https://m3tam3re@code.m3ta.dev/m3tam3re/nixpkgs.git" \
"$REPO_DIR"
- name: Update All Flake Inputs
id: update-flake-inputs
run: |
cd "$REPO_DIR"
echo "::group::Discovering version-pinned flake inputs"
# Get GitHub inputs with version refs (e.g., v1.2.9)
VERSIONED_INPUTS=$(nix flake metadata --json | jq -r '
.locks.nodes | to_entries[] |
select(.value.original.type == "github") |
select(.value.original.ref != null) |
select(.value.original.ref | test("^v?[0-9]+\\.[0-9]+")) |
"\(.key) \(.value.original.owner) \(.value.original.repo) \(.value.original.ref)"
')
echo "Discovered version-pinned inputs:"
echo "$VERSIONED_INPUTS"
echo "::endgroup::"
UPDATED_INPUTS=""
FAILED_INPUTS=""
# Update each version-pinned input
while read -r INPUT_NAME OWNER REPO CURRENT_REF; do
[ -z "$INPUT_NAME" ] && continue
echo "::group::Checking $INPUT_NAME ($OWNER/$REPO)"
# Get latest stable release (exclude prereleases)
# The /releases/latest endpoint already returns the latest non-prerelease, non-draft release
LATEST=$(curl -sf "https://api.github.com/repos/$OWNER/$REPO/releases/latest" | \
jq -r 'if .prerelease == false then .tag_name else empty end')
if [ -z "$LATEST" ]; then
echo "⚠️ No stable release found for $INPUT_NAME (repo may only have prereleases)"
FAILED_INPUTS="$FAILED_INPUTS $INPUT_NAME(no-stable-release)"
echo "::endgroup::"
continue
fi
echo "Current: $CURRENT_REF | Latest: $LATEST"
if [ "$LATEST" != "$CURRENT_REF" ]; then
echo "Updating $INPUT_NAME from $CURRENT_REF to $LATEST"
# Update flake.nix
sed -i "s|github:$OWNER/$REPO/[^\"']*|github:$OWNER/$REPO/$LATEST|g" flake.nix
# Update flake.lock for this input
if nix flake update "$INPUT_NAME" 2>&1 | tee /tmp/input-update.log; then
UPDATED_INPUTS="$UPDATED_INPUTS $INPUT_NAME($LATEST)"
echo "✅ Updated $INPUT_NAME to $LATEST"
else
echo "❌ Failed to update $INPUT_NAME"
FAILED_INPUTS="$FAILED_INPUTS $INPUT_NAME(update-failed)"
git checkout flake.nix flake.lock 2>/dev/null || true
fi
else
echo "✓ $INPUT_NAME is already up to date"
fi
echo "::endgroup::"
done <<< "$VERSIONED_INPUTS"
echo "::group::Updating non-version-pinned inputs"
# Update all non-version-pinned inputs (branches, no-ref)
nix flake update
echo "::endgroup::"
# Check if we have any changes
if [ -n "$(git status --porcelain flake.nix flake.lock)" ]; then
echo "::group::Committing flake input updates"
nix fmt flake.nix
git add flake.nix flake.lock
COMMIT_MSG="chore: update flake inputs"
[ -n "$UPDATED_INPUTS" ] && COMMIT_MSG="$COMMIT_MSG - $(echo $UPDATED_INPUTS | tr ' ' ', ')"
git commit -m "$COMMIT_MSG"
echo "flake_inputs_updated=true" >> $GITHUB_OUTPUT
echo "updated_inputs=${UPDATED_INPUTS# }" >> $GITHUB_OUTPUT
[ -n "$FAILED_INPUTS" ] && echo "failed_inputs=${FAILED_INPUTS# }" >> $GITHUB_OUTPUT
echo "::endgroup::"
else
echo "flake_inputs_updated=false" >> $GITHUB_OUTPUT
fi
- name: Check Prerequisites
id: check
run: |
cd "$REPO_DIR"
if [ ! -d "pkgs" ]; then
echo "❌ Error: 'pkgs' directory not found."
exit 1
fi
if [ -f "flake.nix" ]; then
echo "has_flake=true" >> $GITHUB_OUTPUT
else
echo "has_flake=false" >> $GITHUB_OUTPUT
fi
- name: Update Packages
id: update
run: |
cd "$REPO_DIR"
set -e
git checkout master
UPDATES_FOUND=false
UPDATED_PACKAGES=""
check_commit() {
[ "$1" != "$(git rev-parse HEAD)" ] && echo "true" || echo "false"
}
has_update_script() {
local pkg=$1
# Check if package has passthru.updateScript attribute
nix eval .#${pkg}.passthru.updateScript --json >/dev/null 2>&1
}
# Check if updateScript is a custom script (path-based) vs nix-update-script
is_custom_update_script() {
local pkg=$1
local result
# nix-update-script returns a list like [ "/nix/store/...-nix-update/bin/nix-update" ]
# Custom scripts return a path like "/nix/store/.../update.sh"
result=$(nix eval --impure --raw --expr "
let
flake = builtins.getFlake (toString ./.);
pkg = flake.packages.\${builtins.currentSystem}.${pkg};
script = pkg.passthru.updateScript or [];
in
if builtins.isPath script then
\"custom\"
else if builtins.isList script && builtins.length script > 0 then
let first = builtins.head script;
in if builtins.isString first && builtins.match \".*/nix-update$\" first != null then
\"nix-update-script\"
else if builtins.isPath first then
\"custom\"
else
\"other\"
else if builtins.isAttrs script && script ? command then
if builtins.isPath script.command then \"custom\"
else if builtins.isList script.command && builtins.isPath (builtins.head script.command) then \"custom\"
else \"other\"
else
\"other\"
" 2>/dev/null || echo "other")
[[ "$result" == "custom" ]]
}
# Run a custom update script directly (for packages like n8n)
run_custom_update_script() {
local pkg=$1
local before_hash=$(git rev-parse HEAD)
echo " 🔧 Detected custom update script for $pkg"
# Get package metadata for environment variables
local name pname version
name=$(nix eval --raw .#${pkg}.name 2>/dev/null || echo "$pkg")
pname=$(nix eval --raw .#${pkg}.pname 2>/dev/null || echo "$pkg")
version=$(nix eval --raw .#${pkg}.version 2>/dev/null || echo "unknown")
# Run the custom script using nix develop
if nix develop --impure --expr "
with builtins;
let
flake = getFlake (toString ./.);
pkgs = flake.inputs.nixpkgs.legacyPackages.\${currentSystem};
pkg' = flake.packages.\${currentSystem}.${pkg};
script = pkg'.passthru.updateScript;
cmd = if isAttrs script then script.command else script;
scriptPath = if isList cmd then head cmd else cmd;
in pkgs.mkShell {
inputsFrom = [pkg'];
packages = with pkgs; [ curl jq git ];
}
" --command bash -c "
export UPDATE_NIX_NAME='${name}'
export UPDATE_NIX_PNAME='${pname}'
export UPDATE_NIX_OLD_VERSION='${version}'
export UPDATE_NIX_ATTR_PATH='${pkg}'
# Get the script path and execute it
script_path=\$(nix eval --impure --raw --expr '
let
flake = builtins.getFlake (toString ./.);
pkg = flake.packages.\${builtins.currentSystem}.${pkg};
script = pkg.passthru.updateScript;
cmd = if builtins.isAttrs script then script.command else script;
in if builtins.isList cmd then toString (builtins.head cmd)
else toString cmd
' 2>/dev/null)
if [ -n \"\$script_path\" ]; then
echo \"Running: \$script_path\"
bash \"\$script_path\"
fi
" 2>&1 | tee /tmp/update-${pkg}.log; then
if [ "$(check_commit "$before_hash")" = "true" ]; then
echo "✅ Updated $pkg (via custom script)"
return 0
fi
fi
# Clean up on failure
git checkout -- . 2>/dev/null || true
git clean -fd 2>/dev/null || true
if ! grep -q "already up to date\|No new version found" /tmp/update-${pkg}.log; then
echo "⚠️ Custom update script failed for $pkg"
fi
return 1
}
run_update() {
local pkg=$1
local before_hash=$(git rev-parse HEAD)
echo "::group::Updating $pkg"
# Check if this package has a custom update script
if is_custom_update_script "$pkg"; then
if run_custom_update_script "$pkg"; then
echo "::endgroup::"
return 0
else
echo "::endgroup::"
return 1
fi
fi
# Standard nix-update for packages with nix-update-script
local args=("--flake" "--commit" "--use-github-releases")
args+=("$pkg")
if nix-update "${args[@]}" 2>&1 | tee /tmp/update-${pkg}.log; then
if [ "$(check_commit "$before_hash")" = "true" ]; then
echo "✅ Updated $pkg"
echo "::endgroup::"
return 0
fi
fi
# Clean up any uncommitted changes from failed update
git checkout -- . 2>/dev/null || true
git clean -fd 2>/dev/null || true
echo "::endgroup::"
if ! grep -q "already up to date\|No new version found" /tmp/update-${pkg}.log; then
echo "⚠️ Update failed for $pkg"
fi
return 1
}
if [ -n "${{ inputs.package }}" ]; then
pkg="${{ inputs.package }}"
if [ -d "pkgs/$pkg" ]; then
if run_update "$pkg"; then
UPDATES_FOUND=true
UPDATED_PACKAGES="$pkg"
fi
else
echo "❌ Package 'pkgs/$pkg' not found"
fi
else
# Dynamically discover packages with updateScript attribute
echo "🔍 Discovering packages with passthru.updateScript..."
# Get all packages and filter those with updateScript
ALL_PACKAGES=$(find pkgs -mindepth 1 -maxdepth 1 -type d -exec basename {} \; 2>/dev/null | sort)
UPDATABLE_PACKAGES=""
if [ -z "$ALL_PACKAGES" ]; then
echo "No packages found in pkgs/"
exit 0
fi
for pkg in $ALL_PACKAGES; do
if has_update_script "$pkg"; then
echo " ✓ $pkg (has updateScript)"
UPDATABLE_PACKAGES="$UPDATABLE_PACKAGES $pkg"
else
echo " ⊘ $pkg (no updateScript - skipping)"
fi
done
if [ -z "$UPDATABLE_PACKAGES" ]; then
echo "️ No packages with updateScript found."
exit 0
fi
echo ""
echo "📦 Found $(echo $UPDATABLE_PACKAGES | wc -w) updatable packages"
echo ""
for pkg in $UPDATABLE_PACKAGES; do
if run_update "$pkg"; then
UPDATES_FOUND=true
if [ -n "$UPDATED_PACKAGES" ]; then
UPDATED_PACKAGES="$UPDATED_PACKAGES, $pkg"
else
UPDATED_PACKAGES="$pkg"
fi
fi
done
fi
COMMIT_COUNT=$(git rev-list --count origin/master..HEAD)
if [ "$COMMIT_COUNT" -gt 0 ]; then
echo "✅ $COMMIT_COUNT updates committed locally."
echo "has_updates=true" >> $GITHUB_OUTPUT
echo "updated_packages=${UPDATED_PACKAGES}" >> $GITHUB_OUTPUT
else
echo "️ No updates found."
echo "has_updates=false" >> $GITHUB_OUTPUT
fi
- name: Verify Builds
if: steps.update.outputs.has_updates == 'true' || steps.update-flake-inputs.outputs.flake_inputs_updated == 'true'
run: |
cd "$REPO_DIR"
echo "::group::Running flake check"
if ! nix flake check; then
echo "❌ Flake check failed"
exit 1
fi
echo "✅ Flake check passed"
echo "::endgroup::"
IFS=', ' read -ra PKGS <<< "${{ steps.update.outputs.updated_packages }}"
FAILED_PACKAGES=()
SUCCESSFUL_PACKAGES=()
for pkg in "${PKGS[@]}"; do
echo "::group::Building $pkg"
if nix build .#$pkg 2>&1 | tee /tmp/build-${pkg}.log; then
echo "✅ Build successful for $pkg"
SUCCESSFUL_PACKAGES+=("$pkg")
else
echo "❌ Build failed for $pkg"
FAILED_PACKAGES+=("$pkg")
fi
echo "::endgroup::"
done
if [ ${#FAILED_PACKAGES[@]} -gt 0 ]; then
echo ""
echo "❌ Failed packages: ${FAILED_PACKAGES[*]}"
echo "✅ Successful packages: ${SUCCESSFUL_PACKAGES[*]}"
echo ""
# Upload logs as artifacts for debugging
echo "## Build Failure Logs" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
for pkg in "${FAILED_PACKAGES[@]}"; do
echo "### $pkg" >> $GITHUB_STEP_SUMMARY
echo '```bash' >> $GITHUB_STEP_SUMMARY
cat /tmp/build-${pkg}.log >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
done
exit 1
fi
echo ""
echo "✅ All packages built successfully: ${SUCCESSFUL_PACKAGES[*]}"
- name: Push Changes
if: steps.update.outputs.has_updates == 'true' || steps.update-flake-inputs.outputs.flake_inputs_updated == 'true'
run: |
cd "$REPO_DIR"
PACKAGES="${{ steps.update.outputs.updated_packages }}"
if [ "${{ steps.update-flake-inputs.outputs.flake_inputs_updated }}" = "true" ]; then
UPDATED_INPUTS="${{ steps.update-flake-inputs.outputs.updated_inputs }}"
if [ -n "$PACKAGES" ]; then
PACKAGES="$PACKAGES, flake inputs ($UPDATED_INPUTS)"
else
PACKAGES="flake inputs ($UPDATED_INPUTS)"
fi
fi
echo "::group::Git Operations"
echo "Current commit: $(git rev-parse HEAD)"
echo "Pending commits: $(git rev-list --count origin/master..HEAD)"
echo ""
echo "Pulling latest changes (rebase)..."
if git pull --rebase origin master; then
echo "✅ Rebase successful"
else
echo "⚠️ Rebase failed, resetting and retrying..."
git rebase --abort 2>/dev/null || true
git reset --hard origin/master
echo "❌ Could not rebase, updates lost. Will retry next run."
exit 0
fi
echo ""
echo "Pushing changes to master..."
git push origin master
echo ""
echo "✅ Successfully pushed updates for: $PACKAGES"
echo "::endgroup::"
- name: Cleanup
if: always()
run: |
# Remove git credentials securely
rm -f ~/.git-credentials
git config --global --unset credential.helper 2>/dev/null || true
# Remove temporary directory
rm -rf "$REPO_DIR"
# Remove all log files
rm -f /tmp/update-*.log /tmp/build-*.log /tmp/opencode-build.log /tmp/update-log.txt /tmp/success-packages.txt
# Clear sensitive environment variables
unset GIT_AUTHOR_EMAIL GIT_COMMITTER_EMAIL
- name: Summary
if: always()
run: |
HAS_UPDATES="false"
if [ "${{ steps.update.outputs.has_updates }}" = "true" ]; then
HAS_UPDATES="true"
echo "# ✅ Update Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "## Updated Packages" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "\`${{ steps.update.outputs.updated_packages }}\`" >> $GITHUB_STEP_SUMMARY
fi
if [ "${{ steps.update-flake-inputs.outputs.flake_inputs_updated }}" = "true" ]; then
HAS_UPDATES="true"
echo "" >> $GITHUB_STEP_SUMMARY
echo "## Updated Flake Inputs" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
UPDATED_INPUTS="${{ steps.update-flake-inputs.outputs.updated_inputs }}"
if [ -n "$UPDATED_INPUTS" ]; then
echo "$UPDATED_INPUTS" | tr ' ' '\n' | while read -r input; do
[ -n "$input" ] && echo "- **$input**" >> $GITHUB_STEP_SUMMARY
done
fi
FAILED_INPUTS="${{ steps.update-flake-inputs.outputs.failed_inputs }}"
if [ -n "$FAILED_INPUTS" ]; then
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Failed Inputs" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "$FAILED_INPUTS" | tr ' ' '\n' | while read -r input; do
[ -n "$input" ] && echo "- $input" >> $GITHUB_STEP_SUMMARY
done
fi
fi
if [ "$HAS_UPDATES" = "true" ]; then
echo "" >> $GITHUB_STEP_SUMMARY
echo "## Status" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- ✅ All updates validated with \`nix flake check\`" >> $GITHUB_STEP_SUMMARY
echo "- ✅ All builds successful" >> $GITHUB_STEP_SUMMARY
echo "- ✅ Changes pushed to master" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "## Workflow Performance" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- Started: ${{ github.event.head_commit.timestamp }}" >> $GITHUB_STEP_SUMMARY
echo "- Completed: $(date -u +'%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_STEP_SUMMARY
echo "- Workflow Run: [#${{ github.run_number }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})" >> $GITHUB_STEP_SUMMARY
else
echo "# ️ No Updates Required" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "No updates found this run. All packages and flake inputs are up to date." >> $GITHUB_STEP_SUMMARY
fi
+39
View File
@@ -0,0 +1,39 @@
# Nix build outputs
result
result-*
# Direnv
.direnv/
.envrc
# Development shells
shell.nix
# Editor files
.vscode/
.idea/
*.swp
*.swo
*~
.DS_Store
# Nix-specific
.pre-commit-config.yaml
.envrc.local
# Temporary files
*.tmp
*.log
# Testing
test-result/
# Local configuration (if you want to keep local overrides)
local.nix
flake.lock.bak
.todos/
# AI agent state
.sidecar/
.sidecar-*
.sisyphus/
+1
View File
@@ -0,0 +1 @@
/home/sascha.koenig/p/NIX/nixpkgs
+170
View File
@@ -0,0 +1,170 @@
# m3ta-nixpkgs Knowledge Base
## MANDATORY: Use td for Task Management
You must run td usage --new-session at conversation start (or after /clear) to see current work.
Use td usage -q for subsequent reads.
**Generated:** 2026-02-14
**Commit:** dc2f3b6
**Branch:** master
## OVERVIEW
Personal Nix flake: custom packages, overlays, NixOS/Home Manager modules, dev shells. Flakes-only (no channels).
## STRUCTURE
```
.
├── flake.nix # Entry: packages, overlays, modules, shells, lib
├── pkgs/ # Custom packages (one dir each, callPackage registry)
├── modules/
│ ├── nixos/ # System modules (ports.nix)
│ └── home-manager/ # User modules by category (cli/, coding/, ports.nix)
├── lib/ # Shared utilities (ports.nix)
├── shells/ # Dev environments (default, python, devops)
├── overlays/mods/ # Package modifications (n8n version bump)
├── templates/ # Boilerplate for new packages/modules
├── examples/ # Usage examples
└── .gitea/workflows/ # CI/CD workflows (nix-update automation)
```
## WHERE TO LOOK
| Task | Location | Notes |
| -------------------- | ---------------------------------- | ------------------------------------- |
| Add package | `pkgs/<name>/default.nix` | Register in `pkgs/default.nix` |
| Add NixOS module | `modules/nixos/<name>.nix` | Import in `modules/nixos/default.nix` |
| Add HM module | `modules/home-manager/<category>/` | Category: cli, coding, or root |
| Override nixpkgs pkg | `overlays/mods/<name>.nix` | Import in `overlays/mods/default.nix` |
| Add dev shell | `shells/<name>.nix` | Register in `shells/default.nix` |
| Use port management | `config.m3ta.ports.get "service"` | Host-specific via `hostOverrides` |
| CI/CD workflows | `.gitea/workflows/<name>.yml` | Automated package updates (nix-update) |
## CONVENTIONS
**Formatter**: `nix fmt` before commit (alejandra)
**Naming**:
- Packages: `lowercase-hyphen` (e.g., `hyprpaper-random`)
- Variables: `camelCase` (e.g., `portHelpers`)
- Module options: `m3ta.*` namespace
**Imports**: Multi-line, trailing commas:
```nix
{
lib,
stdenv,
fetchFromGitHub,
}:
```
**Modules**: Standard pattern:
```nix
{ config, lib, pkgs, ... }:
with lib; let
cfg = config.m3ta.myModule;
in {
options.m3ta.myModule = {
enable = mkEnableOption "description";
};
config = mkIf cfg.enable { ... };
}
```
**Meta**: Always include all fields:
```nix
meta = with lib; {
description = "...";
homepage = "...";
license = licenses.mit;
platforms = platforms.linux;
mainProgram = "...";
};
```
## PACKAGE PATTERNS
**Rust**: `rustPlatform.buildRustPackage rec { cargoLock.lockFile = src + "/Cargo.lock"; }`
**Shell**: `writeShellScriptBin "name" ''script''` or `mkDerivation` with custom `installPhase`
**AppImage**: `appimageTools.wrapType2 { ... }`
**Custom fetcher**: `fetchFromGitea { domain = "code.m3ta.dev"; owner = "m3tam3re"; ... }`
## MODULE PATTERNS
**Simple**: `options.cli.name = { enable = mkEnableOption "..."; }; config = mkIf cfg.enable { ... };`
**Multiple**: `config = mkMerge [ (mkIf cfg.x.enable { ... }) (mkIf cfg.y.enable { ... }) ];`
**Shared lib**: `portsLib = import ../../lib/ports.nix { inherit lib; }; portHelpers = portsLib.mkPortHelpers { ... };`
## PORT MANAGEMENT
Central port management: `config.m3ta.ports.get "service"` with host-specific via `hostOverrides`
Generated: `/etc/m3ta/ports.json` (NixOS), `~/.config/m3ta/ports.json` (HM)
## COMMANDS
```bash
nix flake check # Validate flake
nix fmt # Format (alejandra)
nix build .#<pkg> # Build package
nix flake show # List outputs
nix develop # Enter dev shell
nix develop .#python # Python shell
nix develop .#devops # DevOps shell
# In dev shell only:
statix check . # Lint
deadnix . # Find dead code
```
## ANTI-PATTERNS
| Don't | Do Instead |
| ------------------------- | ------------------------------------------------------------------- |
| `lib.fakeHash` in commits | Get real hash: `nix build`, copy from error |
| Flat module files | Organize by category (`cli/`, `coding/`) |
| Hardcode ports | Use `m3ta.ports` module |
| Skip meta fields | Include all: description, homepage, license, platforms, mainProgram |
| `with pkgs;` in modules | Explicit `pkgs.package` or `with pkgs; [ ... ]` in lists only |
## COMMIT FORMAT
```
type: brief description
```
Types: `feat`, `fix`, `docs`, `style`, `refactor`, `chore`
## NOTES
- **Hash fetching**: Use `lib.fakeHash` initially, build to get real hash
- **HM modules**: Category subdirs (`cli/`, `coding/`) have own `default.nix` aggregators
- **Ports module**: Different for NixOS vs HM (HM adds `generateEnvVars` option)
- **Overlays**: `modifications` overlay uses `{prev}:` pattern, not `{final, prev}:`
- **Dev shell tools**: `statix`, `deadnix` only available inside `nix develop`
- **Automated package updates**: Packages are automatically updated weekly via Gitea Actions using `nix-update`. Review PRs from the automation before merging. For urgent updates, manually run the workflow or update manually.
## Task Management
This project uses **td** for tracking tasks across AI coding sessions.
Run `td usage --new-session` at conversation start to see current work.
Use `td usage -q` for subsequent reads.
**Quick reference:**
- `td usage --new-session` - Start new session and view tasks
- `td usage -q` - Quick view of current tasks (subsequent reads)
- `td version` - Check version
For full workflow details, see the [td documentation](./docs/packages/td.md).
-7
View File
@@ -1,7 +0,0 @@
This repository is being used as a Dolt remote.
ref=refs/dolt/data
head=43d141bca1faebdf2ed20deb3c147ca1b2946eea
timestamp=2026-07-04T07:30:30Z
+92
View File
@@ -0,0 +1,92 @@
# m3ta-nixpkgs
Personal Nix flake repository: custom packages, overlays, NixOS modules, and Home Manager modules.
## Features
- 🎁 **Custom Packages**: Collection of personal Nix packages
- 🔄 **Overlays**: Package modifications and enhancements
- 🐚 **Development Shells**: Pre-configured environments (Python, DevOps)
- ⚙️ **NixOS Modules**: System-level configuration modules
- 🏠 **Home Manager Modules**: User-level configuration modules
- 📚 **Library Functions**: Helper utilities for configuration management
- ❄️ **Flakes Only**: Modern Nix flakes support (no channels)
## Quick Links
- 📖 [Full Documentation](./docs)
- 🚀 [Quick Start Guide](./docs/QUICKSTART.md)
- 📚 [Architecture](./docs/ARCHITECTURE.md)
- 🤝 [Contributing](./docs/CONTRIBUTING.md)
- 📦 [Packages](./docs/packages/)
- ⚙️ [Modules](./docs/modules/)
- 📖 [Guides](./docs/guides/)
## Quick Start
```bash
# Add to your flake
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
m3ta-nixpkgs.url = "git+https://code.m3ta.dev/m3tam3re/nixpkgs";
# Build a package
nix build git+https://code.m3ta.dev/m3tam3re/nixpkgs#code2prompt
# Run a package
nix run git+https://code.m3ta.dev/m3tam3re/nixpkgs#zellij-ps
```
## Available Packages
| Package | Description |
| ------------------ | ------------------------------------- |
| `beads` | Lightweight memory system for AI coding agents with graph-based issue tracking |
| `code2prompt` | Convert code to prompts |
| `hyprpaper-random` | Random wallpaper setter for Hyprpaper |
| `launch-webapp` | Launch web applications |
| `mem0` | AI memory assistant with vector storage |
| `msty-studio` | Msty Studio application |
| `n8n` | Free and source-available fair-code licensed workflow automation tool |
| `notesmd-cli` | Obsidian CLI (Community) - Interact with Obsidian in the terminal |
| `opencode` | AI coding agent built for the terminal |
| `opencode-desktop` | OpenCode Desktop App with Wayland support (includes workaround for upstream issue #11755) |
| `openspec` | Spec-driven development (SDD) for AI coding assistants |
| `pomodoro-timer` | Pomodoro timer utility |
| `rofi-project-opener` | Rofi-based project launcher |
| `sidecar` | Companion tool for CLI agents with diffs, file trees, and task management |
| `stt-ptt` | Push to Talk Speech to Text |
| `td` | Minimalist CLI for tracking tasks across AI coding sessions |
| `tuxedo-backlight` | Backlight control for Tuxedo laptops |
| `zellij-ps` | Project switcher for Zellij |
## Automated Package Updates
This repository uses Gitea Actions to automatically update packages using `nix-update`:
**Workflow**: [`.gitea/workflows/nix-update.yml`](./.gitea/workflows/nix-update.yml)
**Schedule**: Runs weekly on Sundays, and can be triggered manually.
**What it does**:
- Checks all packages in `pkgs/` for updates
- Updates versions and hashes using `nix-update --flake --commit`
- Creates a new branch with updates
- Opens a pull request automatically
**Manual Trigger**:
Go to **Actions → Update Nix Packages with nix-update → Run workflow** in Gitea UI, then optionally specify a specific package to update.
**Setup Required**:
1. Create a Personal Access Token in Gitea (Settings → Applications → Generate Token)
2. Token scopes needed: `user`, `repo`, `write:issue`
3. Add token as secret: Settings → Secrets → New → `NIX_UPDATE_TOKEN`
For detailed usage, module documentation, package references, and contribution guidelines, see the [full documentation](./docs).
## License
Individual packages may have their own licenses. Check each package's `meta.license` attribute.
## Maintainer
[@m3tam3re](https://m3ta.dev)
+473
View File
@@ -0,0 +1,473 @@
# Architecture
Understanding the design and structure of m3ta-nixpkgs.
## Overview
m3ta-nixpkgs is organized as a modern Nix flake with a focus on reusability, consistency, and maintainability. The repository follows clear conventions and patterns to make it easy to understand, extend, and contribute to.
## Repository Structure
```
m3ta-nixpkgs/
├── flake.nix # Main entry point, defines all outputs
├── pkgs/ # Custom packages (callPackage registry)
│ ├── default.nix # Package registry (entry point)
│ ├── code2prompt/ # Individual packages
│ ├── hyprpaper-random/
│ ├── mem0/
│ └── ...
├── modules/
│ ├── nixos/ # NixOS modules
│ │ ├── default.nix # Module aggregator
│ │ ├── mem0.nix
│ │ └── ports.nix
│ └── home-manager/ # Home Manager modules
│ ├── default.nix # Module aggregator
│ ├── ports.nix
│ ├── cli/ # Categorized modules
│ │ ├── default.nix
│ │ └── zellij-ps.nix
│ └── coding/
│ ├── default.nix
│ └── editors.nix
├── lib/ # Shared utilities
│ ├── default.nix # Library aggregator
│ └── ports.nix # Port management functions
├── shells/ # Development environments
│ ├── default.nix # Shell registry
│ ├── python.nix
│ └── devops.nix
├── overlays/ # Package modifications
│ ├── default.nix # Overlay aggregator
│ └── mods/
│ └── default.nix # Individual overlays
├── templates/ # Boilerplate for new items
│ ├── package/
│ ├── nixos-module/
│ └── home-manager-module/
├── examples/ # Usage examples
│ ├── nixos-configuration.nix
│ └── home-manager-standalone.nix
└── docs/ # Documentation
```
## Flake Outputs
`flake.nix` is the entry point that defines all outputs:
### Packages
```nix
packages = forAllSystems (system: let
pkgs = pkgsFor system;
in
import ./pkgs {inherit pkgs;});
```
- Built for all supported systems
- Uses `callPackage` pattern for lazy evaluation
- Available via `nix build .#<package-name>`
### Overlays
```nix
overlays = {
# Default overlay: adds all custom packages
default = final: prev: import ./pkgs {pkgs = final;};
# Additions overlay: same as default
additions = final: prev: import ./pkgs {pkgs = final;};
# Modifications overlay: modifies existing nixpkgs packages
modifications = final: prev: import ./overlays/mods {inherit prev;};
};
```
- `default`: Adds all custom packages to nixpkgs
- `additions`: Individual package additions
- `modifications`: Overrides existing packages
### NixOS Modules
```nix
nixosModules = {
default = ./modules/nixos; # Import all modules
ports = ./modules/nixos/ports.nix; # Specific module
mem0 = ./modules/nixos/mem0.nix;
};
```
- System-level configuration modules
- Use `m3ta.*` namespace
- Can import all modules or individual ones
### Home Manager Modules
```nix
homeManagerModules = {
default = import ./modules/home-manager;
ports = import ./modules/home-manager/ports.nix;
zellij-ps = import ./modules/home-manager/zellij-ps.nix;
};
```
- User-level configuration modules
- Categorized by function (cli, coding)
- Use `m3ta.*` namespace
### Library Functions
```nix
lib = forAllSystems (system: let
pkgs = pkgsFor system;
in
import ./lib {lib = pkgs.lib;});
```
- Helper functions for configuration
- Port management utilities
- Can be used in your configurations
### Development Shells
```nix
devShells = forAllSystems (system: let
pkgs = pkgsFor system;
in
import ./shells {inherit pkgs;});
```
- Pre-configured development environments
- Available: `default`, `python`, `devops`
- Usage: `nix develop .#<shell-name>`
### Templates
```nix
templates = {
package = {
path = ./templates/package;
description = "Template for a new package";
};
nixos-module = {
path = ./templates/nixos-module;
description = "Template for a new NixOS module";
};
home-manager-module = {
path = ./templates/home-manager-module;
description = "Template for a new Home Manager module";
};
};
```
- Boilerplate for quick start
- Usage: `nix flake init -t .#template-name`
## Package Organization
### Registry Pattern
`pkgs/default.nix` acts as a central registry:
```nix
{
inherit (pkgs) callPackage;
} rec {
code2prompt = callPackage ./code2prompt {};
hyprpaper-random = callPackage ./hyprpaper-random {};
mem0 = callPackage ./mem0 {};
# ...
}
```
**Benefits**:
- Lazy evaluation: only builds requested packages
- Consistent interface: all packages use `callPackage`
- Easy discovery: one file lists all packages
### Package Structure
Each package lives in its own directory:
```
pkgs/your-package/
├── default.nix # Package definition
├── source.py # Optional: source files
└── README.md # Optional: package documentation
```
**Conventions**:
- Directory name matches registry attribute
- Use `callPackage` for dependencies
- Always include `meta` with all fields
### Common Package Patterns
#### Rust Packages
```nix
rustPlatform.buildRustPackage rec {
pname = "myapp";
version = "1.0.0";
src = fetchFromGitHub { ... };
cargoLock.lockFile = src + "/Cargo.lock";
# ...
}
```
#### Python Packages
```nix
python3.pkgs.buildPythonPackage rec {
pname = "mypythonapp";
version = "1.0.0";
src = fetchFromGitHub { ... };
dependencies = with python3.pkgs; [requests click];
# ...
}
```
#### Shell Scripts
```nix
writeShellScriptBin "myscript" ''
#!/usr/bin/env bash
echo "Hello World"
''
```
#### AppImage
```nix
appimageTools.wrapType2 rec {
name = "myapp";
src = fetchurl { ... };
# ...
}
```
## Module Organization
### NixOS Modules
Located in `modules/nixos/`:
```
modules/nixos/
├── default.nix # Imports all modules
├── ports.nix # Port management
├── mem0.nx # Individual module
```
**Pattern**:
```nix
{config, lib, pkgs, ...}:
with lib; let
cfg = config.m3ta.myModule;
in {
options.m3ta.myModule = {
enable = mkEnableOption "description";
# ... options
};
config = mkIf cfg.enable {
# ... configuration
};
}
```
### Home Manager Modules
Located in `modules/home-manager/` with categories:
```
modules/home-manager/
├── default.nix # Imports all modules
├── ports.nix # Port management
├── cli/
│ ├── default.nix # Aggregates CLI modules
│ └── zellij-ps.nix
└── coding/
├── default.nix # Aggregates coding modules
└── editors.nix
```
**Categories**:
- `cli/`: Command-line tools and utilities
- `coding/`: Development tools and editors
**Pattern** (same as NixOS):
```nix
{config, lib, pkgs, ...}:
with lib; let
cfg = config.m3ta.coding.editors;
in {
options.m3ta.coding.editors = {
enable = mkEnableOption "editor configuration";
# ... options
};
config = mkIf cfg.enable {
# ... configuration
};
}
```
## Library Functions
Located in `lib/`:
```nix
{lib}: {
# Port management utilities
ports = import ./ports.nix {inherit lib;};
}
```
### Port Management
Centralized port management across hosts:
```nix
# Usage in configuration
portHelpers = inputs.m3ta-nixpkgs.lib.${system}.ports.mkPortHelpers myPorts;
# Get port with host override
services.nginx.port = portHelpers.getPort "nginx" "laptop";
# Get all ports for host
allLaptopPorts = portHelpers.getHostPorts "laptop";
```
**Benefits**:
- Single source of truth for ports
- Host-specific overrides
- Avoid port conflicts
## Naming Conventions
| Context | Convention | Example |
|---------|------------|---------|
| Packages | `lowercase-hyphen` | `hyprpaper-random` |
| Variables | `camelCase` | `portHelpers` |
| Module options | `m3ta.*` | `m3ta.ports.enable` |
| Files | `lowercase-hyphen` | `my-module.nix` |
| Directories | `lowercase-hyphen` | `cli/`, `coding/` |
## Code Patterns
### Module Options
Always use `mkEnableOption` for enable flags:
```nix
options.m3ta.myModule = {
enable = mkEnableOption "description";
};
```
### Conditional Configuration
Use `mkIf` for conditional config:
```nix
config = mkIf cfg.enable {
# Only applied when cfg.enable is true
};
```
### Multiple Conditions
Use `mkMerge` for multiple conditions:
```nix
config = mkMerge [
(mkIf cfg.feature1.enable { ... })
(mkIf cfg.feature2.enable { ... })
];
```
### Imports
Multi-line, trailing commas:
```nix
{
lib,
stdenv,
fetchFromGitHub,
}:
```
### Meta Fields
Always include all fields:
```nix
meta = with lib; {
description = "...";
homepage = "...";
license = licenses.mit;
platforms = platforms.linux;
mainProgram = "program-name";
};
```
## Design Decisions
### Flakes-Only
**Decision**: Use flakes exclusively, no channels.
**Rationale**:
- Reproducible builds
- Explicit dependencies
- Better integration with modern Nix tooling
### CallPackage Pattern
**Decision**: Use `callPackage` for all packages.
**Rationale**:
- Lazy evaluation
- Clear dependency graph
- Consistent interface
### Module Categorization
**Decision**: Categorize Home Manager modules by function.
**Rationale**:
- Easier to find related modules
- Logical organization
- Follows user mental model
### Port Management
**Decision**: Centralized port management with host overrides.
**Rationale**:
- Avoid port conflicts
- Easy to manage multiple hosts
- Single source of truth
### Namespace Convention
**Decision**: Use `m3ta.*` namespace for all modules.
**Rationale**:
- Avoid conflicts
- Clear attribution
- Easy to discover
## Supported Systems
- `x86_64-linux` - Primary development target
- `aarch64-linux` - ARM Linux
- `x86_64-darwin` - macOS Intel
- `aarch64-darwin` - macOS Apple Silicon
**Note**: Some packages may be Linux-only (check `meta.platforms`).
+373
View File
@@ -0,0 +1,373 @@
# Contributing
Contributing to m3ta-nixpkgs.
## Setting Up Development Environment
```bash
# Clone repository
git clone https://code.m3ta.dev/m3tam3re/nixpkgs.git
cd nixpkgs
# Enter development shell (includes linting tools)
nix develop
# Or use a specific shell
nix develop .#python
nix develop .#devops
```
## Code Style and Formatting
### Formatting
Use alejandra to format Nix files:
```bash
# Format all files
nix fmt
# Format specific file
alejandra path/to/file.nix
```
**Always run `nix fmt` before committing.**
### Linting
Linting tools are only available inside the dev shell:
```bash
# Enter dev shell first
nix develop
# Run statix (linter)
statix check .
# Run deadnix (find dead code)
deadnix .
```
## Conventions
### Naming
- **Packages**: `lowercase-hyphen` (e.g., `hyprpaper-random`)
- **Variables**: `camelCase` (e.g., `portHelpers`)
- **Module options**: `m3ta.*` namespace
- **Files**: `lowercase-hyphen` (e.g., `my-module.nix`)
### Imports
Multi-line, trailing commas:
```nix
{
lib,
stdenv,
fetchFromGitHub,
}:
```
### Meta Fields
Always include all fields in package definitions:
```nix
meta = with lib; {
description = "Short description";
homepage = "https://github.com/author/repo";
license = licenses.mit;
platforms = platforms.linux;
mainProgram = "program-name";
};
```
### Module Pattern
Standard module pattern:
```nix
{ config, lib, pkgs, ... }:
with lib; let
cfg = config.m3ta.myModule;
in {
options.m3ta.myModule = {
enable = mkEnableOption "description";
};
config = mkIf cfg.enable {
# Configuration
};
}
```
## Adding a Package
1. Create package directory in `pkgs/your-package/`
2. Write `default.nix` with package definition
3. Register in `pkgs/default.nix`
See [Adding Packages Guide](./guides/adding-packages.md) for detailed instructions.
**Note**: Package versions are automatically updated weekly via Gitea Actions using `nix-update`. You don't need to worry about keeping versions current - the automation will create PRs for updates. Just focus on ensuring the package builds and works correctly.
### Package Testing
```bash
# Build the package
nix build .#your-package
# Test if package runs
nix run .#your-package -- --help
# Check with linter
nix develop
statix check pkgs/your-package/
```
## Adding a NixOS Module
1. Create module file in `modules/nixos/your-module.nix`
2. Import in `modules/nixos/default.nix` (or use directly)
```nix
# modules/nixos/default.nix
{
imports = [
./your-module.nix
./other-module.nix
];
}
```
## Adding a Home Manager Module
1. Choose appropriate category: `cli/`, `coding/`, or root
2. Create module file
3. Import in category's `default.nix` or root `default.nix`
```nix
# modules/home-manager/cli/default.nix
{
imports = [
./your-tool.nix
];
}
```
## Development Workflow
### Making Changes
```bash
# Create feature branch
git checkout -b feature/your-change
# Make changes
# Format code
nix fmt
# Test builds
nix build .#your-package
nix flake check
# Lint
nix develop
statix check .
deadnix .
```
### Commit Format
Use conventional commits:
```
type: brief description
Types:
- feat: New feature
- fix: Bug fix
- docs: Documentation changes
- style: Code style changes (formatting)
- refactor: Code refactoring
- chore: Maintenance tasks
- test: Adding or updating tests
```
Examples:
```
feat: add new package for myapp
fix: resolve port conflict in mem0 module
docs: update installation instructions
style: format nix files
refactor: simplify port management
chore: update dependencies
```
### Before Committing
```bash
# Format all files
nix fmt
# Validate flake
nix flake check
# Run linters
nix develop
statix check .
deadnix .
# Add files
git add .
# Commit
git commit -m "type: description"
```
## Testing
### Package Testing
```bash
# Build for specific system
nix build .#your-package --system x86_64-linux
# Test on different systems
nix build .#your-package --system aarch64-linux
```
### Module Testing
```bash
# Test NixOS configuration
sudo nixos-rebuild test --flake .#hostname
# Test Home Manager configuration
home-manager switch --flake .#username@hostname
```
### Flake Validation
```bash
# Validate all outputs
nix flake check
# Show all outputs
nix flake show
```
## Pull Requests
### Before Submitting
1. [ ] Code formatted with `nix fmt`
2. [ ] Passes `statix check .`
3. [ ] Passes `deadnix .`
4. [ ] Passes `nix flake check`
5. [ ] New packages include `meta` fields
6. [ ] Documentation updated if needed
7. [ ] Commit messages follow convention
### Handling Automated Update PRs
The repository has automated package updates via Gitea Actions (see main README for details). When reviewing automated update PRs:
1. **Build and test**: Verify the updated package builds successfully
2. **Check changelinks**: Review upstream release notes for breaking changes
3. **Test functionality**: Ensure the package still works as expected
4. **Review package definition**: Check if any manual adjustments are needed
For urgent updates, you can manually trigger the workflow from the Gitea UI or update the package manually.
### PR Description
Include:
- What changed and why
- How to test
- Any breaking changes
- Related issues
## Troubleshooting
### Hash Errors
When building packages, you may encounter hash errors:
```
got: sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
expected: sha256-BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=
```
**Solution**: Copy the `got` hash and update the package:
```nix
src = fetchFromGitHub {
# ...
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; # Use actual hash
};
```
### Dependency Not Found
If a package isn't found, check:
1. Package registered in `pkgs/default.nix`
2. Overlay applied in your configuration
3. System matches supported platform
### Linting Errors
```bash
# Fix statix issues manually or use auto-fix where available
statix fix .
# Review deadnix suggestions
deadnix -e .
```
## Getting Help
- Check existing packages and modules for patterns
- Read [Architecture](./ARCHITECTURE.md) for design decisions
- Review [Code Patterns](./reference/patterns.md) for conventions
- Open an issue for questions
## Anti-Patterns
| Don't | Do Instead |
|-------|------------|
| `lib.fakeHash` in commits | Get real hash: `nix build`, copy from error |
| Flat module files | Organize by category (`cli/`, `coding/`) |
| Hardcode ports | Use `m3ta.ports` module |
| Skip meta fields | Include all: description, homepage, license, platforms, mainProgram |
| `with pkgs;` in modules | Explicit `pkgs.package` or `with pkgs; [ ... ]` in lists only |
| Suppress type errors | Fix underlying type issues |
| Delete tests to "pass" | Fix failing tests |
## Code Review Checklist
- [ ] Follows naming conventions
- [ ] Properly formatted (`nix fmt`)
- [ ] Passes linting (`statix`, `deadnix`)
- [ ] Has complete `meta` fields (packages)
- [ ] Documentation updated if needed
- [ ] No dead code
- [ ] No obvious bugs or issues
- [ ] Appropriate for scope
## Release Process
This is a personal repository, but semantic versioning is followed for tags:
1. Update versions as needed
2. Update changelog
3. Tag release
4. Push tags
```bash
git tag -a v1.0.0 -m "Release v1.0.0"
git push origin v1.0.0
```
+316
View File
@@ -0,0 +1,316 @@
# Quick Start Guide
Get started with m3ta-nixpkgs in 5 minutes.
## Prerequisites
- Nix with flakes enabled (Nix 2.4+)
- Basic familiarity with NixOS and/or Home Manager
Enable flakes in `/etc/nixos/configuration.nix`:
```nix
nix.settings.experimental-features = ["nix-command" "flakes"];
```
## Adding to Your Flake
### NixOS Configuration
```nix
{
description = "My NixOS configuration";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
home-manager.url = "github:nix-community/home-manager";
m3ta-nixpkgs = {
url = "git+https://code.m3ta.dev/m3tam3re/nixpkgs";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = {
self,
nixpkgs,
home-manager,
m3ta-nixpkgs,
...
}: {
nixosConfigurations = {
hostname = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
./hardware-configuration.nix
# Import m3ta's NixOS modules
m3ta-nixpkgs.nixosModules.default
# Apply overlay to make packages available
({pkgs, ...}: {
nixpkgs.overlays = [m3ta-nixpkgs.overlays.default];
environment.systemPackages = with pkgs; [
code2prompt
zellij-ps
# Regular nixpkgs packages
vim
];
})
home-manager.nixosModules.home-manager
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.users.yourusername = {
imports = [m3ta-nixpkgs.homeManagerModules.default];
home.packages = with pkgs; [
launch-webapp
];
};
}
];
};
};
};
}
```
### Standalone Home Manager
```nix
{
description = "My Home Manager configuration";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
home-manager.url = "github:nix-community/home-manager";
m3ta-nixpkgs = {
url = "git+https://code.m3ta.dev/m3tam3re/nixpkgs";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = {
self,
nixpkgs,
home-manager,
m3ta-nixpkgs,
} @ inputs: let
system = "x86_64-linux";
pkgs = import nixpkgs {
inherit system;
overlays = [m3ta-nixpkgs.overlays.default];
};
in {
homeConfigurations.yourusername = home-manager.lib.homeManagerConfiguration {
inherit pkgs;
extraSpecialArgs = {inherit inputs;};
modules = [
m3ta-nixpkgs.homeManagerModules.default
{
home.username = "yourusername";
home.homeDirectory = "/home/yourusername";
home.packages = with pkgs; [
code2prompt
zellij-ps
];
programs.home-manager.enable = true;
}
];
};
};
}
```
## Using Packages Without Configuration
You can build and run packages directly without adding to your configuration:
```bash
# Build a package
nix build git+https://code.m3ta.dev/m3tam3re/nixpkgs#code2prompt
# Run a package
nix run git+https://code.m3ta.dev/m3tam3re/nixpkgs#zellij-ps
# List all available packages
nix flake show git+https://code.m3ta.dev/m3tam3re/nixpkgs
```
## Common Use Cases
### Use a Package System-Wide
```nix
# In configuration.nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
code2prompt # From m3ta-nixpkgs
git # From nixpkgs
];
}
```
### Use a Package for Your User Only
```nix
# In home.nix
{pkgs, ...}: {
home.packages = with pkgs; [
launch-webapp
zellij-ps
];
}
```
### Use a NixOS Module
```nix
{config, ...}: {
imports = [
# Or import the default which includes all modules
];
# Enable mem0 service
m3ta.mem0 = {
enable = true;
port = 8000;
llm = {
provider = "openai";
apiKeyFile = "/run/secrets/openai-api-key";
};
};
}
```
### Use Port Management
```nix
{config, ...}: {
m3ta.ports = {
enable = true;
definitions = {
nginx = 80;
grafana = 3000;
};
hostOverrides.laptop = {
nginx = 8080; # Override on laptop
};
currentHost = config.networking.hostName;
};
services.nginx = {
enable = true;
httpConfig = ''
server {
listen ${toString (config.m3ta.ports.get "nginx")};
}
'';
};
}
```
## Available Packages
| Package | Description |
| ------------------ | ------------------------------------- |
| `code2prompt` | Convert code to prompts |
| `hyprpaper-random` | Random wallpaper setter for Hyprpaper |
| `launch-webapp` | Launch web applications |
| `mem0` | AI memory assistant with vector storage |
| `msty-studio` | Msty Studio application |
| `pomodoro-timer` | Pomodoro timer utility |
| `tuxedo-backlight` | Backlight control for Tuxedo laptops |
| `zellij-ps` | Project switcher for Zellij |
## Essential Commands
```bash
# Validate your configuration
nix flake check
# Format Nix files
nix fmt
# Apply NixOS configuration
sudo nixos-rebuild switch
# Apply Home Manager configuration
home-manager switch
# Enter development shell
nix develop .#python # Python shell
nix develop .#devops # DevOps shell
# List all outputs
nix flake show
```
## Development Workflow
```bash
# Clone repository
git clone https://code.m3ta.dev/m3tam3re/nixpkgs.git
cd nixpkgs
# Create a new package
nix flake init -t .#package
# Test package build
nix build .#your-package
# Run linting (in dev shell)
nix develop
statix check .
deadnix .
# Format before commit
nix fmt
```
## Troubleshooting
### Package Not Found
Make sure you applied the overlay:
```nix
nixpkgs.overlays = [m3ta-nixpkgs.overlays.default];
```
Or reference directly:
```nix
inputs.m3ta-nixpkgs.packages.${pkgs.system}.package-name
```
### Module Not Found
Make sure you imported the module:
```nix
imports = [
m3ta-nixpkgs.nixosModules.default
# or specific module:
m3ta-nixpkgs.nixosModules.mem0
];
```
### Hash Mismatch
If you're developing and get a hash error, rebuild to get the real hash:
```bash
nix build .#your-package
# Copy hash from error and update package
```
## Next Steps
- [Architecture](./ARCHITECTURE.md) - Understanding the repository structure
- [Adding Packages](./guides/adding-packages.md) - How to add new packages
- [Using Modules](./guides/using-modules.md) - Deep dive into modules
- [Port Management](./guides/port-management.md) - Managing service ports
+156
View File
@@ -0,0 +1,156 @@
# m3ta-nixpkgs Documentation
Complete documentation for m3ta's personal Nix flake repository.
## Overview
m3ta-nixpkgs is a collection of custom packages, overlays, NixOS modules, and Home Manager modules organized as a modern Nix flake. This repository follows a flakes-only approach (no channels) and provides reusable components for personal infrastructure.
## Getting Started
- **[Quick Start Guide](./QUICKSTART.md)** - Get up and running in 5 minutes
- **[Architecture](./ARCHITECTURE.md)** - Understanding the repository structure and design
- **[Contributing](./CONTRIBUTING.md)** - How to contribute to this repository
## Documentation Sections
### 📚 Guides
Step-by-step guides for common tasks:
- [Getting Started](./guides/getting-started.md) - Initial setup and basic usage
- [Adding Packages](./guides/adding-packages.md) - How to add new packages
- [Port Management](./guides/port-management.md) - Managing service ports across hosts
- [Using Modules](./guides/using-modules.md) - Using NixOS and Home Manager modules
- [Development Workflow](./guides/development-workflow.md) - Development and testing workflow
### 📦 Packages
Documentation for all custom packages:
- [beads](./packages/beads.md) - Lightweight memory system for AI coding agents with graph-based issue tracking
- [code2prompt](./packages/code2prompt.md) - Convert code to prompts
- [hyprpaper-random](./packages/hyprpaper-random.md) - Random wallpaper setter for Hyprpaper
- [launch-webapp](./packages/launch-webapp.md) - Launch web applications
- [mem0](./packages/mem0.md) - AI memory assistant with vector storage
- [msty-studio](./packages/msty-studio.md) - Msty Studio application
- [n8n](./packages/n8n.md) - Free and source-available fair-code licensed workflow automation tool
- [notesmd-cli](./packages/notesmd-cli.md) - Obsidian CLI (Community) - Interact with Obsidian in the terminal
- [opencode](./packages/opencode.md) - AI coding agent built for terminal
- [pomodoro-timer](./packages/pomodoro-timer.md) - Pomodoro timer utility
- [rofi-project-opener](./packages/rofi-project-opener.md) - Rofi-based project launcher with custom args
- [sidecar](./packages/sidecar.md) - Companion tool for CLI agents with diffs, file trees, and task management
- [stt-ptt](./packages/stt-ptt.md) - Push to Talk Speech to Text using Whisper
- [td](./packages/td.md) - Minimalist CLI for tracking tasks across AI coding sessions
- [tuxedo-backlight](./packages/tuxedo-backlight.md) - Backlight control for Tuxedo laptops
- [zellij-ps](./packages/zellij-ps.md) - Project switcher for Zellij
### ⚙️ Modules
Configuration modules for NixOS and Home Manager:
#### NixOS Modules
- [Overview](./modules/nixos/overview.md) - NixOS modules overview
- [mem0](./modules/nixos/mem0.md) - Mem0 REST API server module
- [ports](./modules/nixos/ports.md) - Port management module
#### Home Manager Modules
- [Overview](./modules/home-manager/overview.md) - Home Manager modules overview
- [CLI Tools](./modules/home-manager/cli/) - CLI-related modules
- [rofi-project-opener](./modules/home-manager/cli/rofi-project-opener.md) - Rofi-based project launcher
- [stt-ptt](./modules/home-manager/cli/stt-ptt.md) - Push to Talk Speech to Text
- [zellij-ps](./modules/home-manager/cli/zellij-ps.md) - Zellij project switcher
- [Coding](./modules/home-manager/coding/) - Development-related modules
- [editors](./modules/home-manager/coding/editors.md) - Editor configurations
### 📖 Reference
Technical references and APIs:
- [Functions](./reference/functions.md) - Library functions documentation
- [Patterns](./reference/patterns.md) - Code patterns and anti-patterns
## Repository Structure
```
m3ta-nixpkgs/
├── docs/ # This directory
│ ├── README.md
│ ├── QUICKSTART.md
│ ├── ARCHITECTURE.md
│ ├── CONTRIBUTING.md
│ ├── guides/
│ ├── packages/
│ ├── modules/
│ └── reference/
├── pkgs/ # Custom packages
├── modules/
│ ├── nixos/ # NixOS modules
│ └── home-manager/ # Home Manager modules
├── lib/ # Library functions
├── shells/ # Development shells
├── overlays/ # Package overlays
├── templates/ # Templates
└── examples/ # Usage examples
```
## Key Concepts
### Flakes-Only Approach
This repository uses modern Nix flakes exclusively. No channels or `nix-channel` commands are needed. All dependencies are declaratively specified in `flake.nix`.
### Namespace Convention
All modules use the `m3ta.*` namespace:
- `m3ta.ports.*` - Port management
- `m3ta.mem0.*` - Mem0 service configuration
- `m3ta.*.enable` - Enable/disable modules
### Port Management
Centralized port management across hosts using the `m3ta.ports` module:
```nix
m3ta.ports = {
enable = true;
definitions = { mem0 = 8000; };
hostOverrides.laptop = { mem0 = 8080; };
currentHost = "laptop";
};
```
## Supported Systems
- `x86_64-linux` - Primary
- `aarch64-linux` - ARM Linux
- `x86_64-darwin` - macOS (Intel)
- `aarch64-darwin` - macOS (Apple Silicon)
## Quick Commands
```bash
# Validate flake
nix flake check
# Format code
nix fmt
# Build package
nix build .#<package-name>
# List outputs
nix flake show
# Enter dev shell
nix develop
```
## License
Individual packages may have their own licenses. Check each package's `meta.license` attribute.
## Maintainer
[@m3tam3re](https://m3ta.dev)
+504
View File
@@ -0,0 +1,504 @@
# Adding Packages Guide
How to add new packages to m3ta-nixpkgs.
## Overview
Packages in m3ta-nixpkgs are organized using a `callPackage` registry pattern. Each package lives in its own directory and is registered centrally.
## Quick Start
### Using Templates
Use the package template for quick setup:
```bash
nix flake init -t .#package my-new-package
```
This creates a template structure in `templates/package/` that you can copy.
### Automatic Updates
**Important**: This repository uses automated package updates via Gitea Actions and `nix-update`. When adding a new package:
- Use any stable, working version for the initial package
- You don't need to use the absolute latest version
- The automation will keep the package updated automatically on a weekly basis
- Review and merge automated update PRs as they come in
See the main README.md for more details on the automated update workflow.
### Manual Setup
1. Create directory: `pkgs/your-package/`
2. Write `default.nix` with package definition
3. Register in `pkgs/default.nix`
## Package Structure
```
pkgs/your-package/
├── default.nix # Package definition (required)
├── source.py # Optional: additional source files
├── wrapper.sh # Optional: wrapper scripts
└── README.md # Optional: package documentation
```
## Common Patterns
### Rust Package
```nix
{
lib,
rustPlatform,
fetchFromGitHub,
}:
rustPlatform.buildRustPackage rec {
pname = "my-rust-app";
version = "1.0.0";
src = fetchFromGitHub {
owner = "author";
repo = "my-rust-app";
rev = "v${version}";
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
cargoLock.lockFile = src + "/Cargo.lock";
buildInputs = [openssl];
nativeBuildInputs = [pkg-config];
meta = with lib; {
description = "My Rust application";
homepage = "https://github.com/author/my-rust-app";
license = licenses.mit;
platforms = platforms.linux;
mainProgram = "my-rust-app";
};
}
```
### Python Package
```nix
{
lib,
python3,
fetchFromGitHub,
}:
python3.pkgs.buildPythonPackage rec {
pname = "my-python-app";
version = "1.0.0";
pyproject = true;
src = fetchFromGitHub {
owner = "author";
repo = "my-python-app";
rev = "v${version}";
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
build-system = with python3.pkgs; [setuptools];
dependencies = with python3.pkgs; [
requests
click
];
optional-dependencies = with python3.pkgs; {
extras = [pyyaml];
};
doCheck = true;
pythonImportsCheck = ["myapp"];
meta = with lib; {
description = "My Python application";
homepage = "https://github.com/author/my-python-app";
license = licenses.mit;
platforms = platforms.linux;
mainProgram = "my-app";
};
}
```
### Shell Script Package
```nix
{
lib,
writeShellScriptBin,
}:
writeShellScriptBin "my-script" ''
#!/usr/bin/env bash
set -euo pipefail
echo "Hello from my script!"
# Your script logic here
''
# If you need to add dependencies
{
lib,
writeShellApplication,
bash,
curl,
}:
writeShellApplication {
name = "my-script";
runtimeInputs = [bash curl];
text = ''
#!/usr/bin/env bash
set -euo pipefail
curl -s https://example.com
'';
}
```
### AppImage Package
```nix
{
lib,
appimageTools,
fetchurl,
}:
appimageTools.wrapType2 rec {
name = "my-app";
version = "1.0.0";
src = fetchurl {
url = "https://github.com/author/my-app/releases/download/v${version}/My-App-${version}.AppImage";
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
meta = with lib; {
description = "My AppImage application";
homepage = "https://github.com/author/my-app";
license = licenses.unfree;
platforms = platforms.linux;
mainProgram = name;
};
}
```
### Custom Source with Patch
```nix
{
lib,
stdenv,
fetchFromGitHub,
fetchpatch,
buildGoModule,
}:
buildGoModule rec {
pname = "my-go-app";
version = "1.0.0";
src = fetchFromGitHub {
owner = "author";
repo = "my-go-app";
rev = "v${version}";
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
patches = [
# Add local patch
./fix-build.patch
# Add patch from URL
(fetchpatch {
url = "https://github.com/author/my-app/pull/123.patch";
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
})
];
vendorHash = "sha256-BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=";
meta = with lib; {
description = "My Go application";
homepage = "https://github.com/author/my-go-app";
license = licenses.mit;
platforms = platforms.linux;
mainProgram = "my-app";
};
}
```
### Package with Custom Installation
```nix
{
lib,
stdenv,
fetchFromGitHub,
makeWrapper,
}:
stdenv.mkDerivation rec {
pname = "my-app";
version = "1.0.0";
src = fetchFromGitHub {
owner = "author";
repo = "my-app";
rev = "v${version}";
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
nativeBuildInputs = [makeWrapper];
buildPhase = ''
make build
'';
installPhase = ''
install -Dm755 my-app $out/bin/my-app
# Wrap with runtime dependencies
wrapProgram $out/bin/my-app \
--prefix PATH : ${lib.makeBinPath [some-dep]}
'';
meta = with lib; {
description = "My custom application";
homepage = "https://github.com/author/my-app";
license = licenses.mit;
platforms = platforms.linux;
mainProgram = "my-app";
};
}
```
## Registration
### Register in `pkgs/default.nix`
Add your package to the registry:
```nix
{
inherit (pkgs) callPackage;
} rec {
# Existing packages
code2prompt = callPackage ./code2prompt {};
zellij-ps = callPackage ./zellij-ps {};
# Your new package
my-new-package = callPackage ./my-new-package {};
}
```
### With Custom Arguments
If your package needs custom arguments:
```nix
# pkgs/default.nix
{
inherit (pkgs) callPackage;
} rec {
my-new-package = callPackage ./my-new-package {
customArg = "value";
};
}
# pkgs/my-new-package/default.nix
{
lib,
stdenv,
fetchurl,
customArg, # This will be passed from the registry
}:
stdenv.mkDerivation {
# ...
}
```
## Getting Hashes
### Using `lib.fakeHash`
During development, use `lib.fakeHash` to get the real hash:
```nix
src = fetchFromGitHub {
owner = "author";
repo = "my-app";
rev = "v${version}";
hash = lib.fakeHash; # Temporary placeholder
};
```
Build the package:
```bash
nix build .#my-new-package
```
Copy the actual hash from the error message and update the package:
```nix
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; # Real hash
```
**Important**: Never commit `lib.fakeHash` to the repository.
## Testing
### Build Package
```bash
nix build .#my-new-package
```
### Test Execution
```bash
nix run .#my-new-package -- --help
```
### Run in Shell
```bash
nix shell .#my-new-package
my-new-app --version
```
### Linting
```bash
nix develop
statix check pkgs/my-new-package/
```
## Best Practices
### Meta Fields
Always include complete `meta` information:
```nix
meta = with lib; {
description = "Short one-line description";
longDescription = ''
Longer description explaining what the package does,
its features, and use cases.
'';
homepage = "https://github.com/author/repo";
changelog = "https://github.com/author/repo/releases/tag/v${version}";
license = licenses.mit;
platforms = platforms.linux;
mainProgram = "program-name";
};
```
### Dependencies
Explicitly declare all dependencies:
```nix
{
lib,
stdenv,
fetchFromGitHub,
# Runtime dependencies
openssl,
curl,
# Native build dependencies
pkg-config,
cmake,
}:
```
### Versioning
Use `rec` to reference `version` in multiple places:
```nix
rec {
pname = "my-app";
version = "1.0.0";
src = fetchFromGitHub {
rev = "v${version}";
# ...
};
}
```
### Platform Restrictions
If package is platform-specific:
```nix
meta = with lib; {
# Linux only
platforms = platforms.linux;
# Or specific platforms
platforms = ["x86_64-linux" "aarch64-linux"];
# Or exclude platforms
broken = stdenv.isDarwin;
};
```
## Troubleshooting
### Hash Mismatch
Error: `got: sha256-AAAAAAAA... expected: sha256-BBBBBB...`
Solution: Copy `got` hash and update package definition.
### Dependency Not Found
Error: `error: undefined variable 'somedep'`
Solution: Add dependency to function arguments and build inputs:
```nix
{
lib,
somedep, # Add here
}:
stdenv.mkDerivation {
buildInputs = [somedep]; # Add here
}
```
### Import Check Failure
Error: `error: Python module 'mymodule' not found`
Solution: Disable or fix imports check:
```nix
pythonImportsCheck = ["mymodule"]; # Check this is correct
# Or if importing creates side effects:
pythonImportsCheck = [];
```
## Examples
See existing packages in the repository:
- `pkgs/code2prompt/` - Rust package
- `pkgs/mem0/` - Python package
- `pkgs/hyprpaper-random/` - Shell script
- `pkgs/msty-studio/` - AppImage
- `pkgs/zellij-ps/` - Fetch from Gitea
## Next Steps
- [Architecture](../ARCHITECTURE.md) - Understanding package organization
- [Using Modules](./using-modules.md) - If you need to create modules
- [Contributing](../CONTRIBUTING.md) - Code style and guidelines
+527
View File
@@ -0,0 +1,527 @@
# Development Workflow Guide
Development, testing, and contribution workflow for m3ta-nixpkgs.
## Initial Setup
### Clone Repository
```bash
git clone https://code.m3ta.dev/m3tam3re/nixpkgs.git
cd nixpkgs
```
### Enter Development Shell
```bash
# Default shell (includes linting tools)
nix develop
# Python shell
nix develop .#python
# DevOps shell
nix develop .#devops
```
### Development Shell Tools
The default dev shell includes:
- `statix` - Nix linter
- `deadnix` - Find dead code
- `alejandra` - Code formatter
## Workflow
### 1. Create Feature Branch
```bash
# Checkout main and pull latest
git checkout main
git pull
# Create feature branch
git checkout -b feature/my-new-package
```
### 2. Make Changes
```bash
# Create new package
mkdir -p pkgs/my-package
vim pkgs/my-package/default.nix
# Or modify existing package
vim pkgs/existing-package/default.nix
# Or add module
vim modules/nixos/my-module.nix
```
### 3. Format Code
```bash
# Format all files
nix fmt
# Format specific file
alejandra path/to/file.nix
```
**Always format before committing.**
### 4. Test Changes
#### Build Package
```bash
# Build specific package
nix build .#my-package
# Build all packages
nix build .#packages.x86_64-linux
```
#### Run Package
```bash
# Test if package runs
nix run .#my-package -- --help
# Or enter shell with package
nix shell .#my-package
my-package --version
```
#### Validate Flake
```bash
# Validate all outputs
nix flake check
# Show all outputs
nix flake show
```
#### Test Module
```bash
# Test NixOS configuration
sudo nixos-rebuild test --flake .#hostname
# Test Home Manager configuration
home-manager switch --flake .#username@hostname
```
### 5. Lint Code
```bash
# Enter dev shell for linting tools
nix develop
# Run statix
statix check .
# Run deadnix
deadnix .
# Fix auto-fixable issues
statix fix .
```
### 6. Commit Changes
```bash
# Stage changes
git add .
# Commit with conventional format
git commit -m "feat: add my-package for doing X"
# Commit types: feat, fix, docs, style, refactor, chore, test
```
### 7. Push and Create PR
```bash
# Push branch
git push origin feature/my-new-package
# Create PR via web interface or CLI
gh pr create --title "feat: add my-package" --body "Description of changes"
```
## Testing Strategies
### Local Testing
#### Test Package Build
```bash
# Build for current system
nix build .#my-package
# Build for specific system
nix build .#my-package --system aarch64-linux
# Build for macOS
nix build .#my-package --system x86_64-darwin
```
#### Test Package Functionality
```bash
# Enter shell with package
nix shell .#my-package
# Run the program
my-package --help
my-package --version
# Test with sample data
echo "test" | my-package
```
#### Test Configuration
```bash
# Test NixOS configuration
sudo nixos-rebuild test --flake .#hostname
# Test Home Manager configuration
home-manager switch --flake .#username@hostname
# Check configuration syntax
nix eval .#nixosConfigurations.hostname.config --apply builtins.attrNames
```
### Integration Testing
#### Test with Real Services
```bash
# If package is a service
# 1. Add to configuration
# 2. Apply configuration
sudo nixos-rebuild switch
# 3. Test service
systemctl status my-service
journalctl -u my-service -f
# 4. Test functionality
curl http://localhost:8080
```
#### Test with Dependencies
```bash
# Build dependency chain
nix build .#my-package \
--rebuild \
--keep-going
# Check if dependencies are satisfied
nix path-info .#my-package --references
```
## Continuous Integration
### Pre-Commit Hook
Create `.git/hooks/pre-commit`:
```bash
#!/usr/bin/env bash
set -euo pipefail
# Format code
nix fmt
# Lint
statix check .
deadnix .
# Validate
nix flake check
# Test build
nix build .#your-package
```
Make executable:
```bash
chmod +x .git/hooks/pre-commit
```
### Pre-Push Hook
Create `.git/hooks/pre-push`:
```bash
#!/usr/bin/env bash
set -euo pipefail
# Validate flake
nix flake check
# Run tests if they exist
# make test
```
## Debugging
### Build Failures
#### Hash Mismatch
Error: `got: sha256-AAAAAAAA... expected: sha256-BBBBBB...`
Solution: Copy the `got` hash and update package:
```nix
src = fetchFromGitHub {
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; # Use actual hash
};
```
#### Dependency Not Found
Error: `error: undefined variable 'somelib'`
Solution: Check function arguments:
```nix
{
lib,
stdenv,
fetchFromGitHub,
somelib, # Add this if missing
}:
```
#### Build Failed
Error: `builder for '/nix/store/...' failed`
Solution:
```bash
# Build with verbose output
nix build .#my-package -v --show-trace
# Check build logs
nix log .#my-package
# Enter build environment for debugging
nix shell -f .#my-package .bashInteractive
```
### Runtime Failures
#### Package Not Executable
Error: `error: operation not permitted`
Solution: Check `mainProgram` in meta:
```nix
meta = with lib; {
mainProgram = "my-app"; # Must match executable name
};
```
#### Library Not Found
Error: `error while loading shared libraries: libfoo.so`
Solution: Add to build inputs:
```nix
buildInputs = [someLib];
```
### Configuration Failures
#### Option Not Found
Error: `error: The option 'm3ta.mymodule' does not exist`
Solution: Import the module:
```nix
imports = [
m3ta-nixpkgs.nixosModules.default
];
```
## Common Tasks
### Update Package Version
```bash
# 1. Update version in package definition
vim pkgs/my-package/default.nix
# 2. Build to get new hash
nix build .#my-package
# 3. Update hash from error message
# 4. Test new version
nix run .#my-package -- --version
# 5. Commit
git commit -m "chore: update my-package to v2.0.0"
```
### Update Dependencies
```bash
# 1. Update fetcher version/rev
vim pkgs/my-package/default.nix
# 2. Update dependencies if needed
vim pkgs/my-package/default.nix
# 3. Build and test
nix build .#my-package
nix run .#my-package -- --help
# 4. Commit
git commit -m "fix: update dependencies for my-package"
```
### Add Tests
```bash
# 1. Add test to package
vim pkgs/my-package/default.nix
# 2. Run tests
nix build .#my-package
# 3. Verify tests pass
# 4. Commit
git commit -m "test: add tests for my-package"
```
### Fix Linting Issues
```bash
# 1. Run linter
nix develop
statix check .
# 2. Fix issues manually or auto-fix
statix fix .
# 3. Check again
statix check .
# 4. Commit
git commit -m "style: fix linting issues"
```
## Performance Optimization
### Use Caching
```bash
# Use binary cache (if available)
nix build .#my-package --substituters https://cache.nixos.org https://your-cache.example.com
# Use local cache
nix build .#my-package --max-jobs 4
```
### Parallel Builds
```bash
# Build multiple packages in parallel
nix build .#package1 .#package2 .#package3
```
### Incremental Builds
```bash
# Only rebuild changed packages
nix build .#my-package --check
# Don't rebuild dependencies
nix build .#my-package --no-link
```
## Release Process
### Version Bump
```bash
# 1. Update versions as needed
vim pkgs/*/default.nix
# 2. Update CHANGELOG.md
vim CHANGELOG.md
# 3. Test all packages
nix flake check
# 4. Commit
git commit -m "chore: prepare release v1.0.0"
```
### Tag Release
```bash
# Create tag
git tag -a v1.0.0 -m "Release v1.0.0"
# Push tag
git push origin v1.0.0
# Push with tags
git push --follow-tags
```
### Update Flakes
Update flake lock after release:
```bash
# Update lock file
nix flake update
# Commit
git commit -m "chore: update flake lock"
```
## Checklist
### Before Committing
- [ ] Code formatted with `nix fmt`
- [ ] Passes `statix check .`
- [ ] Passes `deadnix .`
- [ ] Passes `nix flake check`
- [ ] Package builds successfully
- [ ] Package runs as expected
- [ ] Documentation updated (if needed)
- [ ] Commit message follows convention
### Before Merging PR
- [ ] All tests pass
- [ ] Code review approved
- [ ] No merge conflicts
- [ ] Documentation complete
- [ ] Breaking changes documented
## Resources
- [Contributing Guide](../CONTRIBUTING.md) - Code style and guidelines
- [Architecture](../ARCHITECTURE.md) - Understanding repository structure
- [Adding Packages](./adding-packages.md) - Package creation guide
- [Quick Start](../QUICKSTART.md) - Getting started guide
+402
View File
@@ -0,0 +1,402 @@
# Getting Started Guide
Initial setup and basic usage of m3ta-nixpkgs.
## Installation
### Prerequisites
Make sure you have Nix installed with flakes enabled:
```bash
# Check Nix version (need 2.4+)
nix --version
# Enable flakes (in /etc/nixos/configuration.nix)
nix.settings.experimental-features = ["nix-command" "flakes"]
# Rebuild NixOS
sudo nixos-rebuild switch
```
### Adding to Your Flake
#### Option 1: NixOS Configuration
Add to your `flake.nix`:
```nix
{
description = "My NixOS configuration";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
home-manager.url = "github:nix-community/home-manager";
m3ta-nixpkgs = {
url = "git+https://code.m3ta.dev/m3tam3re/nixpkgs";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = {
self,
nixpkgs,
home-manager,
m3ta-nixpkgs,
...
}: {
nixosConfigurations = {
myhost = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
./hardware-configuration.nix
# Import m3ta-nixpkgs modules
m3ta-nixpkgs.nixosModules.default
# Apply overlay
({pkgs, ...}: {
nixpkgs.overlays = [m3ta-nixpkgs.overlays.default];
# Packages from m3ta-nixpkgs are now available
environment.systemPackages = with pkgs; [
code2prompt
zellij-ps
];
})
# Home Manager integration
home-manager.nixosModules.home-manager
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.users.myusername = {
imports = [m3ta-nixpkgs.homeManagerModules.default];
home.packages = with pkgs; [
launch-webapp
];
};
}
];
};
};
};
}
```
#### Option 2: Standalone Home Manager
```nix
{
description = "My Home Manager configuration";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
home-manager.url = "github:nix-community/home-manager";
m3ta-nixpkgs = {
url = "git+https://code.m3ta.dev/m3tam3re/nixpkgs";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = {
self,
nixpkgs,
home-manager,
m3ta-nixpkgs,
}: let
system = "x86_64-linux";
pkgs = import nixpkgs {
inherit system;
overlays = [m3ta-nixpkgs.overlays.default];
};
in {
homeConfigurations.myusername = home-manager.lib.homeManagerConfiguration {
inherit pkgs;
modules = [
m3ta-nixpkgs.homeManagerModules.default
{
home.username = "myusername";
home.homeDirectory = "/home/myusername";
home.packages = with pkgs; [
code2prompt
zellij-ps
];
programs.home-manager.enable = true;
}
];
};
};
}
```
## Quick Usage
### Using Packages Directly
Without adding to your configuration:
```bash
# Build a package
nix build git+https://code.m3ta.dev/m3tam3re/nixpkgs#code2prompt
# Run a package
nix run git+https://code.m3ta.dev/m3tam3re/nixpkgs#zellij-ps
# List all available packages
nix flake show git+https://code.m3ta.dev/m3tam3re/nixpkgs
```
### Using Packages in Configuration
After applying overlay:
```nix
# System-wide (NixOS)
environment.systemPackages = with pkgs; [
code2prompt
zellij-ps
];
# User-only (Home Manager)
home.packages = with pkgs; [
launch-webapp
];
```
### Using Modules
```nix
# Import all modules
imports = [
m3ta-nixpkgs.nixosModules.default
];
# Or import specific module
imports = [
m3ta-nixpkgs.nixosModules.mem0
];
# Configure module
m3ta.mem0 = {
enable = true;
port = 8000;
};
```
## Common Tasks
### Install a Package System-Wide
```nix
# /etc/nixos/configuration.nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
code2prompt
hyprpaper-random
];
}
# Apply
sudo nixos-rebuild switch
```
### Install a Package for Your User
```nix
# home.nix
{pkgs, ...}: {
home.packages = with pkgs; [
launch-webapp
zellij-ps
];
}
# Apply
home-manager switch
```
### Enable a NixOS Module
```nix
# /etc/nixos/configuration.nix
{config, ...}: {
imports = [
m3ta-nixpkgs.nixosModules.default
];
m3ta.mem0 = {
enable = true;
port = 8000;
};
# Apply
# sudo nixos-rebuild switch
}
```
### Enable a Home Manager Module
```nix
# home.nix
{config, ...}: {
imports = [
m3ta-nixpkgs.homeManagerModules.default
];
cli.zellij-ps = {
enable = true;
};
# Apply
# home-manager switch
}
```
### Use Port Management
```nix
{config, ...}: {
m3ta.ports = {
enable = true;
definitions = {
nginx = 80;
grafana = 3000;
};
hostOverrides.laptop = {
nginx = 8080;
};
currentHost = config.networking.hostName;
};
services.nginx = {
enable = true;
httpConfig = ''
server {
listen ${toString (config.m3ta.ports.get "nginx")};
root /var/www;
}
'';
};
}
```
## Available Packages
| Package | Description |
| ------------------ | ------------------------------------- |
| `code2prompt` | Convert code to prompts |
| `hyprpaper-random` | Random wallpaper setter for Hyprpaper |
| `launch-webapp` | Launch web applications |
| `mem0` | AI memory assistant with vector storage |
| `msty-studio` | Msty Studio application |
| `pomodoro-timer` | Pomodoro timer utility |
| `tuxedo-backlight` | Backlight control for Tuxedo laptops |
| `zellij-ps` | Project switcher for Zellij |
## Available Modules
### NixOS Modules
- `ports` - Port management across hosts
- `mem0` - Mem0 REST API server
### Home Manager Modules
- `ports` - Port management (with `generateEnvVars`)
- `cli.zellij-ps` - Zellij project switcher
- `coding.editors` - Editor configurations
## Development
### Development Shells
```bash
# Default dev shell
nix develop
# Python dev shell
nix develop .#python
# DevOps dev shell
nix develop .#devops
```
### Building and Testing
```bash
# Build package
nix build .#code2prompt
# Validate flake
nix flake check
# List outputs
nix flake show
# Format code
nix fmt
```
### Linting (in dev shell)
```bash
nix develop
# Run linter
statix check .
# Find dead code
deadnix .
```
## Troubleshooting
### Package Not Found
**Error**: `error: undefined variable 'code2prompt'`
**Solution**: Make sure you applied the overlay:
```nix
nixpkgs.overlays = [m3ta-nixpkgs.overlays.default];
```
### Module Not Found
**Error**: `error: The option 'm3ta.mem0' does not exist`
**Solution**: Make sure you imported the module:
```nix
imports = [
m3ta-nixpkgs.nixosModules.default
# or
m3ta-nixpkgs.nixosModules.mem0
];
```
### Hash Mismatch
**Error**: `got: sha256-AAAAAAAA... expected: sha256-BBBBBB...`
**Solution**: Copy the `got` hash from the error and update the package definition.
### Building for Different System
```bash
# Build for aarch64-linux
nix build .#code2prompt --system aarch64-linux
# Build for macOS
nix build .#code2prompt --system x86_64-darwin
```
## Next Steps
- [Adding Packages](./adding-packages.md) - How to add new packages
- [Using Modules](./using-modules.md) - Deep dive into modules
- [Port Management](./port-management.md) - Managing service ports
- [Architecture](../ARCHITECTURE.md) - Understanding the repository structure
+525
View File
@@ -0,0 +1,525 @@
# Port Management Guide
Managing service ports across multiple hosts with the `m3ta.ports` module.
## Overview
The port management module provides a centralized way to define service ports that can have host-specific overrides. This prevents port conflicts and makes it easy to manage services across multiple machines.
## Basic Usage
### Enable Port Management
```nix
{config, ...}: {
m3ta.ports = {
enable = true;
# Define default ports
definitions = {
nginx = 80;
grafana = 3000;
prometheus = 9090;
homepage = 8080;
};
# Define host-specific overrides
hostOverrides = {
laptop = {
nginx = 8080; # Override on laptop
homepage = 3001; # Override on laptop
};
server = {
homepage = 3002; # Override on server
};
};
# Set current host (determines which overrides to use)
currentHost = config.networking.hostName;
};
}
```
### Using Ports
```nix
{config, ...}: {
services.nginx = {
enable = true;
httpConfig = ''
server {
listen ${toString (config.m3ta.ports.get "nginx")};
root /var/www;
}
'';
};
services.grafana = {
enable = true;
settings.server.http_port = config.m3ta.ports.get "grafana";
};
}
```
## Module Options
### `m3ta.ports.enable`
Enable port management module.
- Type: `boolean`
- Default: `false`
### `m3ta.ports.definitions`
Default port definitions.
- Type: `attrsOf int`
- Default: `{}`
```nix
definitions = {
nginx = 80;
grafana = 3000;
prometheus = 9090;
};
```
### `m3ta.ports.hostOverrides`
Host-specific port overrides.
- Type: `attrsOf (attrsOf int)`
- Default: `{}`
```nix
hostOverrides = {
laptop = {
nginx = 8080;
grafana = 3001;
};
server = {
grafana = 3002;
};
};
```
### `m3ta.ports.currentHost`
Current hostname. Determines which overrides to apply.
- Type: `string`
- Example: `config.networking.hostName`
```nix
currentHost = "laptop"; # Use laptop overrides
```
### `m3ta.ports.generateEnvVars` (Home Manager only)
Generate environment variables from ports.
- Type: `boolean`
- Default: `false` (Home Manager)
- NixOS: Not available
When enabled, generates environment variables like:
- `PORT_NGINX=8080`
- `PORT_GRAFANA=3000`
## Functions
### `config.m3ta.ports.get "service"`
Get port for a service with host-specific override.
```nix
services.nginx = {
port = config.m3ta.ports.get "nginx";
};
```
If current host is `laptop` and `hostOverrides.laptop.nginx = 8080`, returns `8080`.
If no override, returns default `80`.
### `config.m3ta.ports.getHostPorts "hostname"`
Get all ports for a specific host.
```nix
# Get all ports for laptop
laptopPorts = config.m3ta.ports.getHostPorts "laptop";
# Returns: { nginx = 8080; grafana = 3000; ... }
```
### `config.m3ta.ports.listServices`
List all defined service names.
```nix
allServices = config.m3ta.ports.listServices;
# Returns: ["nginx" "grafana" "prometheus" "homepage"]
```
## Examples
### NixOS Configuration
```nix
{config, ...}: {
# Define ports
m3ta.ports = {
enable = true;
definitions = {
nginx = 80;
grafana = 3000;
prometheus = 9090;
loki = 3100;
promtail = 9080;
};
hostOverrides.laptop = {
nginx = 8080;
grafana = 3001;
};
currentHost = config.networking.hostName;
};
# Use ports
services.nginx = {
enable = true;
httpConfig = ''
server {
listen ${toString (config.m3ta.ports.get "nginx")};
root /var/www;
}
'';
};
services.grafana = {
enable = true;
settings.server.http_port = config.m3ta.ports.get "grafana";
};
services.prometheus = {
enable = true;
port = config.m3ta.ports.get "prometheus";
};
services.loki = {
enable = true;
configuration.http_listen_port = config.m3ta.ports.get "loki";
};
}
```
### Home Manager Configuration
```nix
{config, ...}: {
# Define ports
m3ta.ports = {
enable = true;
definitions = {
dev-server = 3000;
nextjs = 3001;
vite = 5173;
};
hostOverrides.desktop = {
vite = 5174;
};
currentHost = "desktop";
generateEnvVars = true; # Generate env vars
};
# Ports are now available as env vars
# PORT_DEV_SERVER=3000
# PORT_NEXTJS=3001
# PORT_VITE=5174
home.sessionVariables = {
DEV_PORT = toString (config.m3ta.ports.get "dev-server");
};
}
```
### With Custom Modules
Using ports with custom modules (e.g., `m3ta.mem0`):
```nix
{config, ...}: {
# Define ports
m3ta.ports = {
enable = true;
definitions = {
mem0 = 8000;
qdrant = 6333;
};
hostOverrides.laptop = {
mem0 = 8080;
};
currentHost = config.networking.hostName;
};
# Use with mem0 module
m3ta.mem0 = {
enable = true;
port = config.m3ta.ports.get "mem0"; # 8000 or 8080 on laptop
};
# Use with qdrant service
services.qdrant = {
enable = true;
port = config.m3ta.ports.get "qdrant";
};
}
```
### Port File Generation
Generate a JSON file with all ports:
```nix
{config, pkgs, ...}: {
m3ta.ports = {
enable = true;
definitions = {
service1 = 80;
service2 = 443;
};
currentHost = config.networking.hostName;
};
# Generate port file
environment.etc."m3ta/ports.json".text = builtins.toJSON (
config.m3ta.ports.getHostPorts config.networking.hostName
);
}
```
## Advanced Usage
### Conditional Configuration
```nix
{config, ...}: {
services.nginx = {
enable = true;
# Only open firewall if binding to non-localhost
httpConfig = let
port = config.m3ta.ports.get "nginx";
in ''
server {
listen ${toString port};
}
'';
};
networking.firewall.allowedTCPPorts =
if config.m3ta.ports.get "nginx" == 80
then [80]
else [];
}
```
### Port Ranges
```nix
definitions = {
service-start = 8000;
service-end = 8999;
};
# Use in config
services.my-app = {
portRange = [
config.m3ta.ports.get "service-start"
config.m3ta.ports.get "service-end"
];
};
```
### Dynamic Port Allocation
```nix
{config, ...}: {
m3ta.ports = {
enable = true;
definitions = {
# Reserve port ranges
app-range-start = 9000;
app-range-end = 9999;
};
currentHost = config.networking.hostName;
};
# Calculate next available port
services.my-app = {
port = config.m3ta.ports.get "app-range-start" + 0;
};
services.my-other-app = {
port = config.m3ta.ports.get "app-range-start" + 1;
};
}
```
## Best Practices
### Use Descriptive Service Names
```nix
# Good
definitions = {
nginx = 80;
grafana = 3000;
prometheus-ui = 9090;
prometheus-push = 9091;
};
# Avoid
definitions = {
p1 = 80;
p2 = 3000;
p3 = 9090;
};
```
### Group Related Services
```nix
definitions = {
# Monitoring stack
grafana = 3000;
prometheus = 9090;
loki = 3100;
promtail = 9080;
# Web services
nginx = 80;
homepage = 8080;
# Databases
postgres = 5432;
redis = 6379;
qdrant = 6333;
};
```
### Document Overrides
```nix
hostOverrides = {
# Laptop: Running multiple dev servers, use higher ports
laptop = {
nginx = 8080;
dev-server = 3000;
};
# Server: Production, use standard ports
server = {
nginx = 80;
dev-server = null; # Disable on server
};
};
```
### Handle Missing Ports
```nix
services.some-service = {
enable = true;
port = config.m3ta.ports.get "some-service" or 8080;
};
```
## Troubleshooting
### Service Not Found
Error: `Service "foo" not defined`
Solution: Add service to `definitions`:
```nix
definitions = {
foo = 8080;
};
```
### Current Host Not Set
Error: `currentHost not set`
Solution: Set `currentHost`:
```nix
currentHost = config.networking.hostName;
```
### Port Conflict
Issue: Two services trying to use same port.
Solution: Define both in port management:
```nix
definitions = {
service1 = 8080;
service2 = 8081; # Different port
};
```
## Migration from Hardcoded Ports
### Before
```nix
services.nginx = {
enable = true;
httpConfig = ''
server {
listen 80;
}
'';
};
services.grafana = {
enable = true;
settings.server.http_port = 3000;
};
```
### After
```nix
m3ta.ports = {
enable = true;
definitions = {
nginx = 80;
grafana = 3000;
};
currentHost = config.networking.hostName;
};
services.nginx = {
enable = true;
httpConfig = ''
server {
listen ${toString (config.m3ta.ports.get "nginx")};
}
'';
};
services.grafana = {
enable = true;
settings.server.http_port = config.m3ta.ports.get "grafana";
};
```
## Next Steps
- [Architecture](../ARCHITECTURE.md) - Understanding the library functions
- [Using Modules](./using-modules.md) - Using modules with port management
- [Contributing](../CONTRIBUTING.md) - Code style and guidelines
+605
View File
@@ -0,0 +1,605 @@
# Using Modules Guide
How to use NixOS and Home Manager modules from m3ta-nixpkgs.
## Overview
Modules in m3ta-nixpkgs provide reusable configuration for NixOS (system-level) and Home Manager (user-level) settings. All modules use the `m3ta.*` namespace.
## Module Organization
### NixOS Modules
Located in `modules/nixos/`:
```
modules/nixos/
├── default.nix # Aggregates all NixOS modules
├── ports.nix # Port management
└── mem0.nix # Mem0 REST API server
```
### Home Manager Modules
Located in `modules/home-manager/` with categories:
```
modules/home-manager/
├── default.nix # Aggregates all HM modules
├── ports.nix # Port management
├── cli/ # CLI tools
│ ├── default.nix # Aggregates CLI modules
│ └── zellij-ps.nix
└── coding/ # Development tools
├── default.nix # Aggregates coding modules
└── editors.nix
```
## Importing Modules
### NixOS Modules
#### Import All Modules
```nix
{config, ...}: {
imports = [
m3ta-nixpkgs.nixosModules.default
];
}
```
#### Import Specific Module
```nix
{config, ...}: {
imports = [
m3ta-nixpkgs.nixosModules.mem0
];
}
```
#### Import from Local Path
```nix
{config, ...}: {
imports = [
./modules/nixos/mem0.nix
];
}
```
### Home Manager Modules
#### Import All Modules
```nix
{config, ...}: {
imports = [
m3ta-nixpkgs.homeManagerModules.default
];
}
```
#### Import Specific Module
```nix
{config, ...}: {
imports = [
m3ta-nixpkgs.homeManagerModules.ports
];
}
```
#### Import Category
```nix
{config, ...}: {
imports = [
# Import all CLI modules
m3ta-nixpkgs.homeManagerModules.cli.zellij-ps
];
}
```
## Available Modules
### NixOS Modules
#### `m3ta.ports`
Port management across hosts.
```nix
m3ta.ports = {
enable = true;
definitions = {
nginx = 80;
grafana = 3000;
};
hostOverrides.laptop = {
nginx = 8080;
};
currentHost = config.networking.hostName;
};
```
**Documentation**: [Port Management Guide](./port-management.md)
#### `m3ta.mem0`
Mem0 REST API server for AI memory.
```nix
m3ta.mem0 = {
enable = true;
port = 8000;
llm = {
provider = "openai";
apiKeyFile = "/run/secrets/openai-api-key";
model = "gpt-4o-mini";
};
vectorStore = {
provider = "qdrant";
config = {
host = "localhost";
port = 6333;
};
};
};
```
**Documentation**: [mem0 Module](../modules/nixos/mem0.md)
### Home Manager Modules
#### `m3ta.ports`
Port management (similar to NixOS, with `generateEnvVars`).
```nix
m3ta.ports = {
enable = true;
definitions = {
dev-server = 3000;
};
generateEnvVars = true;
currentHost = config.networking.hostName;
};
```
**Documentation**: [Port Management Guide](./port-management.md)
#### `cli.zellij-ps`
Zellij project switcher for quickly navigating between project folders.
```nix
cli.zellij-ps = {
enable = true;
package = pkgs.zellij-ps;
};
```
**Documentation**: [zellij-ps Module](../modules/home-manager/cli/zellij-ps.md)
#### `coding.editors`
Editor configurations.
```nix
m3ta.coding.editors = {
enable = true;
neovim.enable = true;
zed.enable = true;
};
```
**Documentation**: [Editors Module](../modules/home-manager/coding/editors.md)
## Common Patterns
### Module Configuration
All modules follow this pattern:
```nix
{ config, lib, pkgs, ... }:
with lib; let
cfg = config.m3ta.myModule;
in {
options.m3ta.myModule = {
enable = mkEnableOption "description";
# ... other options
};
config = mkIf cfg.enable {
# ... configuration
};
}
```
### Conditional Configuration
Use `mkIf` to conditionally apply config:
```nix
config = mkIf cfg.enable {
# Only applied when cfg.enable = true
services.my-service = {
enable = true;
};
}
```
### Multiple Conditions
Use `mkMerge` for multiple conditions:
```nix
config = mkMerge [
(mkIf cfg.feature1.enable {
# Applied when feature1 is enabled
})
(mkIf cfg.feature2.enable {
# Applied when feature2 is enabled
})
];
```
### Optional Dependencies
```nix
options.m3ta.myModule = {
enable = mkEnableOption "my module";
package = mkOption {
type = types.package;
default = pkgs.defaultPackage;
};
};
config = mkIf cfg.enable {
services.my-service = {
package = cfg.package;
};
};
```
## Configuration Examples
### Minimal NixOS Configuration
```nix
{pkgs, ...}: {
imports = [
m3ta-nixpkgs.nixosModules.default
];
m3ta.ports = {
enable = true;
definitions = {
my-service = 8080;
};
currentHost = "laptop";
};
services.my-custom-service = {
enable = true;
port = config.m3ta.ports.get "my-service";
};
}
```
### Full NixOS Configuration
```nix
{config, pkgs, ...}: {
imports = [
m3ta-nixpkgs.nixosModules.default
];
# Port management
m3ta.ports = {
enable = true;
definitions = {
nginx = 80;
grafana = 3000;
prometheus = 9090;
mem0 = 8000;
};
hostOverrides.laptop = {
nginx = 8080;
mem0 = 8081;
};
currentHost = config.networking.hostName;
};
# Mem0 service
m3ta.mem0 = {
enable = true;
port = config.m3ta.ports.get "mem0";
llm = {
provider = "openai";
apiKeyFile = "/run/secrets/openai-api-key";
};
vectorStore = {
provider = "qdrant";
config = {
host = "localhost";
port = 6333;
};
};
};
# Nginx
services.nginx = {
enable = true;
httpConfig = ''
server {
listen ${toString (config.m3ta.ports.get "nginx")};
root /var/www;
}
'';
};
# Grafana
services.grafana = {
enable = true;
settings.server.http_port = config.m3ta.ports.get "grafana";
};
}
```
### Minimal Home Manager Configuration
```nix
{pkgs, ...}: {
imports = [
m3ta-nixpkgs.homeManagerModules.default
];
m3ta.ports = {
enable = true;
definitions = {
dev-server = 3000;
};
currentHost = "desktop";
};
home.sessionVariables = {
DEV_PORT = toString (config.m3ta.ports.get "dev-server");
};
}
```
### Full Home Manager Configuration
```nix
{config, pkgs, ...}: {
imports = [
m3ta-nixpkgs.homeManagerModules.default
];
# Port management
m3ta.ports = {
enable = true;
definitions = {
dev-server = 3000;
nextjs = 3001;
vite = 5173;
};
hostOverrides.laptop = {
vite = 5174;
};
currentHost = config.networking.hostName;
};
# CLI tools
cli.zellij-ps = {
enable = true;
};
# Coding tools
coding.editors = {
enable = true;
neovim.enable = true;
};
# Packages
home.packages = with pkgs; [
code2prompt
zellij-ps
];
# Environment variables
home.sessionVariables = {
EDITOR = "nvim";
DEV_SERVER_PORT = toString (config.m3ta.ports.get "dev-server");
};
}
```
## Module Options Reference
### Standard Options
All modules typically include:
| Option | Type | Description |
|---------|-------|-------------|
| `enable` | `boolean` | Enable the module |
| `package` | `package` | Custom package to use |
| `extraConfig` | `attrs` | Additional configuration |
### Port Management Options
| Option | Type | Description |
|---------|-------|-------------|
| `definitions` | `attrsOf int` | Default port definitions |
| `hostOverrides` | `attrsOf attrs` | Host-specific overrides |
| `currentHost` | `string` | Current hostname |
| `generateEnvVars` | `boolean` | Generate environment variables (HM only) |
## Combining with Other Flakes
### Using Multiple Module Sources
```nix
{config, ...}: {
imports = [
# m3ta-nixpkgs modules
m3ta-nixpkgs.nixosModules.default
# Other flake modules
inputs.impermanence.nixosModules.impermanence
inputs.sops-nix.nixosModules.sops
];
# Configure all modules
m3ta.ports = {
enable = true;
definitions = {nginx = 80;};
currentHost = config.networking.hostName;
};
environment.persistence = {
"/persist" = {
directories = ["/var/lib/mem0"];
};
};
}
```
### Using with Secrets
```nix
{config, ...}: {
imports = [
m3ta-nixpkgs.nixosModules.default
inputs.sops-nix.nixosModules.sops
];
sops.secrets = {
openai-api-key = {};
};
m3ta.mem0 = {
enable = true;
llm = {
apiKeyFile = config.sops.secrets.openai-api-key.path;
};
};
}
```
## Troubleshooting
### Module Not Found
Error: `error: The option 'm3ta.mymodule' does not exist`
**Solutions**:
1. Make sure you imported the module:
```nix
imports = [
m3ta-nixpkgs.nixosModules.default
];
```
2. Check module name is correct
```nix
# Correct
m3ta.mem0.enable = true;
# Wrong
m3ta.mymodule.enable = true; # Doesn't exist
```
### Option Type Mismatch
Error: `type mismatch at 'm3ta.mymodule.enable', expected a boolean but got a list`
**Solution**: Check option types in documentation
```nix
# Correct
m3ta.mymodule.enable = true;
# Wrong
m3ta.mymodule.enable = [true]; # Should be boolean
```
### Port Not Defined
Error: `Service "foo" not defined`
**Solution**: Add to port definitions
```nix
m3ta.ports = {
definitions = {
foo = 8080; # Add this
};
};
```
## Best Practices
### Use Namespaces
Always use the `m3ta.*` namespace:
```nix
# Good
m3ta.mem0.enable = true;
# Bad (potential conflicts)
mem0.enable = true;
```
### Document Your Configuration
Add comments explaining module usage:
```nix
# Port management for multi-host setup
m3ta.ports = {
enable = true;
definitions = {
nginx = 80;
grafana = 3000;
};
hostOverrides.laptop = {
nginx = 8080; # Use different port on laptop
};
currentHost = config.networking.hostName;
};
# Mem0 AI memory service
m3ta.mem0 = {
enable = true;
port = config.m3ta.ports.get "mem0";
};
```
### Test Configuration
```bash
# Test NixOS configuration without applying
sudo nixos-rebuild test --flake .#hostname
# Check configuration
nix flake check
# Show all options
nix eval .#nixosConfigurations.hostname.config.m3ta --apply builtins.attrNames
```
## Next Steps
- [Port Management](./port-management.md) - Detailed port management guide
- [Adding Packages](./adding-packages.md) - How to add new packages
- [Architecture](../ARCHITECTURE.md) - Understanding module structure
- [Contributing](../CONTRIBUTING.md) - Code style and guidelines
@@ -0,0 +1,219 @@
# rofi-project-opener Module
Home Manager module for configuring the rofi-project-opener package.
## Overview
This module provides declarative configuration for rofi-project-opener, a Rofi-based project launcher. It generates the necessary configuration files and installs the package.
## Quick Start
```nix
{config, pkgs, ...}: {
cli.rofi-project-opener = {
enable = true;
projectDirs = {
dev = { path = "~/dev"; };
work = { path = "~/work"; args = "--agent work-assistant"; };
};
};
}
```
## Options
### `cli.rofi-project-opener.enable`
Whether to enable rofi-project-opener.
**Type:** `boolean`
**Default:** `false`
### `cli.rofi-project-opener.projectDirs`
Attribute set of base directories to scan for project subdirectories.
**Type:** `attrsOf (submodule)`
Each entry is a submodule with:
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `path` | `str` | required | Base directory path (supports `~`) |
| `args` | `str` | `""` | Arguments to pass to command |
**Default:**
```nix
{
dev = { path = "~/dev"; };
projects = { path = "~/projects"; };
}
```
**Example:**
```nix
projectDirs = {
nixpkgs = { path = "~/p/NIX"; args = "--agent nix-expert"; };
chat = { path = "~/p/CHAT"; args = "--agent chiron"; };
dev = { path = "~/dev"; };
work = { path = "~/work"; args = "--profile work"; };
};
```
### `cli.rofi-project-opener.terminal`
Terminal emulator to use for launching projects.
**Type:** `either str package`
**Default:** `"kitty"`
**Examples:**
```nix
# Using a package
terminal = pkgs.kitty;
terminal = pkgs.alacritty;
# Using a string (must be in PATH)
terminal = "kitty";
terminal = "wezterm";
```
### `cli.rofi-project-opener.terminalCommand`
Command to run in the terminal after navigating to the project directory.
**Type:** `str`
**Default:** `""` (runs `opencode` with args)
**Placeholders:**
- `%s` - Project path
- `%a` - Project args (from `projectDirs.<name>.args`)
**Examples:**
```nix
# Default behavior - run opencode with project args
terminalCommand = "";
# Explicit opencode with args
terminalCommand = "opencode %a";
# Different editor
terminalCommand = "nvim";
# VSCode with path
terminalCommand = "code %s";
# Custom application
terminalCommand = "my-dev-tool --project %s %a";
```
### `cli.rofi-project-opener.rofiPrompt`
Prompt text displayed in the Rofi menu.
**Type:** `str`
**Default:** `"Select project"`
### `cli.rofi-project-opener.rofiArgs`
Arguments to pass to Rofi.
**Type:** `listOf str`
**Default:** `["-dmenu" "-i"]`
**Example:**
```nix
rofiArgs = ["-dmenu" "-i" "-theme" "gruvbox" "-width" "50"];
```
## Generated Files
The module generates these configuration files:
### `~/.config/rofi-project-opener/projects.json`
JSON file containing project directories:
```json
{
"dev": {"path": "~/dev", "args": ""},
"work": {"path": "~/work", "args": "--agent work-assistant"}
}
```
### `~/.config/rofi-project-opener/config`
Shell configuration file:
```bash
TERMINAL="/nix/store/.../bin/kitty"
TERMINAL_CMD="opencode %a"
ROFI_PROMPT="Select project"
ROFI_ARGS="-dmenu -i"
```
## Full Example
```nix
{config, pkgs, ...}: {
imports = [m3ta-nixpkgs.homeManagerModules.default];
cli.rofi-project-opener = {
enable = true;
# Project directories with optional args
projectDirs = {
nixpkgs = {
path = "~/p/NIX";
args = "";
};
chat = {
path = "~/p/CHAT";
args = "--agent chiron";
};
dev = {
path = "~/dev";
args = "";
};
};
# Terminal configuration
terminal = pkgs.kitty;
terminalCommand = "opencode %a";
# Rofi configuration
rofiPrompt = "Open Project";
rofiArgs = ["-dmenu" "-i" "-theme" "nord"];
};
}
```
## Usage
After enabling, run:
```bash
rofi-project-opener
```
Or bind to a keyboard shortcut in your window manager:
**Hyprland:**
```nix
wayland.windowManager.hyprland.settings.bind = [
"$mod, P, exec, rofi-project-opener"
];
```
**Sway:**
```nix
wayland.windowManager.sway.config.keybindings = {
"${modifier}+p" = "exec rofi-project-opener";
};
```
## Related
- [rofi-project-opener Package](../../../packages/rofi-project-opener.md) - Package documentation
- [zellij-ps Module](./zellij-ps.md) - Similar project switcher for Zellij
- [Home Manager Overview](../overview.md) - All Home Manager modules
+312
View File
@@ -0,0 +1,312 @@
# stt-ptt Home Manager Module
Push to Talk Speech to Text for Home Manager.
## Overview
This module configures stt-ptt, a push-to-talk speech-to-text tool using whisper.cpp. It handles model downloads, environment configuration, and package installation.
## Quick Start
```nix
{config, ...}: {
imports = [m3ta-nixpkgs.homeManagerModules.default];
cli.stt-ptt = {
enable = true;
};
}
```
This will:
- Install stt-ptt with default whisper-cpp
- Download the `ggml-large-v3-turbo` model on first activation
- Set environment variables for model path and notification timeout
## Module Options
### `cli.stt-ptt.enable`
Enable the stt-ptt module.
- Type: `boolean`
- Default: `false`
### `cli.stt-ptt.whisperPackage`
The whisper-cpp package to use for transcription.
- Type: `package`
- Default: `pkgs.whisper-cpp`
**Pre-built variants:**
```nix
# CPU (default)
whisperPackage = pkgs.whisper-cpp;
# Vulkan GPU acceleration (pre-built)
whisperPackage = pkgs.whisper-cpp-vulkan;
```
**Override options** (can be combined):
| Option | Description |
|--------|-------------|
| `cudaSupport` | NVIDIA CUDA acceleration |
| `rocmSupport` | AMD ROCm acceleration |
| `vulkanSupport` | Vulkan GPU acceleration |
| `coreMLSupport` | Apple CoreML (macOS only) |
| `metalSupport` | Apple Metal (macOS ARM only) |
```nix
# NVIDIA CUDA support
whisperPackage = pkgs.whisper-cpp.override { cudaSupport = true; };
# AMD ROCm support
whisperPackage = pkgs.whisper-cpp.override { rocmSupport = true; };
# Vulkan support (manual override)
whisperPackage = pkgs.whisper-cpp.override { vulkanSupport = true; };
```
### `cli.stt-ptt.model`
The Whisper model to use. Models are automatically downloaded from HuggingFace on first activation.
- Type: `string`
- Default: `"ggml-large-v3-turbo"`
Available models (sorted by size):
| Model | Size | Notes |
|-------|------|-------|
| `ggml-tiny` | 75MB | Fastest, lowest quality |
| `ggml-tiny.en` | 75MB | English-only, slightly faster |
| `ggml-base` | 142MB | Fast, basic quality |
| `ggml-base.en` | 142MB | English-only |
| `ggml-small` | 466MB | Balanced speed/quality |
| `ggml-small.en` | 466MB | English-only |
| `ggml-medium` | 1.5GB | Good quality |
| `ggml-medium.en` | 1.5GB | English-only |
| `ggml-large-v1` | 2.9GB | High quality (original) |
| `ggml-large-v2` | 2.9GB | High quality (improved) |
| `ggml-large-v3` | 2.9GB | Highest quality |
| `ggml-large-v3-turbo` | 1.6GB | High quality, optimized speed (recommended) |
Quantized versions (`q5_0`, `q5_1`, `q8_0`) are also available for reduced size.
### `cli.stt-ptt.notifyTimeout`
Notification timeout in milliseconds for the recording indicator.
- Type: `integer`
- Default: `3000`
- Example: `5000` (5 seconds), `0` (persistent)
### `cli.stt-ptt.language`
Language for speech recognition. Use "auto" for automatic language detection, or specify a language code for better accuracy.
- Type: `enum ["auto", "en", "es", "fr", "de", "it", "pt", "ru", "zh", "ja", "ko", "ar", "hi", "tr", "pl", "nl", "sv", "da", "fi", "no", "vi", "th", "id", "uk", "cs"]`
- Default: `"auto"`
**Auto-detection**: When set to "auto", whisper.cpp analyzes the audio to determine the spoken language automatically.
**Language specification**: Specifying a language code improves transcription accuracy if you know the language in advance.
```nix
# Automatic language detection (default)
language = "auto";
# Force English transcription
language = "en";
# Spanish transcription
language = "es";
```
**Common language codes:**
| Code | Language |
|------|----------|
| `en` | English |
| `es` | Spanish |
| `fr` | French |
| `de` | German |
| `zh` | Chinese |
| `ja` | Japanese |
| `ko` | Korean |
whisper.cpp supports 100+ languages. See whisper.cpp documentation for the full list.
## Usage
After enabling, bind `stt-ptt start` and `stt-ptt stop` to a key:
```bash
# Start recording
stt-ptt start
# Stop recording and transcribe (types result)
stt-ptt stop
```
### Keybinding Examples
#### Hyprland
```nix
wayland.windowManager.hyprland.settings = {
bind = [
"SUPER, V, exec, stt-ptt start"
];
bindr = [
"SUPER, V, exec, stt-ptt stop"
];
};
```
Or in `hyprland.conf`:
```conf
# Press to start recording, release to transcribe
bind = SUPER, V, exec, stt-ptt start
bindr = SUPER, V, exec, stt-ptt stop
```
#### Sway
```conf
bindsym --no-repeat $mod+v exec stt-ptt start
bindsym --release $mod+v exec stt-ptt stop
```
## Configuration Examples
### Basic Setup
```nix
cli.stt-ptt = {
enable = true;
};
```
### Fast English Transcription
```nix
cli.stt-ptt = {
enable = true;
model = "ggml-base.en";
notifyTimeout = 2000;
};
```
### Language-Specific Transcription
```nix
cli.stt-ptt = {
enable = true;
model = "ggml-large-v3-turbo";
language = "es"; # Force Spanish transcription
};
```
### High Quality with NVIDIA GPU
```nix
cli.stt-ptt = {
enable = true;
model = "ggml-large-v3";
whisperPackage = pkgs.whisper-cpp.override { cudaSupport = true; };
};
```
### Vulkan GPU Acceleration
```nix
cli.stt-ptt = {
enable = true;
model = "ggml-large-v3-turbo";
whisperPackage = pkgs.whisper-cpp-vulkan;
};
```
### AMD GPU with ROCm
```nix
cli.stt-ptt = {
enable = true;
model = "ggml-large-v3-turbo";
whisperPackage = pkgs.whisper-cpp.override { rocmSupport = true; };
};
```
### Balanced Setup
```nix
cli.stt-ptt = {
enable = true;
model = "ggml-small";
notifyTimeout = 3000;
};
```
## File Locations
| Path | Description |
|------|-------------|
| `~/.local/share/stt-ptt/models/` | Downloaded Whisper models |
| `~/.cache/stt-ptt/stt.wav` | Temporary audio recording |
| `~/.cache/stt-ptt/stt.pid` | PID file for recording process |
## Environment Variables
The module sets these automatically:
| Variable | Value |
|----------|-------|
| `STT_MODEL` | `~/.local/share/stt-ptt/models/<model>.bin` |
| `STT_LANGUAGE` | Configured language ("auto" by default) |
| `STT_NOTIFY_TIMEOUT` | Configured timeout in ms |
## Requirements
- Wayland compositor (wtype is Wayland-only)
- PipeWire for audio recording
- Desktop notification daemon
## Troubleshooting
### Model Download Failed
The model downloads on first `home-manager switch`. If it fails:
```bash
# Manual download
mkdir -p ~/.local/share/stt-ptt/models
curl -L -o ~/.local/share/stt-ptt/models/ggml-large-v3-turbo.bin \
https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-large-v3-turbo.bin
```
### Transcription Too Slow
Use a smaller model or enable GPU acceleration:
```nix
cli.stt-ptt = {
enable = true;
model = "ggml-tiny.en"; # Much faster
};
```
### Text Not Appearing
1. Ensure you're on Wayland: `echo $XDG_SESSION_TYPE`
2. Check if wtype works: `wtype "test"`
3. Some apps may need focus; try clicking the text field first
## Related
- [stt-ptt Package](../../../packages/stt-ptt.md) - Package documentation
- [Using Modules Guide](../../../guides/using-modules.md) - Module usage patterns
@@ -0,0 +1,81 @@
# zellij-ps Home Manager Module
Zellij project switcher for Home Manager.
## Overview
This module configures the zellij-ps tool, a Fish script that provides a fast, interactive way to switch between project folders in Zellij terminal multiplexer sessions.
## Quick Start
```nix
{config, ...}: {
imports = [m3ta-nixpkgs.homeManagerModules.default];
cli.zellij-ps = {
enable = true;
};
}
```
## Module Options
### `cli.zellij-ps.enable`
Enable zellij-ps module.
- Type: `boolean`
- Default: `false`
### `cli.zellij-ps.package`
Custom package to use.
- Type: `package`
- Default: `pkgs.zellij-ps`
## Usage
After enabling, zellij-ps will be available in your path:
```bash
# Run from outside Zellij to start a project session
zellij-ps
# Or pass a project path directly
zellij-ps ~/projects/my-project
```
### Basic Usage
1. Set `$PROJECT_FOLDERS` in your shell config (e.g., `~/projects:~/code`)
2. Run `zellij-ps` from outside a Zellij session
3. Use fzf to select a project from your configured folders
4. Zellij will create or attach to a session for that project
## Configuration
### Custom Package
Use a custom or modified package:
```nix
cli.zellij-ps = {
enable = true;
package = pkgs.callPackage ./my-zellij-ps {};
};
```
## Dependencies
The module ensures these are installed:
- `fish` - Shell for script execution
- `fd` - Fast file search
- `fzf` - Fuzzy finder
- `zellij` - Terminal multiplexer
## Related
- [zellij-ps Package](../../packages/zellij-ps.md) - Package documentation
- [Using Modules Guide](../../guides/using-modules.md) - Module usage patterns
+317
View File
@@ -0,0 +1,317 @@
# editors Home Manager Module
Editor configurations for Home Manager.
## Overview
This module provides pre-configured settings for various code editors, making it easy to set up your development environment.
## Quick Start
```nix
{config, ...}: {
imports = [m3ta-nixpkgs.homeManagerModules.default];
m3ta.coding.editors = {
enable = true;
neovim.enable = true;
zed.enable = true;
};
}
```
## Module Options
### `m3ta.coding.editors.enable`
Enable the editors module.
- Type: `boolean`
- Default: `false`
### `m3ta.coding.editors.neovim.enable`
Enable Neovim configuration.
- Type: `boolean`
- Default: `false`
### `m3ta.coding.editors.neovim.package`
Custom Neovim package.
- Type: `package`
- Default: `pkgs.neovim`
### `m3ta.coding.editors.zed.enable`
Enable Zed editor configuration.
- Type: `boolean`
- Default: `false`
### `m3ta.coding.editors.zed.package`
Custom Zed package.
- Type: `package`
- Default: `pkgs.zed`
## Supported Editors
### Neovim
Neovim is a highly extensible Vim-based text editor.
```nix
m3ta.coding.editors = {
enable = true;
neovim = {
enable = true;
package = pkgs.neovim;
};
}
```
**Features**:
- Vim-style editing
- Plugin system
- Lua scripting
- Fast performance
- Built-in LSP support
**Configuration**: The module provides sensible defaults. You can customize by adding your own configuration.
### Zed
Zed is a high-performance, multiplayer code editor.
```nix
m3ta.coding.editors = {
enable = true;
zed = {
enable = true;
package = pkgs.zed;
};
}
```
**Features**:
- Fast startup
- Built-in collaboration
- AI assistance (optional)
- Modern UI
- Low memory usage
**Configuration**: Zed uses JSON configuration files that can be customized.
## Usage Examples
### Minimal Neovim Setup
```nix
{config, ...}: {
m3ta.coding.editors = {
enable = true;
neovim.enable = true;
};
}
```
### Minimal Zed Setup
```nix
{config, ...}: {
m3ta.coding.editors = {
enable = true;
zed.enable = true;
};
}
```
### Multiple Editors
```nix
{config, ...}: {
m3ta.coding.editors = {
enable = true;
neovim.enable = true;
zed.enable = true;
};
}
```
### Custom Package
```nix
{config, ...}: {
m3ta.coding.editors = {
enable = true;
neovim = {
enable = true;
package = pkgs.neovim-unwrapped; # Use unwrapped version
};
};
}
```
## Configuration Files
### Neovim
The module sets up Neovim configuration in:
```
~/.config/nvim/
```
You can extend it with:
```nix
{config, ...}: {
xdg.configFile."nvim/init.lua".text = ''
-- Your custom Neovim configuration
'';
}
```
### Zed
Zed configuration is in:
```
~/.config/zed/settings.json
```
You can customize it with:
```nix
{config, ...}: {
xdg.configFile."zed/settings.json".text = builtins.toJSON {
# Your custom Zed settings
};
}
```
## Migration Guide
### From Manual Configuration
If you have existing editor configurations, you can:
1. Backup your current config
2. Enable the module
3. Test it out
4. Gradually migrate custom settings
**Backup**:
```bash
# Backup Neovim
cp -r ~/.config/nvim ~/.config/nvim.backup
# Backup Zed
cp -r ~/.config/zed ~/.config/zed.backup
```
### From Other Editors
**Vim to Neovim**:
- Most Vim configurations work with Neovim
- Enable module and test
- Migrate plugins to modern Lua versions
**VSCode to Zed**:
- Zed has built-in keybinding presets
- Enable module and check keybindings
- Adjust as needed
## Keybindings
### Neovim
Default keybindings (Vim-style):
| Mode | Key | Action |
|-------|------|---------|
| Normal | `i` | Enter insert mode |
| Normal | `ESC` | Exit insert mode |
| Normal | `:w` | Save |
| Normal | `:q` | Quit |
| Normal | `u` | Undo |
| Normal | `Ctrl+r` | Redo |
### Zed
Default keybindings:
| Mode | Key | Action |
|-------|------|---------|
| General | `Ctrl+S` | Save |
| General | `Ctrl+P` | Command palette |
| General | `Ctrl+Shift+P` | File palette |
| Navigation | `Ctrl+B` | Toggle sidebar |
| Navigation | `Ctrl+Shift+B` | Toggle activity bar |
## Plugins and Extensions
### Neovim
The module provides a base. You can add plugins using:
```nix
{pkgs, ...}: {
programs.neovim.plugins = with pkgs.vimPlugins; [
nvim-lspconfig
nvim-treesitter
telescope-nvim
];
}
```
### Zed
Zed extensions are managed through the editor:
1. Open Zed
2. Go to Extensions (Ctrl+Shift+X)
3. Browse and install extensions
## Troubleshooting
### Editor Not Found
Ensure the editor package is installed:
```bash
# Check Neovim
which nvim
# Check Zed
which zed
```
### Configuration Not Applied
Check if the module is enabled:
```bash
# Check Home Manager state
home-manager show
# View current config
nix eval .#homeConfigurations.username.config.m3ta.coding.editors --apply builtins.attrNames
```
### Conflicts with Existing Config
If you have existing configuration:
1. Backup current config
2. Test module with fresh config
3. Gradually add custom settings
## Related
- [Using Modules Guide](../../guides/using-modules.md) - How to use modules
- [Adding Packages](../../guides/adding-packages.md) - How to add new packages
+206
View File
@@ -0,0 +1,206 @@
# Home Manager Modules Overview
Overview of available Home Manager modules in m3ta-nixpkgs.
## Available Modules
### Core Modules
- [ports](./ports.md) - Port management across hosts
### CLI Modules (`cli/`)
- [zellij-ps](./cli/zellij-ps.md) - Zellij project switcher
### Coding Modules (`coding/`)
- [editors](./coding/editors.md) - Editor configurations
## Importing Modules
### Import All Modules
```nix
{config, ...}: {
imports = [
m3ta-nixpkgs.homeManagerModules.default
];
}
```
### Import Specific Module
```nix
{config, ...}: {
imports = [
m3ta-nixpkgs.homeManagerModules.ports
m3ta-nixpkgs.homeManagerModules.zellij-ps
];
}
```
### Import Category
```nix
{config, ...}: {
imports = [
m3ta-nixpkgs.homeManagerModules.cli.zellij-ps
m3ta-nixpkgs.homeManagerModules.coding.editors
];
}
```
## Module Namespace
All Home Manager modules use the `m3ta.*` namespace:
```nix
# Port management
m3ta.ports = {
enable = true;
definitions = {dev-server = 3000;};
};
# CLI tools
cli.zellij-ps = {
enable = true;
};
# Coding tools
coding.editors = {
enable = true;
neovim.enable = true;
};
```
## Module Categories
### Core
Essential modules for all users:
- **ports** - Port management with optional environment variable generation
### CLI (`cli/`)
Command-line interface tools and utilities:
- **zellij-ps** - Project switcher for Zellij terminal multiplexer
### Coding (`coding/`)
Development tools and configurations:
- **editors** - Editor configurations (Neovim, Zed, etc.)
## Integration Examples
### With NixOS
```nix
{config, ...}: {
# NixOS modules
imports = [
m3ta-nixpkgs.nixosModules.default
];
# Home Manager integration
home-manager.users.myusername = {
imports = [
m3ta-nixpkgs.homeManagerModules.default
];
m3ta.ports = {
enable = true;
definitions = {
dev-server = 3000;
};
currentHost = config.networking.hostName;
};
};
}
```
### Standalone Home Manager
```nix
{config, pkgs, ...}: {
imports = [
m3ta-nixpkgs.homeManagerModules.default
];
m3ta.ports = {
enable = true;
definitions = {
dev-server = 3000;
};
currentHost = "desktop";
};
cli.zellij-ps = {
enable = true;
};
coding.editors = {
enable = true;
neovim.enable = true;
};
}
```
## Module Locations
### Core
- `modules/home-manager/ports.nix` - Port management module
### CLI
- `modules/home-manager/cli/default.nix` - CLI module aggregator
- `modules/home-manager/cli/zellij-ps.nix` - Zellij project switcher
### Coding
- `modules/home-manager/coding/default.nix` - Coding module aggregator
- `modules/home-manager/coding/editors.nix` - Editor configurations
## Adding New Modules
### Core Module
1. Create: `modules/home-manager/my-module.nix`
2. Add to `modules/home-manager/default.nix`
### CLI Module
1. Create: `modules/home-manager/cli/my-tool.nix`
2. Add to `modules/home-manager/cli/default.nix`
### Coding Module
1. Create: `modules/home-manager/coding/my-tool.nix`
2. Add to `modules/home-manager/coding/default.nix`
### Module Template
```nix
{ config, lib, pkgs, ... }:
with lib; let
cfg = config.m3ta.category.myModule;
in {
options.m3ta.category.myModule = {
enable = mkEnableOption "my module";
# ... options
};
config = mkIf cfg.enable {
# Configuration
};
}
```
## Related
- [Using Modules Guide](../../guides/using-modules.md) - How to use modules
- [NixOS Modules](./nixos/overview.md) - System-level modules
- [Port Management Guide](../../guides/port-management.md) - Detailed port management
+272
View File
@@ -0,0 +1,272 @@
# ports Home Manager Module
Port management module for Home Manager.
## Overview
This module provides centralized port management for user-level services, similar to the NixOS version but with additional support for generating environment variables.
See [Port Management Guide](../../guides/port-management.md) for detailed usage.
## Quick Start
```nix
{config, ...}: {
m3ta.ports = {
enable = true;
# Define default ports
definitions = {
dev-server = 3000;
nextjs = 3001;
vite = 5173;
};
# Host-specific overrides
hostOverrides = {
laptop = {
vite = 5174;
};
};
# Current host
currentHost = "desktop";
# Generate environment variables (Home Manager only)
generateEnvVars = true;
};
}
```
## Module Options
### `m3ta.ports.enable`
Enable port management.
- Type: `boolean`
- Default: `false`
### `m3ta.ports.definitions`
Default port definitions.
- Type: `attrsOf int`
- Default: `{}`
Example:
```nix
definitions = {
dev-server = 3000;
nextjs = 3001;
vite = 5173;
};
```
### `m3ta.ports.hostOverrides`
Host-specific port overrides.
- Type: `attrsOf (attrsOf int)`
- Default: `{}`
Example:
```nix
hostOverrides = {
laptop = {
vite = 5174;
};
desktop = {
vite = 5173;
};
};
```
### `m3ta.ports.currentHost`
Current hostname.
- Type: `string`
- Example: `"desktop"`
### `m3ta.ports.generateEnvVars`
Generate environment variables from ports.
- Type: `boolean`
- Default: `false`
- Home Manager only
When enabled, generates environment variables like:
```bash
PORT_DEV_SERVER=3000
PORT_NEXTJS=3001
PORT_VITE=5173
```
## Functions
### `config.m3ta.ports.get "service"`
Get port for a service with host-specific override.
```nix
home.sessionVariables = {
DEV_PORT = toString (config.m3ta.ports.get "dev-server");
};
```
### `config.m3ta.ports.getHostPorts "hostname"`
Get all ports for a specific host.
```nix
laptopPorts = config.m3ta.ports.getHostPorts "laptop";
# Returns: { dev-server = 3000; vite = 5174; ... }
```
### `config.m3ta.ports.listServices`
List all defined service names.
```nix
allServices = config.m3ta.ports.listServices;
# Returns: ["dev-server" "nextjs" "vite"]
```
## Environment Variables
When `generateEnvVars = true`, the following environment variables are generated:
```
PORT_<SERVICE_UPPERCASE>=<port_number>
```
Example:
```nix
m3ta.ports = {
enable = true;
definitions = {
dev-server = 3000;
nextjs = 3001;
};
generateEnvVars = true;
};
```
Generates:
```bash
PORT_DEV_SERVER=3000
PORT_NEXTJS=3001
```
You can then use these in scripts:
```bash
#!/usr/bin/env bash
# Use environment variable directly
npm start --port=$PORT_DEV_SERVER
```
## Usage Examples
### Basic Usage
```nix
{config, ...}: {
m3ta.ports = {
enable = true;
definitions = {
dev-server = 3000;
};
currentHost = "desktop";
};
home.sessionVariables = {
DEV_PORT = toString (config.m3ta.ports.get "dev-server");
};
}
```
### With Environment Variables
```nix
{config, ...}: {
m3ta.ports = {
enable = true;
definitions = {
dev-server = 3000;
nextjs = 3001;
vite = 5173;
};
currentHost = "desktop";
generateEnvVars = true;
};
# Now available as environment variables
# PORT_DEV_SERVER=3000
# PORT_NEXTJS=3001
# PORT_VITE=5173
}
```
### With Multi-Host Setup
```nix
{config, ...}: {
m3ta.ports = {
enable = true;
definitions = {
dev-server = 3000;
vite = 5173;
};
hostOverrides = {
laptop = {
vite = 5174;
};
desktop = {
vite = 5173;
};
};
currentHost = config.networking.hostName;
generateEnvVars = true;
};
}
```
### With Shell Scripts
Create `~/.config/zellij/scripts/dev.ksh`:
```ksh
#!/usr/bin/env ksh
# Start dev server using environment variable
cd ~/projects/my-app
npm start --port=$PORT_DEV_SERVER
```
## Difference from NixOS Module
The Home Manager version has one additional feature:
### `generateEnvVars`
Not available in NixOS module. Generates environment variables for all defined ports:
```nix
# Home Manager
m3ta.ports.generateEnvVars = true; # Available
# NixOS
# Not available
```
## Related
- [Port Management Guide](../../guides/port-management.md) - Detailed guide
- [NixOS Ports Module](../nixos/ports.md) - System-level port management
+508
View File
@@ -0,0 +1,508 @@
# mem0 NixOS Module
Mem0 REST API server module for AI memory management.
## Overview
This module provides a systemd service for the Mem0 REST API server, enabling AI agents to maintain persistent memory across conversations.
## Quick Start
```nix
{config, ...}: {
imports = [m3ta-nixpkgs.nixosModules.mem0];
m3ta.mem0 = {
enable = true;
port = 8000;
llm = {
provider = "openai";
apiKeyFile = "/run/secrets/openai-api-key";
model = "gpt-4o-mini";
};
vectorStore = {
provider = "qdrant";
config = {
host = "localhost";
port = 6333;
};
};
};
}
```
## Module Options
### `m3ta.mem0.enable`
Enable the Mem0 REST API server.
- Type: `boolean`
- Default: `false`
### `m3ta.mem0.package`
The mem0 package to use.
- Type: `package`
- Default: `pkgs.mem0`
### `m3ta.mem0.host`
Host address to bind the server to.
- Type: `string`
- Default: `"127.0.0.1"`
### `m3ta.mem0.port`
Port to run the REST API server on.
- Type: `port`
- Default: `8000`
### `m3ta.mem0.workers`
Number of worker processes.
- Type: `integer`
- Default: `1`
### `m3ta.mem0.logLevel`
Logging level for the server.
- Type: `enum` ["critical" "error" "warning" "info" "debug" "trace"]
- Default: `"info"`
### `m3ta.mem0.stateDir`
Directory to store mem0 data and state.
- Type: `path`
- Default: `"/var/lib/mem0"`
### `m3ta.mem0.user`
User account under which mem0 runs.
- Type: `string`
- Default: `"mem0"`
### `m3ta.mem0.group`
Group under which mem0 runs.
- Type: `string`
- Default: `"mem0"`
### `m3ta.mem0.environmentFile`
Environment file containing additional configuration.
- Type: `nullOr path`
- Default: `null`
## LLM Configuration
### `m3ta.mem0.llm.provider`
LLM provider to use.
- Type: `enum` ["openai" "anthropic" "azure" "groq" "together" "ollama" "litellm"]
- Default: `"openai"`
### `m3ta.mem0.llm.model`
Model name to use.
- Type: `string`
- Default: `"gpt-4o-mini"`
### `m3ta.mem0.llm.apiKeyFile`
Path to file containing the API key.
- Type: `nullOr path`
- Default: `null`
- Example: `"/run/secrets/openai-api-key"`
### `m3ta.mem0.llm.temperature`
Temperature parameter for LLM generation.
- Type: `nullOr float`
- Default: `null`
### `m3ta.mem0.llm.maxTokens`
Maximum tokens for LLM generation.
- Type: `nullOr int`
- Default: `null`
### `m3ta.mem0.llm.extraConfig`
Additional LLM configuration options.
- Type: `attrs`
- Default: `{}`
## Vector Store Configuration
### `m3ta.mem0.vectorStore.provider`
Vector database provider.
- Type: `enum` ["qdrant" "chroma" "pinecone" "weaviate" "faiss" "pgvector" "redis" "elasticsearch" "milvus"]
- Default: `"qdrant"`
### `m3ta.mem0.vectorStore.config`
Configuration for the vector store.
- Type: `attrs`
- Default: `{}`
Example for Qdrant:
```nix
vectorStore.config = {
host = "localhost";
port = 6333;
collection_name = "mem0_memories";
};
```
Example for pgvector:
```nix
vectorStore.config = {
host = "localhost";
port = 5432;
dbname = "postgres";
user = "postgres";
password = "postgres";
};
```
## Embedder Configuration
### `m3ta.mem0.embedder.provider`
Embedding model provider.
- Type: `nullOr (enum` ["openai" "huggingface" "ollama" "vertexai"])
- Default: `null`
### `m3ta.mem0.embedder.model`
Embedding model name.
- Type: `nullOr string`
- Default: `null`
### `m3ta.mem0.embedder.config`
Configuration for the embedder.
- Type: `attrs`
- Default: `{}`
## Usage Examples
### Minimal Configuration
```nix
{config, ...}: {
m3ta.mem0 = {
enable = true;
};
}
```
### With OpenAI
```nix
{config, ...}: {
m3ta.mem0 = {
enable = true;
llm = {
provider = "openai";
apiKeyFile = "/run/secrets/openai-api-key";
model = "gpt-4";
};
};
}
```
### With Local LLM (Ollama)
```nix
{config, ...}: {
m3ta.mem0 = {
enable = true;
llm = {
provider = "ollama";
model = "llama2";
};
};
}
```
### With Port Management
```nix
{config, ...}: {
m3ta.ports = {
enable = true;
definitions = {
mem0 = 8000;
};
currentHost = config.networking.hostName;
};
m3ta.mem0 = {
enable = true;
port = config.m3ta.ports.get "mem0";
};
}
```
### With Qdrant
```nix
{config, ...}: {
m3ta.mem0 = {
enable = true;
vectorStore = {
provider = "qdrant";
config = {
host = "localhost";
port = 6333;
};
};
};
}
services.qdrant = {
enable = true;
port = 6333;
};
```
### With Secrets (agenix)
```nix
{config, ...}: {
age.secrets.openai-api-key = {
file = ./secrets/openai-api-key.age;
};
m3ta.mem0 = {
enable = true;
llm = {
apiKeyFile = config.age.secrets.openai-api-key.path;
};
};
}
```
## Service Management
### Start/Stop/Restart
```bash
# Start service
sudo systemctl start mem0
# Stop service
sudo systemctl stop mem0
# Restart service
sudo systemctl restart mem0
# Check status
sudo systemctl status mem0
```
### View Logs
```bash
# View logs
sudo journalctl -u mem0 -f
# View last 100 lines
sudo journalctl -u mem0 -n 100
```
### Service File
The module creates a systemd service at `/etc/systemd/system/mem0.service` with:
- Security hardening enabled
- Automatic restart on failure
- Proper user/group setup
## API Usage
### Add Memory
```bash
curl -X POST http://localhost:8000/v1/memories \
-H "Content-Type: application/json" \
-d '{
"content": "User prefers coffee over tea",
"metadata": {"user_id": "123"}
}'
```
### Search Memories
```bash
curl http://localhost:8000/v1/memories/search?q=coffee
```
### Update Memory
```bash
curl -X PATCH http://localhost:8000/v1/memories/memory_id \
-H "Content-Type: application/json" \
-d '{
"content": "User prefers coffee over tea, but also likes chai"
}'
```
### Delete Memory
```bash
curl -X DELETE http://localhost:8000/v1/memories/memory_id
```
## Dependencies
### Required Services
Depending on your configuration, you may need:
- **qdrant** service (if using qdrant vector store)
- **postgresql** with pgvector (if using pgvector)
- **chroma** service (if using chroma)
- **ollama** (if using local LLMs)
### Example: Qdrant
```nix
services.qdrant = {
enable = true;
port = 6333;
};
```
### Example: PostgreSQL
```nix
services.postgresql = {
enable = true;
enableTCPIP = true;
package = pkgs.postgresql_15;
extensions = ["pgvector"];
settings = {
port = 5432;
};
};
```
## Firewall
The module automatically opens the firewall port if binding to non-localhost addresses:
```nix
# Opens port if host is not "127.0.0.1" or "localhost"
m3ta.mem0 = {
enable = true;
host = "0.0.0.0"; # Binds to all interfaces
port = 8000;
};
# Firewall automatically opens port 8000
```
## Security
### User/Group
Creates dedicated user and group:
- User: `mem0`
- Group: `mem0`
- Home: `/var/lib/mem0`
### Hardening
Systemd service includes security hardening:
- `NoNewPrivileges`
- `PrivateTmp`
- `ProtectSystem=strict`
- `ProtectHome=true`
- `RestrictRealtime=true`
- `RestrictNamespaces=true`
- `LockPersonality=true`
### Secrets
Use `apiKeyFile` for API keys instead of plain text:
```nix
# Good
llm.apiKeyFile = "/run/secrets/openai-api-key";
# Bad (insecure)
llm.apiKey = "sk-xxx";
```
## Troubleshooting
### Service Won't Start
Check logs:
```bash
sudo journalctl -u mem0 -n 50
```
Common issues:
1. **API key missing**: Ensure `apiKeyFile` exists and is readable
2. **Vector store unavailable**: Ensure qdrant/other store is running
3. **Port in use**: Check if port is available
### API Not Responding
Check service status:
```bash
sudo systemctl status mem0
# Check if port is open
ss -tuln | grep 8000
```
### Memory Issues
Increase memory limit in systemd override:
```bash
sudo systemctl edit mem0
[Service]
MemoryMax=2G
```
## Related
- [mem0 Package](../../packages/mem0.md) - Package documentation
- [Port Management Guide](../../guides/port-management.md) - Using with port management
- [Using Modules Guide](../../guides/using-modules.md) - Module usage patterns
+166
View File
@@ -0,0 +1,166 @@
# NixOS Modules Overview
Overview of available NixOS modules in m3ta-nixpkgs.
## Available Modules
- [ports](./ports.md) - Port management across hosts
- [mem0](./mem0.md) - Mem0 REST API server
## Importing Modules
### Import All Modules
```nix
{config, ...}: {
imports = [
m3ta-nixpkgs.nixosModules.default
];
}
```
### Import Specific Module
```nix
{config, ...}: {
imports = [
m3ta-nixpkgs.nixosModules.ports
m3ta-nixpkgs.nixosModules.mem0
];
}
```
## Module Namespace
All NixOS modules use the `m3ta.*` namespace:
```nix
# Port management
m3ta.ports = {
enable = true;
definitions = {nginx = 80;};
};
# Mem0 service
m3ta.mem0 = {
enable = true;
port = 8000;
};
```
## Common Patterns
### Enable Module
All modules follow the pattern:
```nix
m3ta.moduleName = {
enable = true;
# ... options
};
```
### Configuration
Modules typically provide these sections:
- `enable` - Enable/disable module
- `package` - Custom package (optional)
- Configuration options specific to module
## Integration Examples
### With Port Management
```nix
{config, ...}: {
imports = [
m3ta-nixpkgs.nixosModules.default
];
m3ta.ports = {
enable = true;
definitions = {
nginx = 80;
grafana = 3000;
mem0 = 8000;
};
currentHost = config.networking.hostName;
};
m3ta.mem0 = {
enable = true;
port = config.m3ta.ports.get "mem0";
};
services.nginx = {
enable = true;
httpConfig = ''
server {
listen ${toString (config.m3ta.ports.get "nginx")};
root /var/www;
}
'';
};
}
```
### With Home Manager
```nix
{config, ...}: {
# NixOS modules
imports = [
m3ta-nixpkgs.nixosModules.default
];
# Home Manager integration
home-manager.users.myusername = {
imports = [
m3ta-nixpkgs.homeManagerModules.default
];
m3ta.ports = {
enable = true;
definitions = {
dev-server = 3000;
};
currentHost = config.networking.hostName;
};
};
}
```
## Module Locations
- `modules/nixos/ports.nix` - Port management module
- `modules/nixos/mem0.nix` - Mem0 REST API server module
## Adding New Modules
1. Create module file: `modules/nixos/my-module.nix`
2. Follow standard pattern:
```nix
{ config, lib, pkgs, ... }:
with lib; let
cfg = config.m3ta.myModule;
in {
options.m3ta.myModule = {
enable = mkEnableOption "my module";
};
config = mkIf cfg.enable {
# Configuration
};
}
```
3. Import in `modules/nixos/default.nix`
## Related
- [Port Management Guide](../guides/port-management.md) - Detailed port management usage
- [Using Modules Guide](../guides/using-modules.md) - How to use modules
- [Home Manager Modules](./home-manager/overview.md) - User-level modules
+229
View File
@@ -0,0 +1,229 @@
# ports NixOS Module
Port management module for NixOS.
## Overview
This module provides centralized port management across multiple hosts. Define default ports and host-specific overrides to prevent conflicts.
See [Port Management Guide](../../guides/port-management.md) for detailed usage.
## Quick Start
```nix
{config, ...}: {
m3ta.ports = {
enable = true;
# Define default ports
definitions = {
nginx = 80;
grafana = 3000;
prometheus = 9090;
};
# Host-specific overrides
hostOverrides = {
laptop = {
nginx = 8080;
grafana = 3001;
};
};
# Current host
currentHost = config.networking.hostName;
};
}
```
## Module Options
### `m3ta.ports.enable`
Enable port management.
- Type: `boolean`
- Default: `false`
### `m3ta.ports.definitions`
Default port definitions.
- Type: `attrsOf int`
- Default: `{}`
Example:
```nix
definitions = {
nginx = 80;
grafana = 3000;
prometheus = 9090;
};
```
### `m3ta.ports.hostOverrides`
Host-specific port overrides.
- Type: `attrsOf (attrsOf int)`
- Default: `{}`
Example:
```nix
hostOverrides = {
laptop = {
nginx = 8080;
grafana = 3001;
};
server = {
nginx = 80;
prometheus = 9091;
};
};
```
### `m3ta.ports.currentHost`
Current hostname. Determines which overrides to apply.
- Type: `string`
- Example: `config.networking.hostName`
## Functions
### `config.m3ta.ports.get "service"`
Get port for a service with host-specific override.
```nix
services.nginx = {
port = config.m3ta.ports.get "nginx";
};
```
If current host is `laptop` and `hostOverrides.laptop.nginx = 8080`, returns `8080`.
If no override, returns default `80`.
### `config.m3ta.ports.getHostPorts "hostname"`
Get all ports for a specific host.
```nix
# Get all ports for laptop
laptopPorts = config.m3ta.ports.getHostPorts "laptop";
# Returns: { nginx = 8080; grafana = 3000; ... }
```
### `config.m3ta.ports.listServices`
List all defined service names.
```nix
allServices = config.m3ta.ports.listServices;
# Returns: ["nginx" "grafana" "prometheus"]
```
## Usage Examples
### Basic Usage
```nix
{config, ...}: {
m3ta.ports = {
enable = true;
definitions = {
nginx = 80;
grafana = 3000;
};
currentHost = "server";
};
services.nginx = {
enable = true;
httpConfig = ''
server {
listen ${toString (config.m3ta.ports.get "nginx")};
}
'';
};
}
```
### Multi-Host Setup
```nix
{config, ...}: {
m3ta.ports = {
enable = true;
definitions = {
nginx = 80;
grafana = 3000;
prometheus = 9090;
};
hostOverrides = {
laptop = {
nginx = 8080;
grafana = 3001;
};
server = {
nginx = 80;
grafana = 3000;
};
};
currentHost = config.networking.hostName;
};
services.nginx = {
enable = true;
httpConfig = ''
server {
listen ${toString (config.m3ta.ports.get "nginx")};
}
'';
};
}
```
### With Multiple Services
```nix
{config, ...}: {
m3ta.ports = {
enable = true;
definitions = {
# Monitoring
grafana = 3000;
prometheus = 9090;
loki = 3100;
promtail = 9080;
# Web
nginx = 80;
# Databases
postgres = 5432;
redis = 6379;
qdrant = 6333;
};
currentHost = config.networking.hostName;
};
# Use ports
services.grafana = {
enable = true;
settings.server.http_port = config.m3ta.ports.get "grafana";
};
services.postgresql = {
enable = true;
port = config.m3ta.ports.get "postgres";
};
}
```
## Related
- [Port Management Guide](../../guides/port-management.md) - Detailed guide
- [Home Manager Ports Module](../home-manager/ports.md) - User-level port management
+220
View File
@@ -0,0 +1,220 @@
# beads
Lightweight memory system for AI coding agents with graph-based issue tracking.
## Description
beads is a command-line tool designed to provide persistent memory and issue tracking for AI coding agents. It features a graph-based system for managing issues, dependencies, and discovered work across development sessions.
## Features
- 🧠 **Persistent Memory**: Store and retrieve context across AI sessions
- 📊 **Graph-Based Issue Tracking**: Manage issues with dependency relationships
- 🔄 **Discovered Work**: Track work discovered during development
- 🎯 **Multi-Session Continuity**: Resume work from previous sessions
- 📝 **Git Integration**: Seamless integration with git workflows
- 🐚 **Shell Completions**: Bash, Fish, and Zsh completions included
## Installation
### Via Overlay
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
beads
];
}
```
### Direct Reference
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
inputs.m3ta-nixpkgs.packages.${pkgs.system}.beads
];
}
```
### Run Directly
```bash
nix run git+https://code.m3ta.dev/m3tam3re/nixpkgs#beads
```
## Usage
### Basic Commands
```bash
# Show available issues ready to work on
bd ready
# Create a new issue
bd create "Fix authentication bug" --type bug --priority 2
# Show issue details
bd show beads-123
# Update issue status
bd update beads-123 --status in_progress
# Close completed issues
bd close beads-123
# Sync with git remote
bd sync
```
### Issue Types
- `task`: General tasks
- `bug`: Bug fixes
- `feature`: New features
- `epic`: Large-scale initiatives
### Priority Levels
- `0` (P0): Critical
- `1` (P1): High
- `2` (P2): Medium
- `3` (P3): Low
- `4` (P4): Backlog
### Dependency Management
```bash
# Add dependency (beads-123 depends on beads-456)
bd dep add beads-123 beads-456
# Show blocked issues
bd blocked
# Show what blocks an issue
bd show beads-123 --blocked-by
```
## Advanced Usage
### Finding Work
```bash
# Show ready tasks (no blockers)
bd ready
# Show all open issues
bd list --status open
# Show in-progress work
bd list --status in_progress
```
### Assignment
```bash
# Assign issue to yourself
bd update beads-123 --assignee username
# Create assigned issue
bd create "Review PR" --assignee reviewer
```
### Bulk Operations
```bash
# Close multiple issues at once
bd close beads-123 beads-456 beads-789
# Close with reason
bd close beads-123 --reason "Completed in v1.2.0"
```
### Hooks
```bash
# Install git hooks for automatic sync
bd hooks install
# Remove hooks
bd hooks uninstall
```
## Configuration
### Environment Variables
- `BEADS_DATA_DIR`: Custom directory for beads data (default: `.beads/`)
- `BEADS_CONFIG`: Custom configuration file path
- `BEADS_EDITOR`: Default editor for editing issues
### Git Integration
beads integrates with git for version-controlled issue tracking:
- Automatic sync before commits (via hooks)
- Issue references in commit messages
- Branch name tracking
- Git-aware issue states
## Workflow Integration
### Typical Development Workflow
1. **Start session**: `bd prime` or check `bd ready`
2. **Claim work**: `bd update beads-123 --status in_progress`
3. **Work on task**: Implement changes
4. **Discover new work**: `bd create "Discovered subtask"` as needed
5. **Complete task**: `bd close beads-123`
6. **Sync**: `bd sync` (automatic via hooks)
### Team Collaboration
```bash
# Create issue and assign
bd create "Implement feature X" --assignee dev1
# Review assigned work
bd list --assignee yourname
# Close with review notes
bd close beads-123 --reason "Reviewed and approved"
```
## Shell Completions
beads provides shell completions for bash, fish, and zsh:
```bash
# Bash completions are auto-loaded
source <(bd completion bash)
# Fish completions
bd completion fish | source
# Zsh completions
bd completion zsh > ~/.zfunc/_bd
```
## Build Information
- **Version**: 0.47.1
- **Language**: Go
- **License**: MIT
- **Source**: [GitHub](https://github.com/steveyegge/beads)
## Platform Support
- Linux
- macOS
## Notes
- Tests are disabled in the Nix package due to git worktree operations that fail in the sandbox
- Security tests on Darwin are skipped due to `/etc/passwd` unavailability in sandbox
- Shell completions are installed for platforms that can execute the build target
## Related
- [Adding Packages](../guides/adding-packages.md) - How to add new packages
- [Quick Start](../QUICKSTART.md) - Getting started guide
+206
View File
@@ -0,0 +1,206 @@
# code2prompt
A CLI tool that converts your codebase into a single LLM prompt with a source tree, prompt templating, and token counting.
## Description
code2prompt is a command-line tool designed to help developers prepare their codebases for analysis by Large Language Models (LLMs). It creates a comprehensive prompt that includes:
- Source code tree structure
- Concatenated file contents
- Prompt templates
- Token counting for context management
## Features
- 📁 **Source Tree Generation**: Visual representation of your codebase structure
- 📝 **Code Concatenation**: Merges multiple files into a single prompt
- 🧩 **Prompt Templates**: Customizable prompt templates
- 🔢 **Token Counting**: Accurate token counting for various LLMs
- 🎯 **Selective Inclusion**: Choose specific files and directories
- 🔒 **Smart Filtering**: Exclude files by pattern (.git, node_modules, etc.)
## Installation
### Via Overlay
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
code2prompt
];
}
```
### Direct Reference
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
inputs.m3ta-nixpkgs.packages.${pkgs.system}.code2prompt
];
}
```
### Run Directly
```bash
nix run git+https://code.m3ta.dev/m3tam3re/nixpkgs#code2prompt
```
## Usage
### Basic Usage
```bash
# Generate prompt for current directory
code2prompt
# Generate for specific directory
code2prompt /path/to/project
# Output to file
code2prompt -o prompt.txt
# Use custom template
code2prompt --template my_template.md
```
### Common Options
```bash
# Include specific files
code2prompt --include "*.py" "*.js"
# Exclude specific files
code2prompt --exclude "*.test.*" "node_modules/*"
# Generate source tree only
code2prompt --tree-only
# Add custom context
code2prompt --context "This is a Node.js project"
```
### Examples
#### Prepare Codebase for GPT-4
```bash
code2prompt \
--template gpt4-template.md \
--include "*.ts" "*.tsx" \
--exclude "node_modules" "*.test.ts" \
--context "Review this TypeScript codebase" \
-o codebase_prompt.txt
# Then feed to GPT-4
cat codebase_prompt.txt
```
#### Analyze Specific Directory
```bash
# Analyze only src directory
code2prompt src/ \
--include "*.rs" \
--context "Analyze this Rust codebase" \
-o src_analysis.txt
```
#### Create Source Tree
```bash
# Generate only source tree
code2prompt --tree-only > tree.txt
cat tree.txt
```
## Use Cases
### Code Review
Prepare code for AI-assisted code review:
```bash
code2prompt \
--template code-review.md \
--include "*.py" \
--context "Review this Python code for security issues" \
-o review_prompt.txt
```
### Documentation Generation
Generate documentation using LLMs:
```bash
code2prompt \
--template docs-template.md \
--include "*.js" "*.md" \
--context "Generate API documentation" \
-o docs_prompt.txt
```
### Code Migration
Prepare code for migration assistance:
```bash
code2prompt \
--template migration-template.md \
--include "*.js" \
--context "Migrate this JavaScript to TypeScript" \
-o migration_prompt.txt
```
## Configuration
### Environment Variables
- `CODE2PROMPT_TEMPLATE_DIR`: Directory containing custom templates
- `CODE2PROMPT_DEFAULT_TEMPLATE`: Default template to use
### Template Files
Custom templates can include:
```markdown
# Codebase Analysis
## Context
{context}
## Directory Tree
{tree}
## Code
{code}
## Instructions
{instructions}
```
## Build Information
- **Version**: 4.0.2
- **Language**: Rust
- **License**: MIT
- **Source**: [GitHub](https://github.com/mufeedvh/code2prompt)
## Dependencies
- `openssl` - Secure communication
- `pkg-config` - Build configuration
## Platform Support
- Linux (primary)
- macOS (may work)
- Windows (not tested)
## Related
- [Adding Packages](../guides/adding-packages.md) - How to add new packages
- [Quick Start](../QUICKSTART.md) - Getting started guide
+190
View File
@@ -0,0 +1,190 @@
# hyprpaper-random
Minimal random wallpaper setter for Hyprpaper.
## Description
hyprpaper-random is a shell script that randomly selects and applies a wallpaper from a configured directory for use with Hyprpaper on Hyprland. It's designed to be minimal and fast.
## Features
- 🎲 **Random Selection**: Picks a random wallpaper from directory
- 🖼️ **Multi-Monitor Support**: Applies wallpaper to all monitors
- 📁 **Flexible Directory**: Configurable via environment variable
- 🔍 **Format Support**: jpg, jpeg, png, webp, avif
-**Fast**: Uses `fd` for quick file searching
- 🔄 **Safe**: Null-safe handling and error checking
## Installation
### Via Overlay
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
hyprpaper-random
];
}
```
### Direct Reference
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
inputs.m3ta-nixpkgs.packages.${pkgs.system}.hyprpaper-random
];
}
```
### Run Directly
```bash
nix run git+https://code.m3ta.dev/m3tam3re/nixpkgs#hyprpaper-random
```
## Usage
### Basic Usage
```bash
# Use default directory ($XDG_CONFIG_HOME/hypr/wallpapers or ~/.config/hypr/wallpapers)
hyprpaper-random
# Use custom directory
WALLPAPER_DIR=~/Pictures/wallpapers hyprpaper-random
# Or set directory permanently
export WALLPAPER_DIR=~/Pictures/wallpapers
hyprpaper-random
```
### With Hyprpaper
Make sure Hyprpaper is running and loaded:
```bash
# Start Hyprpaper
hyprpaper &
# Set random wallpaper
hyprpaper-random
```
### Automate with Keybinding
Add to Hyprland config:
```nix
{pkgs, ...}: {
wayland.windowManager.hyprland.settings = {
bindm = [
"SUPER, mouse, movewindow"
];
bind = [
# Set random wallpaper on SUPER + W
"SUPER, W, exec, ${pkgs.hyprpaper-random}/bin/hyprpaper-random"
];
};
}
```
### Automate with Cron
```bash
# Change wallpaper every hour
0 * * * * hyprpaper-random
```
## Configuration
### Directory Setup
Default wallpaper directory:
```
$XDG_CONFIG_HOME/hypr/wallpapers/
# or
~/.config/hypr/wallpapers/
```
Custom directory:
```bash
# Temporary
WALLPAPER_DIR=~/Pictures/my-wallpapers hyprpaper-random
# Permanent (add to shell config)
export WALLPAPER_DIR=~/Pictures/my-wallpapers
```
### Environment Variables
- `WALLPAPER_DIR`: Path to wallpaper directory (default: `$XDG_CONFIG_HOME/hypr/wallpapers`)
- `XDG_CONFIG_HOME`: Config directory base (default: `~/.config`)
## Requirements
- `hyprland`: Hyprland window manager (for `hyprctl`)
- `hyprpaper`: Wallpaper utility for Hyprland
- `fd`: Fast file search
- `coreutils`: For `shuf` command
- `gawk`: Text processing
## Platform Support
- Linux (primary, requires Hyprland)
- macOS (not supported)
- Windows (not supported)
## Build Information
- **Version**: 0.1.1
- **Type**: Shell script
- **License**: MIT
## Troubleshooting
### No Wallpapers Found
Error: `No wallpapers found in: /path/to/dir`
**Solution**: Ensure wallpaper directory exists and contains images:
```bash
ls -la $WALLPAPER_DIR # Check directory exists
ls -la $WALLPAPER_DIR/*.jpg # Check for images
```
### Hyprctl Not Found
Error: `hyprctl: command not found`
**Solution**: Ensure Hyprland is installed:
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
hyprland
hyprpaper
];
}
```
### Wallpaper Not Changing
**Solution**: Check if Hyprpaper is running:
```bash
# Check status
hyprctl hyprpaper listloaded
# Check for errors
journalctl -u hyprpaper -f
```
## Related
- [Adding Packages](../guides/adding-packages.md) - How to add new packages
- [Quick Start](../QUICKSTART.md) - Getting started guide
+180
View File
@@ -0,0 +1,180 @@
# launch-webapp
Launches a web app using your default browser in app mode.
## Description
launch-webapp is a shell script that launches web applications (like Discord, Spotify Web, etc.) in your default browser's "app mode". This provides a more native-like experience for web apps.
## Features
- 🌐 **Auto-Detection**: Detects your default web browser
- 🚀 **App Mode**: Launches in dedicated app window (no address bar)
- 🎨 **Native Feel**: Removes browser chrome for app-like experience
- 🔄 **Session Management**: Keeps web apps separate from regular browsing
- 🖥️ **Wayland Support**: Works with Wayland session managers (via `uwsm`)
## Installation
### Via Overlay
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
launch-webapp
];
}
```
### Direct Reference
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
inputs.m3ta-nixpkgs.packages.${pkgs.system}.launch-webapp
];
}
```
### Run Directly
```bash
nix run git+https://code.m3ta.dev/m3tam3re/nixpkgs#launch-webapp
```
## Usage
### Basic Usage
```bash
# Launch web app
launch-webapp https://web.telegram.org
# Launch with additional arguments
launch-webapp https://web.whatsapp.com --app-name="WhatsApp"
```
### Examples
#### Launch Discord Web
```bash
launch-webapp https://discord.com/app
```
#### Launch Spotify Web
```bash
launch-webapp https://open.spotify.com
```
#### Launch Google Chat
```bash
launch-webapp https://chat.google.com
```
## Configuration
### Supported Browsers
The script auto-detects and supports:
- Google Chrome
- Brave Browser
- Microsoft Edge
- Opera
- Vivaldi
- Chromium (fallback)
### Default Browser
The script uses `xdg-settings` to detect your default browser.
```bash
# Check your default browser
xdg-settings get default-web-browser
```
### Wayland Support
The script uses `uwsm` (Wayland Session Manager) for proper Wayland support. Ensure `uwsm` is installed and configured.
## Desktop Integration
### Create Desktop Entry
Create `~/.local/share/applications/webapp-discord.desktop`:
```ini
[Desktop Entry]
Name=Discord Web
Comment=Discord Web App
Exec=launch-webapp https://discord.com/app
Icon=discord
Type=Application
Categories=Network;InstantMessaging;
```
### Add to Menu
The desktop entry will appear in your application menu after creating it.
## Requirements
- `xdg-utils`: For default browser detection
- `uwsm`: Wayland session manager
- Your preferred browser (Chrome, Brave, etc.)
## Platform Support
- Linux (primary, requires Wayland)
- macOS (not tested)
- Windows (not supported)
## Build Information
- **Version**: 0.1.0
- **Type**: Shell script
- **License**: MIT
## Troubleshooting
### Browser Not Found
If the script doesn't find your browser, ensure it's installed:
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
google-chrome
# or brave-browser, microsoft-edge, etc.
];
}
```
### Wayland Issues
If you encounter Wayland issues:
```bash
# Check uwsm is installed
which uwsm
# Check Wayland session
echo $XDG_SESSION_TYPE # Should be "wayland"
```
### App Won't Launch
Check the browser supports app mode:
```bash
# Test manually
google-chrome --app=https://example.com
```
## Related
- [Adding Packages](../guides/adding-packages.md) - How to add new packages
- [Quick Start](../QUICKSTART.md) - Getting started guide
+268
View File
@@ -0,0 +1,268 @@
# mem0
Long-term memory layer for AI agents with REST API support.
## Description
Mem0 provides a sophisticated memory management system for AI applications and agents. It enables AI assistants to maintain persistent memory across conversations and sessions using vector storage.
## Features
- 💾 **Long-term Memory**: Persistent memory across conversations
- 🔍 **Semantic Search**: Vector-based similarity search
- 🤖 **Multiple LLM Support**: OpenAI, Anthropic, Groq, Ollama, etc.
- 📊 **Vector Stores**: Qdrant, Chroma, Pinecone, pgvector, etc.
- 🌐 **REST API**: Easy integration via HTTP endpoints
- 🎯 **Multi-modal Support**: Text and image memories
- 🔧 **Configurable**: Flexible LLM and embedding models
## Installation
### Via Overlay
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
mem0
];
}
```
### Direct Reference
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
inputs.m3ta-nixpkgs.packages.${pkgs.system}.mem0
];
}
```
### Run Directly
```bash
nix run git+https://code.m3ta.dev/m3tam3re/nixpkgs#mem0
```
## Usage
### Command Line
```bash
# Start mem0 server
mem0-server
# With custom port
MEM0_PORT=8080 mem0-server
# With LLM provider
MEM0_LLM_PROVIDER=openai OPENAI_API_KEY=sk-xxx mem0-server
```
### Python Library
```python
from mem0 import Memory
# Initialize with OpenAI
memory = Memory(
llm_provider="openai",
llm_model="gpt-4o-mini",
vector_store="qdrant",
openai_api_key="sk-xxx"
)
# Add a memory
result = memory.add(
"I prefer coffee over tea",
metadata={"user_id": "123"}
)
# Search memories
memories = memory.search("What does the user prefer?")
```
### REST API
```bash
# Start server
mem0-server
# Add memory
curl -X POST http://localhost:8000/v1/memories \
-H "Content-Type: application/json" \
-d '{"content": "User likes Python"}'
# Search memories
curl http://localhost:8000/v1/memories/search?q=Python
```
## Configuration
### Environment Variables
```bash
# LLM Configuration
export MEM0_LLM_PROVIDER=openai
export MEM0_LLM_MODEL=gpt-4o-mini
export MEM0_LLM_TEMPERATURE=0.7
export OPENAI_API_KEY=sk-xxx
# Vector Store
export MEM0_VECTOR_PROVIDER=qdrant
export QDRANT_HOST=localhost
export QDRANT_PORT=6333
# Server
export MEM0_HOST=0.0.0.0
export MEM0_PORT=8000
export MEM0_WORKERS=4
export MEM0_LOG_LEVEL=info
```
### NixOS Module (Recommended)
Use the NixOS module for production:
```nix
{config, ...}: {
imports = [m3ta-nixpkgs.nixosModules.mem0];
m3ta.mem0 = {
enable = true;
port = 8000;
llm = {
provider = "openai";
apiKeyFile = "/run/secrets/openai-api-key";
model = "gpt-4o-mini";
};
vectorStore = {
provider = "qdrant";
config = {
host = "localhost";
port = 6333;
};
};
};
}
```
See [mem0 Module](../modules/nixos/mem0.md) for full module documentation.
## Supported LLM Providers
| Provider | Model Examples | Notes |
|----------|---------------|-------|
| `openai` | gpt-4, gpt-3.5-turbo | Most tested |
| `anthropic` | claude-3-opus, claude-3-sonnet | Requires key |
| `groq` | mixtral-8x7b-32768 | Fast inference |
| `ollama` | llama2, mistral | Local only |
| `together` | llama-2-70b | API access |
## Supported Vector Stores
| Provider | Requirements | Notes |
|----------|--------------|-------|
| `qdrant` | qdrant server | Recommended |
| `chroma` | chroma server | Simple setup |
| `pgvector` | PostgreSQL + pgvector | SQL-based |
| `pinecone` | Pinecone API | Cloud only |
| `redis` | Redis stack | Fast |
| `elasticsearch` | ES cluster | Scalable |
## Use Cases
### AI Chatbot with Memory
```python
from mem0 import Memory
memory = Memory()
# During conversation
memory.add("User works at Google as a software engineer")
# Later conversations
memories = memory.search("Where does the user work?")
# Returns: ["User works at Google as a software engineer"]
```
### Personal Assistant
```python
memory = Memory()
# Store preferences
memory.add("User prefers dark mode", metadata={"category": "preferences"})
memory.add("User is vegetarian", metadata={"category": "diet"})
# Retrieve relevant info
memories = memory.search("What should I cook for the user?")
```
### Code Assistant
```python
memory = Memory()
# Store project context
memory.add("This is a NixOS project with custom packages")
# Later analysis
memories = memory.search("What kind of project is this?")
```
## Requirements
### Vector Store
You need a vector store running. Example with Qdrant:
```nix
services.qdrant = {
enable = true;
port = 6333;
};
```
### LLM Provider
You need API keys or local models:
```nix
# OpenAI
services.mem0.llm.apiKeyFile = "/run/secrets/openai-api-key";
# Or use agenix
age.secrets.openai-api-key.file = ./secrets/openai.age;
```
## Build Information
- **Version**: 1.0.0
- **Language**: Python
- **License**: Apache-2.0
- **Source**: [GitHub](https://github.com/mem0ai/mem0)
## Python Dependencies
- `litellm` - Multi-LLM support
- `qdrant-client` - Qdrant client
- `pydantic` - Data validation
- `openai` - OpenAI client
- `fastapi` - REST API
- `uvicorn` - ASGI server
- `sqlalchemy` - Database ORM
## Platform Support
- Linux (primary)
- macOS (may work)
- Windows (not tested)
## Related
- [mem0 Module](../modules/nixos/mem0.md) - NixOS module documentation
- [Adding Packages](../guides/adding-packages.md) - How to add new packages
- [Port Management](../guides/port-management.md) - Managing service ports
- [Quick Start](../QUICKSTART.md) - Getting started guide
+172
View File
@@ -0,0 +1,172 @@
# msty-studio
Msty Studio enables advanced, privacypreserving AI workflows entirely on your local machine.
## Description
Msty Studio is a desktop application that provides a powerful AI development environment with a focus on privacy. All AI processing happens locally on your machine, ensuring your data never leaves your system.
## Features
- 🔒 **Privacy-First**: All AI processing happens locally
- 🤖 **Local AI Models**: Support for running local LLMs
- 📝 **Code Editor**: Integrated development environment
- 🔄 **Multiple Models**: Switch between different AI models
- 📊 **Model Management**: Download and manage local models
- 🎨 **Modern UI**: Clean, intuitive interface
-**Fast Performance**: Optimized for speed
## Installation
### Via Overlay
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
msty-studio
];
}
```
### Direct Reference
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
inputs.m3ta-nixpkgs.packages.${pkgs.system}.msty-studio
];
}
```
### Run Directly
```bash
nix run git+https://code.m3ta.dev/m3tam3re/nixpkgs#msty-studio
```
## Usage
### Launch Application
```bash
# Launch Msty Studio
msty-studio
# Or from application menu
# Applications -> Msty Studio
```
### First Run
On first launch, you'll need to:
1. Download an AI model (if not already downloaded)
2. Configure model settings
3. Set up your workspace
### Managing Models
Through the Msty Studio interface, you can:
- Download new models
- Remove unused models
- Switch between models
- Configure model parameters
## Configuration
### Model Directory
Models are stored in your home directory:
```
~/.local/share/msty-studio/models/
```
### Settings
Msty Studio stores settings in:
```
~/.config/msty-studio/
```
### Integration with Nix
The package includes required dependencies:
- Node.js (for runtime)
- npm (for package management)
- uv (for Python packages)
- Python (for AI models)
## Requirements
### System Requirements
- Linux (x86_64)
- 8GB RAM minimum (16GB+ recommended)
- Modern CPU with AVX2 support
- GPU recommended (for faster inference)
### Dependencies
The package includes these dependencies:
- `nodejs` - JavaScript runtime
- `nodePackages.npm` - Package manager
- `uv` - Python package installer
- `python3` - Python runtime
## Platform Support
- Linux (x86_64 only)
- macOS (not supported)
- Windows (not supported)
**Note**: Msty Studio is distributed as an AppImage for Linux.
## Build Information
- **Version**: 2.0.0-beta.4
- **Type**: AppImage
- **License**: Proprietary (Unfree)
- **Source**: [msty.studio](https://msty.studio)
## Troubleshooting
### AppImage Won't Launch
Ensure executable bit is set:
```bash
chmod +x ~/.local/share/applications/msty-studio.desktop
```
### Models Not Downloading
Check disk space and network:
```bash
# Check disk space
df -h
# Check network
ping google.com
```
### Performance Issues
- Ensure you're using a GPU-accelerated model
- Close other resource-intensive applications
- Check system resources:
```bash
htop
nvidia-smi # If using NVIDIA GPU
```
## Related
- [Adding Packages](../guides/adding-packages.md) - How to add new packages
- [Quick Start](../QUICKSTART.md) - Getting started guide
+310
View File
@@ -0,0 +1,310 @@
# n8n
Free and source-available fair-code licensed workflow automation tool. Easily automate tasks across different services.
## Description
n8n (pronounced "n-eight-n") is a workflow automation tool that helps you connect different services and automate tasks without writing code. It features a visual node-based editor for creating workflows with hundreds of integrations.
## Features
- 🎨 **Visual Workflow Editor**: Drag-and-drop interface for creating workflows
- 🔗 **Hundreds of Integrations**: Connect to popular services (Slack, GitHub, Google, etc.)
- 🔄 **Webhook Support**: Trigger workflows via HTTP requests
- 📝 **Code Node**: Execute JavaScript/TypeScript code within workflows
- 🚀 **Cloud & Self-Hosted**: Use n8n Cloud or self-host on your own infrastructure
- 📊 **Data Transformation**: Map and transform data between services
-**Scheduling**: Run workflows on schedules (cron-like)
- 🔒 **Security**: Credential management and secure data handling
- 🎯 **Fair-Code License**: Source available with usage restrictions for commercial use
## Installation
### Via Overlay
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
n8n
];
}
```
### Direct Reference
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
inputs.m3ta-nixpkgs.packages.${pkgs.system}.n8n
];
}
```
### Run Directly
```bash
nix run git+https://code.m3ta.dev/m3tam3re/nixpkgs#n8n
```
## Usage
### Basic Usage
```bash
# Start n8n (default configuration)
n8n start
# Start with custom configuration file
n8n start --config /path/to/config
# Run in worker mode (for production with queue)
n8n worker
# Execute a workflow from file
n8n execute /path/to/workflow.json
```
### Development Mode
```bash
# Start with tunnel (external access)
n8n start --tunnel
# Disable telemetry
n8n start --no-telemetry
# Specify workflow directory
n8n start --workflows /path/to/workflows
# Enable/disable features
n8n start --enable-editor
n8n start --disable-metrics
```
### Workflow Management
```bash
# Export workflow to file
n8n export:workflow --id=123 --output=workflow.json
# Import workflow from file
n8n import:workflow --input=workflow.json
# Execute workflow
n8n execute:workflow --id=123
```
## Configuration
### Environment Variables
- `N8N_BASIC_AUTH_ACTIVE`: Enable basic authentication (default: false)
- `N8N_BASIC_AUTH_USER`: Basic auth username
- `N8N_BASIC_AUTH_PASSWORD`: Basic auth password
- `N8N_ENCRYPTION_KEY`: Encryption key for credentials
- `N8N_HOST`: Host URL for web UI (default: localhost)
- `N8N_PORT`: Port for web UI (default: 5678)
- `N8N_PROTOCOL`: Protocol (http or https)
- `N8N_PATH`: Path to mount n8n (default: /)
- `N8N_EDITOR_BASE_URL`: Base URL for editor
- `N8N_WEBHOOK_URL`: URL for webhook endpoints
- `N8N_TIMEZONE`: Timezone for execution (default: UTC)
- `N8N_LOG_LEVEL`: Logging level (output, warn, error, verbose)
- `N8N_LOG_OUTPUT`: Log output destination (console, file)
- `N8N_METRICS`: Enable metrics collection (default: true)
- `DB_TYPE`: Database type (sqlite3db, postgresdb, mysqldb)
- `DB_SQLITE_VACUUM_ON_STARTUP`: Vacuum SQLite on startup
### Database Configuration
By default, n8n uses SQLite for simplicity. For production, use PostgreSQL or MySQL:
```bash
# PostgreSQL
export DB_TYPE=postgresdb
export DB_POSTGRESDB_HOST=localhost
export DB_POSTGRESDB_PORT=5432
export DB_POSTGRESDB_DATABASE=n8n
export DB_POSTGRESDB_USER=n8n
export DB_POSTGRESDB_PASSWORD=yourpassword
# MySQL/MariaDB
export DB_TYPE=mysqldb
export DB_MYSQLDB_HOST=localhost
export DB_MYSQLDB_PORT=3306
export DB_MYSQLDB_DATABASE=n8n
export DB_MYSQLDB_USER=n8n
export DB_MYSQLDB_PASSWORD=yourpassword
```
### Security
Set up encryption for credentials:
```bash
# Generate encryption key
export N8N_ENCRYPTION_KEY=$(openssl rand -base64 32)
# Use in production
export N8N_ENCRYPTION_KEY="your-32-char-encryption-key"
```
## NixOS Module
For NixOS, use the n8n module from nixpkgs for a complete service configuration:
```nix
services.n8n = {
enable = true;
settings = {
host = "0.0.0.0";
port = 5678;
timezone = "UTC";
};
environment = {
N8N_ENCRYPTION_KEY = "your-encryption-key";
DB_TYPE = "postgresdb";
DB_POSTGRESDB_HOST = "/var/run/postgresql";
DB_POSTGRESDB_DATABASE = "n8n";
};
};
```
## Use Cases
### Webhook Automation
Trigger workflows via HTTP requests:
```bash
# Start n8n with tunnel for public URL
n8n start --tunnel
# Create webhook workflow in UI
# Workflow receives data from external service
# Process and send to another service
```
### Scheduled Tasks
Run tasks on a schedule:
```javascript
// In workflow editor, use Schedule Trigger
// Set cron expression: "0 9 * * *" (daily at 9 AM)
// Connect to nodes that perform tasks
```
### Data Sync Between Services
Keep data synchronized:
```bash
# Create workflow with:
# 1. Webhook trigger (service A)
# 2. Data transformation node
# 3. HTTP request node (service B)
# 4. Response back to service A
```
### Automated Reporting
Generate and send reports:
```javascript
// Workflow steps:
// 1. Schedule trigger (daily/weekly)
// 2. Database query node
// 3. Data formatting
// 4. Email or Slack notification
```
## Integration Examples
### Slack Integration
```javascript
// Create Slack notification workflow
// 1. Trigger (webhook or schedule)
// 2. Process data
// 3. Send message to Slack channel
```
### GitHub Integration
```javascript
// GitHub repository automation
// 1. GitHub webhook trigger (push, PR, issue)
// 2. Conditional logic
// 3. Actions (create issue, comment, etc.)
```
### Email Automation
```javascript
// Email processing workflow
// 1. Email trigger (IMAP)
// 2. Parse email content
// 3. Process data
// 4. Send response or forward
```
## Performance Optimization
### Production Tips
- Use PostgreSQL or MySQL instead of SQLite
- Enable queue mode with Redis
- Use worker nodes for scaling
- Configure proper resource limits
- Set up load balancing for web UI
### Queue Mode
```bash
# Start main n8n process
export QUEUE_BULL_REDIS_HOST=redis-server
export QUEUE_BULL_REDIS_PORT=6379
n8n start
# Start worker processes
n8n worker
```
## Build Information
- **Version**: 2.4.1
- **Language**: TypeScript/JavaScript (Node.js)
- **Package Manager**: pnpm
- **License**: Sustainable Use (Fair-Code)
- **Source**: [GitHub](https://github.com/n8n-io/n8n)
## Dependencies
- `nodejs` - JavaScript runtime
- `pnpm` - Package manager (build-time)
- `python3` - Required for SQLite bindings
- `node-gyp` - Node.js native addon build tool
- `libkrb5` - Kerberos authentication
- `libmongocrypt` - MongoDB encryption
- `libpq` - PostgreSQL client library
## Platform Support
- Linux
- macOS
## Notes
- Package has ~80,000 files, so stripping and ELF patching are disabled for performance
- SQLite3 bindings are rebuilt during build phase
- TypeScript files and source maps are removed in preInstall phase
- Non-deterministic files (.turbo, .modules.yaml, types) are removed
- Node modules are pruned to production dependencies only
## Related
- [Adding Packages](../guides/adding-packages.md) - How to add new packages
- [Quick Start](../QUICKSTART.md) - Getting started guide
- [n8n Documentation](https://docs.n8n.io) - Official documentation
- [n8n Community](https://community.n8n.io) - Community forum
+117
View File
@@ -0,0 +1,117 @@
# notesmd-cli
Obsidian CLI (Community) - Interact with Obsidian in the terminal.
## Description
notesmd-cli is a command-line interface for interacting with Obsidian, the popular knowledge management and note-taking application. It allows you to create, search, and manipulate notes directly from the terminal.
## Features
- 📝 **Note Creation**: Create new notes from the command line
- 🔍 **Search**: Search through your Obsidian vault
- 📂 **Vault Management**: Interact with your vault structure
- 🔗 **WikiLink Support**: Work with Obsidian's WikiLink format
- 🏷️ **Tag Support**: Manage and search by tags
-**Fast**: Lightweight Go binary with no external dependencies
## Installation
### Via Overlay
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
notesmd-cli
];
}
```
### Direct Reference
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
inputs.m3ta-nixpkgs.packages.${pkgs.system}.notesmd-cli
];
}
```
### Run Directly
```bash
nix run git+https://code.m3ta.dev/m3tam3re/nixpkgs#notesmd-cli
```
## Usage
### Basic Commands
```bash
# Show help
notesmd-cli --help
# Create a new note
notesmd-cli new "My Note Title"
# Search notes
notesmd-cli search "search term"
# List notes
notesmd-cli list
```
### Working with Vaults
```bash
# Specify vault path
notesmd-cli --vault /path/to/vault new "Note Title"
# Open a note in Obsidian
notesmd-cli open "Note Name"
```
### Advanced Usage
```bash
# Search with tags
notesmd-cli search --tag "project"
# Append to existing note
notesmd-cli append "Note Name" "Additional content"
```
## Configuration
### Environment Variables
- `OBSIDIAN_VAULT`: Default vault path
### Command Line Options
Run `notesmd-cli --help` for a complete list of options.
## Build Information
- **Version**: 0.3.0
- **Language**: Go
- **License**: MIT
- **Source**: [GitHub](https://github.com/Yakitrak/notesmd-cli)
- **Vendor Hash**: null (no external dependencies)
## Platform Support
- Linux
- macOS (Unix systems)
## Notes
- No vendor dependencies (pure Go stdlib)
- The binary is named `notesmd-cli` (not `notesmd`)
- This is the community CLI, not the official Obsidian CLI
## Related
- [Obsidian](https://obsidian.md) - The Obsidian application
- [Adding Packages](../guides/adding-packages.md) - How to add new packages
- [Quick Start](../QUICKSTART.md) - Getting started guide
+346
View File
@@ -0,0 +1,346 @@
# opencode
AI coding agent built for the terminal that can build anything. Combines a TypeScript/JavaScript core with a Go-based TUI for an interactive AI coding experience.
## Description
OpenCode is a terminal-based AI coding agent designed for power users. It provides a comprehensive development environment with AI assistance, code generation, refactoring, and project management capabilities. The tool features a sophisticated TUI (Terminal User Interface) built with Go, while the core functionality is implemented in TypeScript/JavaScript.
## Features
- 🤖 **AI-Powered Coding**: Generate, refactor, and optimize code with AI assistance
- 🖥️ **Modern TUI**: Beautiful terminal interface built with Go
- 🔍 **Code Understanding**: Parse and understand existing codebases
- 🌳 **Tree-Sitter Integration**: Accurate syntax highlighting and code structure analysis
- 📁 **Project Management**: Navigate and manage projects efficiently
- 🧠 **Multi-LLM Support**: Works with various language models (OpenAI, Anthropic, etc.)
- 📝 **Code Generation**: Create new files and features from natural language
- 🔄 **Refactoring**: Intelligent code refactoring with AI
- 🐛 **Bug Detection**: Find and fix bugs automatically
- 📚 **Context Awareness**: Maintains context across editing sessions
- 🎯 **Task Orchestration**: Break down and execute complex tasks
- 💾 **Local Development**: Runs entirely on your machine
## Installation
### Via Overlay
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
opencode
];
}
```
### Direct Reference
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
inputs.m3ta-nixpkgs.packages.${pkgs.system}.opencode
];
}
```
### Run Directly
```bash
nix run git+https://code.m3ta.dev/m3tam3re/nixpkgs#opencode
```
## Usage
### Basic Usage
```bash
# Start OpenCode in current directory
opencode
# Open specific project
opencode /path/to/project
# Start with specific task description
opencode "Fix the login bug"
# Show help
opencode --help
# Show version
opencode --version
```
### Interactive Commands
OpenCode provides an interactive TUI with various commands:
- **Navigation**: Arrow keys to move, Enter to select
- **Search**: `/` to search files, `?` for help
- **Edit**: `e` to edit selected file
- **Command Palette**: `Ctrl+p` to access commands
- **AI Chat**: `Ctrl+c` to open AI chat
- **Exit**: `q` or `Ctrl+d` to quit
### AI Chat Mode
```bash
# Start OpenCode
opencode
# Enter AI chat mode (Ctrl+c)
# Ask questions, request code changes, etc.
# Examples:
# - "Generate a REST API endpoint for user management"
# - "Refactor this function to use async/await"
# - "Find and fix potential memory leaks"
# - "Add unit tests for this module"
```
### Task Management
```bash
# Ask OpenCode to work on a specific task
opencode "Implement authentication with JWT tokens"
# The agent will:
# 1. Understand the codebase
# 2. Plan the implementation
# 3. Generate necessary code
# 4. Make the changes
# 5. Verify the implementation
```
## Configuration
### Environment Variables
- `OPENCODE_API_KEY`: API key for LLM provider
- `OPENCODE_MODEL`: Default model to use (e.g., gpt-4, claude-3-opus)
- `OPENCODE_PROVIDER`: LLM provider (openai, anthropic, etc.)
- `OPENCODE_MAX_TOKENS`: Maximum tokens for responses
- `OPENCODE_TEMPERATURE`: Sampling temperature (0-1)
- `OPENCODE_CONFIG`: Path to configuration file
### Configuration File
Create `~/.opencode/config.json`:
```json
{
"model": "gpt-4",
"provider": "openai",
"maxTokens": 4096,
"temperature": 0.7,
"systemPrompt": "You are a helpful coding assistant"
}
```
### Project-Specific Config
Create `.opencode.json` in your project:
```json
{
"include": ["src/**/*.ts", "tests/**/*.ts"],
"exclude": ["node_modules", "dist", "*.test.ts"],
"systemPrompt": "You are a TypeScript expert"
}
```
## Advanced Usage
### Code Refactoring
```bash
# Ask for refactoring suggestions
opencode "Review and refactor src/utils.ts for better performance"
# Apply refactoring automatically
opencode "Optimize the database queries in src/db/*.ts"
```
### Bug Fixing
```bash
# Describe the bug
opencode "Fix the race condition in the payment processing module"
# OpenCode will:
# 1. Analyze the code
# 2. Identify the issue
# 3. Propose and implement fixes
# 4. Verify the solution
```
### Feature Implementation
```bash
# Request new features
opencode "Add support for OAuth2 authentication"
# Be specific about requirements
opencode "Create a REST API with these endpoints: GET /users, POST /users, PUT /users/:id, DELETE /users/:id"
```
### Code Review
```bash
# Get code review
opencode "Review src/api/*.ts for security vulnerabilities"
# Check for best practices
opencode "Review the entire codebase and suggest improvements following SOLID principles"
```
### Documentation Generation
```bash
# Generate documentation
opencode "Add JSDoc comments to all functions in src/utils.ts"
# Create README
opencode "Generate a comprehensive README.md for this project"
```
## Integration with Editors
### VS Code
OpenCode can work alongside your editor:
```bash
# Keep VS Code running for editing
code .
# Use OpenCode for AI assistance in another terminal
opencode
# Switch between them as needed
```
### Vim/Neovim
```bash
# Use Vim/Neovim as your editor
vim src/main.ts
# Use OpenCode for complex tasks
opencode "Refactor the authentication module"
```
## Use Cases
### Learning New Codebases
```bash
# OpenCode will:
# 1. Analyze the code structure
# 2. Explain how components work
# 3. Answer questions about the code
opencode "Explain how this project handles user authentication"
```
### Porting Code
```bash
# Port from one language to another
opencode "Port this Python function to TypeScript"
```
### Writing Tests
```bash
# Generate unit tests
opencode "Add comprehensive unit tests for src/utils.ts with 100% coverage"
```
### Debugging
```bash
# Get help with debugging
opencode "I'm getting a null pointer exception in src/api/users.ts. Help me debug it"
```
## Keyboard Shortcuts
### Global
- `Ctrl+p` - Open command palette
- `Ctrl+c` - Open AI chat
- `Ctrl+s` - Save current file
- `Ctrl+q` - Quit
- `?` - Show help
### Navigation
- `j` / `k` - Down / Up
- `h` / `l` - Left / Right
- `gg` - Go to top
- `G` - Go to bottom
- `/` - Search
- `n` - Next search result
- `N` - Previous search result
### File Operations
- `e` - Edit file
- `o` - Open in external editor
- `d` - Delete file (with confirmation)
- `y` - Yank (copy)
- `p` - Paste
## Build Information
- **Version**: 1.1.18
- **Language**: TypeScript/JavaScript (core), Go (TUI)
- **Runtime**: Bun
- **License**: MIT
- **Source**: [GitHub](https://github.com/anomalyco/opencode)
## Dependencies
- `bun` - JavaScript runtime and package manager
- `fzf` - Fuzzy finder for file selection
- `ripgrep` - Fast text search
- `models-dev` - Model definitions and schemas
## Platform Support
- Linux (aarch64, x86_64)
- macOS (aarch64, x86_64)
## Notes
- Includes a patch to relax Bun version check (changed to warning instead of error)
- Shell completions are installed for supported platforms (excludes x86_64-darwin)
- Tree-sitter WASM files are patched to use absolute store paths
- JSON schema is generated and installed to `$out/share/opencode/schema.json`
## Tips and Best Practices
### Getting Started
1. **Start Small**: Begin with simple tasks to get familiar with the interface
2. **Provide Context**: Give clear, detailed descriptions of what you want
3. **Iterate**: Work with OpenCode iteratively, refining requests as needed
4. **Review Changes**: Always review AI-generated code before committing
### Effective Prompts
- Be specific about requirements
- Provide examples of expected behavior
- Mention constraints or preferences
- Break complex tasks into smaller steps
### Project Structure
- Keep your project well-organized
- Use consistent naming conventions
- Add clear comments to complex logic
- Maintain a clean git history
## Related
- [Adding Packages](../guides/adding-packages.md) - How to add new packages
- [Quick Start](../QUICKSTART.md) - Getting started guide
- [OpenCode Documentation](https://github.com/anomalyco/opencode) - Official repository and documentation
+220
View File
@@ -0,0 +1,220 @@
# pomodoro-timer
A work timer based on the Pomodoro Technique.
## Description
A simple, shell-based Pomodoro timer that uses `timer`, Kitty terminal, Rofi, libnotify, and speech synthesis to provide visual and audio feedback for work and break sessions.
## Features
- ⏱️ **Pomodoro Technique**: 45-minute work, 10-minute break cycles
- 🎨 **Terminal UI**: Floating Kitty terminal window
- 📋 **Rofi Menu**: Easy session selection
- 🔔 **Notifications**: Desktop and voice notifications
- ⚙️ **Custom Times**: Set custom durations
- 🎯 **Quick Access**: Simple keybinding integration
## Installation
### Via Overlay
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
launch-timer # The main program is named launch-timer
];
}
```
### Direct Reference
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
inputs.m3ta-nixpkgs.packages.${pkgs.system}.launch-timer
];
}
```
### Run Directly
```bash
nix run git+https://code.m3ta.dev/m3tam3re/nixpkgs#launch-timer
```
## Usage
### Basic Usage
```bash
# Launch timer selection menu
launch-timer
```
This opens a Rofi menu with three options:
1. **work** - 45-minute work session
2. **break** - 10-minute break session
3. **custom** - Custom time duration
### Session Options
#### Work Session
```bash
# Select "work" from menu
# Starts 45-minute timer
```
#### Break Session
```bash
# Select "break" from menu
# Starts 10-minute timer
```
#### Custom Time
```bash
# Select "custom" from menu
# Enter time in format: 25m, 1h, 30s
# Examples:
# 25m - 25 minutes
# 1h - 1 hour
# 30s - 30 seconds
```
### Time Formats
Supported formats:
| Format | Example | Description |
|---------|----------|-------------|
| `Xm` | `25m` | X minutes |
| `Xh` | `1h` | X hours |
| `Xs` | `30s` | X seconds |
## Configuration
### Keybinding Integration
Add to Hyprland config:
```nix
{pkgs, ...}: {
wayland.windowManager.hyprland.settings = {
bind = [
# Launch Pomodoro timer with SUPER + T
"SUPER, T, exec, ${pkgs.launch-timer}/bin/launch-timer"
];
};
}
```
### Custom Defaults
Modify the script for custom defaults:
```bash
# Change work duration
start_timer "60m" "work"
# Change break duration
start_timer "15m" "break"
```
## Requirements
### Dependencies
- `timer` - Terminal timer utility
- `kitty` - Terminal emulator
- `rofi` - Application launcher
- `libnotify` - Desktop notifications
- `speechd` - Text-to-speech synthesis
### System Requirements
- Linux (primary)
- Desktop environment with notification support
- Audio output for speech synthesis
## Platform Support
- Linux (primary)
- macOS (not supported)
- Windows (not supported)
## Behavior
### Timer Window
- Opens as floating Kitty window
- Window class: `floating-pomodoro`
- Window title: `floating-pomodoro`
### Notifications
When session ends, you'll receive:
1. Desktop notification: "work session ended!" or "break session ended!"
2. Voice announcement: "work session ended" or "break session ended"
### Input Validation
For custom times:
- Valid: `25m`, `1h`, `30s`, `1h30m`
- Invalid: `25`, `abc`, `1.5h`
## Build Information
- **Version**: 0.1.0
- **Type**: Shell script
- **License**: MIT
- **Main Program**: `launch-timer`
## Troubleshooting
### Kitty Not Found
Ensure Kitty is installed:
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
kitty
];
}
```
### No Notifications
Ensure notification daemon is running:
```bash
# Check for notification daemon
ps aux | grep -i notify
# Start notification daemon
# Depends on your DE: dunst, mako, etc.
```
### Speech Not Working
Check if speech synthesis is working:
```bash
# Test speech
spd-say "Hello"
# Check if speech-dispatcher is running
ps aux | grep speech-dispatcher
```
## Related
- [Adding Packages](../guides/adding-packages.md) - How to add new packages
- [Quick Start](../QUICKSTART.md) - Getting started guide
+245
View File
@@ -0,0 +1,245 @@
# rofi-project-opener
A Rofi-based project directory launcher for quickly opening projects in your terminal with custom commands.
## Description
rofi-project-opener scans configured base directories for project subdirectories and presents them in a Rofi menu. When a project is selected, it opens a terminal, navigates to the project directory, and runs a configurable command (defaults to `opencode`).
Key features:
- JSON-based configuration for project directories
- Per-directory custom arguments (e.g., `--agent chiron` for AI coding assistants)
- Placeholder support (`%s` for path, `%a` for args) in custom commands
- Works with any terminal emulator
## Installation
### Via Overlay
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
rofi-project-opener
];
}
```
### Direct Reference
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
inputs.m3ta-nixpkgs.packages.${pkgs.system}.rofi-project-opener
];
}
```
### Run Directly
```bash
nix run git+https://code.m3ta.dev/m3tam3re/nixpkgs#rofi-project-opener
```
## Usage
### Basic Usage
```bash
# Launch rofi project selector
rofi-project-opener
```
This will:
1. Read project directories from `~/.config/rofi-project-opener/projects.json`
2. Scan each directory for subdirectories (non-hidden)
3. Display projects in Rofi for fuzzy selection
4. Open terminal, cd to project, and run the configured command
### Configuration Files
The script uses two configuration files in `~/.config/rofi-project-opener/`:
**projects.json** - Project directories with optional args:
```json
{
"nixpkgs": {"path": "~/p/NIX", "args": ""},
"chat": {"path": "~/p/CHAT", "args": "--agent chiron"},
"dev": {"path": "~/dev", "args": ""}
}
```
**config** - Terminal and Rofi settings:
```bash
TERMINAL="/path/to/kitty"
TERMINAL_CMD="opencode %a"
ROFI_PROMPT="Select project"
ROFI_ARGS="-dmenu -i"
```
### Placeholders
When using `terminalCommand`, these placeholders are available:
| Placeholder | Description |
|-------------|-------------|
| `%s` | Full path to selected project |
| `%a` | Args from projectDirs config |
**Examples:**
```nix
terminalCommand = "opencode %a"; # opencode with project args
terminalCommand = "nvim"; # just nvim, no args
terminalCommand = "code %s"; # vscode with explicit path
terminalCommand = "myapp --dir %s %a"; # custom app with both
```
## Home Manager Module
### Enable Module
```nix
{config, pkgs, ...}: {
imports = [m3ta-nixpkgs.homeManagerModules.default];
cli.rofi-project-opener = {
enable = true;
projectDirs = {
nixpkgs = { path = "~/p/NIX"; };
chat = { path = "~/p/CHAT"; args = "--agent chiron"; };
dev = { path = "~/dev"; };
};
terminal = pkgs.kitty;
terminalCommand = "opencode %a";
};
}
```
### Module Options
#### `cli.rofi-project-opener.enable`
Enable the rofi-project-opener module.
- Type: `boolean`
- Default: `false`
#### `cli.rofi-project-opener.projectDirs`
Attribute set of base directories to scan for projects.
- Type: `attrsOf (submodule { path, args })`
- Default: `{ dev = { path = "~/dev"; }; projects = { path = "~/projects"; }; }`
Each entry supports:
- `path` (required): Base directory path
- `args` (optional): Arguments to pass to the command
#### `cli.rofi-project-opener.terminal`
Terminal emulator to use.
- Type: `either str package`
- Default: `"kitty"`
#### `cli.rofi-project-opener.terminalCommand`
Command to run in the terminal. Supports `%s` (path) and `%a` (args) placeholders.
- Type: `str`
- Default: `""` (runs `opencode %a`)
#### `cli.rofi-project-opener.rofiPrompt`
Prompt text displayed in Rofi.
- Type: `str`
- Default: `"Select project"`
#### `cli.rofi-project-opener.rofiArgs`
Arguments to pass to Rofi.
- Type: `listOf str`
- Default: `["-dmenu" "-i"]`
## Requirements
### System Requirements
- Linux with Rofi installed
- A terminal emulator (kitty, alacritty, etc.)
- jq (included as dependency)
### Runtime Dependencies
These are automatically included:
- rofi
- jq
- coreutils
- gnugrep
- gnused
- libnotify
## Platform Support
- Linux (primary)
- macOS (not tested)
- Windows (not supported)
## Build Information
- **Type**: Bash script
- **License**: MIT
## Troubleshooting
### No Projects Found
Check that your project directories exist and contain subdirectories:
```bash
cat ~/.config/rofi-project-opener/projects.json
ls ~/p/NIX # Should show subdirectories
```
### Args Not Being Passed
Make sure you're using `%a` placeholder in your `terminalCommand`:
```nix
# Wrong - args not passed
terminalCommand = "opencode";
# Correct - args passed via placeholder
terminalCommand = "opencode %a";
# Also correct - empty uses default behavior with args
terminalCommand = "";
```
### Rofi Not Showing
Ensure Rofi is installed and working:
```bash
echo -e "item1\nitem2" | rofi -dmenu
```
### Terminal Not Opening
Check terminal configuration:
```nix
# Using package
terminal = pkgs.kitty;
# Using string (must be in PATH)
terminal = "kitty";
```
## Related
- [rofi-project-opener Module](../modules/home-manager/cli/rofi-project-opener.md) - Home Manager module documentation
- [zellij-ps](./zellij-ps.md) - Similar project switcher for Zellij
- [Using Modules](../guides/using-modules.md) - How to use modules
+134
View File
@@ -0,0 +1,134 @@
# sidecar
A companion tool for CLI coding agents, providing diffs, file trees, conversation history, and task management with td integration.
## Description
sidecar is a terminal UI tool designed to enhance the experience of using AI coding agents in the terminal. It provides a side panel interface for viewing diffs, file trees, conversation history, and integrates with `td` for task management across coding sessions.
## Features
- 🔀 **Diff Viewer**: Visual diff display for code changes
- 📁 **File Tree**: Navigate and understand project structure
- 💬 **Conversation History**: Review and search past AI interactions
-**Task Management**: Integrated with `td` for tracking tasks
- 🖥️ **Terminal UI**: Clean interface using tmux panes
- 🤖 **AI Agent Integration**: Designed to work with opencode and similar CLI agents
## Installation
### Via Overlay
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
sidecar
];
}
```
### Direct Reference
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
inputs.m3ta-nixpkgs.packages.${pkgs.system}.sidecar
];
}
```
### Run Directly
```bash
nix run git+https://code.m3ta.dev/m3tam3re/nixpkgs#sidecar
```
## Usage
### Starting sidecar
```bash
# Start sidecar alongside your AI coding agent
sidecar
# Start with a specific agent
sidecar --agent opencode
```
### Basic Commands
```bash
# Show help
sidecar --help
# Check version
sidecar --version
```
## Dependencies
sidecar is packaged with the following runtime dependencies:
- **opencode**: AI coding agent
- **td**: Task tracking CLI
- **tmux**: Terminal multiplexer for UI layout
These are automatically included in the PATH when running sidecar.
## Workflow Integration
### Typical Session
1. Start `sidecar` in your project directory
2. The tool opens a tmux session with panes for:
- Your AI coding agent (opencode)
- Task list (via td)
- Diff viewer
- File tree navigator
3. Work with your AI agent as usual
4. View diffs and changes in real-time
5. Track tasks using the integrated td panel
### With opencode
```bash
# sidecar automatically integrates with opencode
cd your-project
sidecar
```
## Configuration
### Environment Variables
- `SIDECAR_CONFIG`: Custom configuration file path
- `SIDECAR_AGENT`: Default AI agent to use (default: opencode)
### Customization
Configuration is managed through sidecar's own config system. See the upstream documentation for details.
## Build Information
- **Version**: 0.71.1
- **Language**: Go
- **License**: MIT
- **Source**: [GitHub](https://github.com/marcus/sidecar)
## Platform Support
- Linux
- macOS (Unix systems)
## Notes
- Tests are disabled in the Nix package build
- The package wraps the binary with required dependencies (opencode, td, tmux) in PATH
- Version check is enabled for the Nix package
## Related
- [td](./td.md) - Task tracking CLI used by sidecar
- [opencode](./opencode.md) - AI coding agent integration
- [Adding Packages](../guides/adding-packages.md) - How to add new packages
- [Quick Start](../QUICKSTART.md) - Getting started guide
+202
View File
@@ -0,0 +1,202 @@
# stt-ptt
Push to Talk Speech to Text using Whisper.
## Description
stt-ptt is a simple push-to-talk speech-to-text tool that uses whisper.cpp for transcription. It records audio via PipeWire, transcribes it using a local Whisper model, and types the result using wtype (Wayland).
## Features
- **Push to Talk**: Start/stop recording with simple commands
- **Local Processing**: Uses whisper.cpp for fast, offline transcription
- **Wayland Native**: Types transcribed text using wtype
- **Configurable**: Model path and notification timeout via environment variables
- **Lightweight**: Minimal dependencies, no cloud services
## Installation
### Via Home Manager Module (Recommended)
See [stt-ptt Home Manager Module](../modules/home-manager/cli/stt-ptt.md) for the recommended setup with automatic model download.
### Via Overlay
```nix
{pkgs, ...}: {
home.packages = [pkgs.stt-ptt];
}
```
### Direct Reference
```nix
{pkgs, ...}: {
home.packages = [
inputs.m3ta-nixpkgs.packages.${pkgs.system}.stt-ptt
];
}
```
## Usage
### Basic Commands
```bash
# Start recording
stt-ptt start
# Stop recording and transcribe
stt-ptt stop
```
### Keybinding Setup
The tool is designed to be bound to a key (e.g., hold to record, release to transcribe).
#### Hyprland
```nix
# In your Hyprland config
wayland.windowManager.hyprland.settings = {
bind = [
# Press Super+V to start, release to stop and transcribe
"SUPER, V, exec, stt-ptt start"
];
bindr = [
# Release trigger
"SUPER, V, exec, stt-ptt stop"
];
};
```
Or in `hyprland.conf`:
```conf
bind = SUPER, V, exec, stt-ptt start
bindr = SUPER, V, exec, stt-ptt stop
```
#### Sway
```conf
# Hold to record, release to transcribe
bindsym --no-repeat $mod+v exec stt-ptt start
bindsym --release $mod+v exec stt-ptt stop
```
#### i3 (X11 - requires xdotool instead of wtype)
Note: stt-ptt uses wtype which is Wayland-only. For X11, you would need to modify the script to use xdotool.
### Environment Variables
| Variable | Description | Default |
|----------|-------------|---------|
| `STT_MODEL` | Path to Whisper model file | `~/.local/share/stt-ptt/models/ggml-large-v3-turbo.bin` |
| `STT_NOTIFY_TIMEOUT` | Notification timeout in ms | `3000` |
## Requirements
- **whisper-cpp**: Speech recognition engine
- **wtype**: Wayland text input (Wayland compositor required)
- **libnotify**: Desktop notifications
- **pipewire**: Audio recording
## Model Setup
Download a Whisper model from [HuggingFace](https://huggingface.co/ggerganov/whisper.cpp/tree/main):
```bash
# Create model directory
mkdir -p ~/.local/share/stt-ptt/models
# Download model (example: large-v3-turbo)
curl -L -o ~/.local/share/stt-ptt/models/ggml-large-v3-turbo.bin \
https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-large-v3-turbo.bin
```
Or use the Home Manager module which handles this automatically.
## Available Models
| Model | Size | Quality | Speed |
|-------|------|---------|-------|
| `ggml-tiny` / `ggml-tiny.en` | 75MB | Basic | Fastest |
| `ggml-base` / `ggml-base.en` | 142MB | Good | Fast |
| `ggml-small` / `ggml-small.en` | 466MB | Better | Medium |
| `ggml-medium` / `ggml-medium.en` | 1.5GB | High | Slower |
| `ggml-large-v3-turbo` | 1.6GB | High | Fast |
| `ggml-large-v3` | 2.9GB | Highest | Slowest |
Models ending in `.en` are English-only and slightly faster for English text.
## Platform Support
- Linux with Wayland (primary)
- Requires PipeWire for audio
- X11 not supported (wtype is Wayland-only)
## Build Information
- **Version**: 0.1.0
- **Type**: Shell script wrapper
- **License**: MIT
## Troubleshooting
### Model Not Found
Error: `Error: Model not found at /path/to/model`
**Solution**: Download a model or use the Home Manager module:
```bash
curl -L -o ~/.local/share/stt-ptt/models/ggml-large-v3-turbo.bin \
https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-large-v3-turbo.bin
```
### No Audio Recorded
**Solution**: Ensure PipeWire is running:
```bash
systemctl --user status pipewire
```
### Text Not Typed
**Solution**: Ensure you're on Wayland and wtype has access:
```bash
# Check if running on Wayland
echo $XDG_SESSION_TYPE # Should print "wayland"
```
### Slow Transcription
**Solution**: Use a smaller model or enable GPU acceleration:
```nix
cli.stt-ptt = {
enable = true;
model = "ggml-base.en"; # Smaller, faster model
};
```
Or with GPU acceleration:
```nix
cli.stt-ptt = {
enable = true;
# Choose one:
whisperPackage = pkgs.whisper-cpp-vulkan; # Vulkan (pre-built)
# whisperPackage = pkgs.whisper-cpp.override { cudaSupport = true; }; # NVIDIA
# whisperPackage = pkgs.whisper-cpp.override { rocmSupport = true; }; # AMD
};
```
## Related
- [stt-ptt Home Manager Module](../modules/home-manager/cli/stt-ptt.md) - Module documentation
- [Adding Packages](../guides/adding-packages.md) - How to add new packages
+130
View File
@@ -0,0 +1,130 @@
# td
Minimalist CLI for tracking tasks across AI coding sessions.
## Description
td (task daemon) is a lightweight command-line tool designed for tracking tasks during AI-assisted coding sessions. It provides a simple, fast way to manage todos and maintain context across conversations with AI coding agents.
## Features
-**Minimal Task Tracking**: Simple, focused task management
- 🤖 **AI Session Aware**: Designed to work with AI coding workflows
- 📊 **Usage Tracking**: Track session usage and context
- 🔄 **Session Continuity**: Resume tasks from previous sessions
- 📝 **Git Integration**: Works alongside git workflows
-**Fast**: Lightweight Go binary with minimal overhead
## Installation
### Via Overlay
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
td
];
}
```
### Direct Reference
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
inputs.m3ta-nixpkgs.packages.${pkgs.system}.td
];
}
```
### Run Directly
```bash
nix run git+https://code.m3ta.dev/m3tam3re/nixpkgs#td
```
## Usage
### Starting a Session
```bash
# Start a new session and view current tasks
td usage --new-session
# Quick view of current tasks (no session tracking)
td usage -q
```
### Basic Commands
```bash
# Show version
td version
# View help
td --help
```
### Task Management
td integrates with AI coding workflows to track tasks across sessions. Use it at the start of conversations to establish context:
```bash
# At conversation start (or after /clear)
td usage --new-session
# For subsequent reads within the same session
td usage -q
```
## Integration with AI Agents
td is designed to be used by AI coding agents as part of their workflow:
1. **Session Start**: Agent reads current tasks with `td usage --new-session`
2. **Work Progress**: Tasks are tracked and updated during the session
3. **Session End**: State is preserved for the next session
### Example Integration
In an AI agent's system prompt or configuration:
```
You must run td usage --new-session at conversation start (or after /clear) to see current work.
Use td usage -q for subsequent reads.
```
## Configuration
### Environment Variables
- `TD_DATA_DIR`: Custom directory for td data storage
### Data Storage
Task data is stored locally in the project or user directory. See upstream documentation for exact storage location.
## Build Information
- **Version**: 0.34.0
- **Language**: Go
- **License**: MIT
- **Source**: [GitHub](https://github.com/marcus/td)
## Platform Support
- Linux
- macOS (Unix systems)
## Notes
- Tests are disabled in the Nix package build due to git worktree operations
- Version check is enabled for the Nix package (`td version`)
- Minimal dependencies - pure Go binary
## Related
- [sidecar](./sidecar.md) - Uses td for integrated task management
- [opencode](./opencode.md) - AI coding agent that integrates with td
- [Adding Packages](../guides/adding-packages.md) - How to add new packages
- [Quick Start](../QUICKSTART.md) - Getting started guide
+248
View File
@@ -0,0 +1,248 @@
# tuxedo-backlight
Keyboard backlight control for Tuxedo laptops.
## Description
A shell script that sets up RGB keyboard backlight colors for Tuxedo laptops with customizable colors for different key groups.
## Features
- ⌨️ **RGB Backlight**: Full RGB keyboard backlight support
- 🎨 **Color Groups**: Different colors for different key groups
- 🔤 **Key Highlighting**: Special colors for modifier keys
- 🎯 **One-Command Setup**: Apply all colors with single command
-**Fast**: Direct sysfs control
## Installation
### Via Overlay
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
tuxedo-backlight
];
}
```
### Direct Reference
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
inputs.m3ta-nixpkgs.packages.${pkgs.system}.tuxedo-backlight
];
}
```
### Run Directly
```bash
nix run git+https://code.m3ta.dev/m3tam3re/nixpkgs#tuxedo-backlight
```
## Usage
### Basic Usage
```bash
# Apply default color scheme
tuxedo-backlight
```
### Colors
The script applies these colors by default:
| Key Group | Color (RGB) | Description |
|-----------|-------------|-------------|
| Main keys | `0 150 255` | Blue (Cyan-ish) |
| Function keys (F1-F12) | `0 255 80` | Green (Lime) |
| Arrow keys | `0 255 80` | Green (Lime) |
| Numpad area | `255 150 0` | Orange |
| DEL key | `255 0 155` | Pink/Magenta |
| ESC key | `255 0 155` | Pink/Magenta |
## Customization
### Modify Colors
Edit the script to customize colors:
```nix
# In pkgs/tuxedo-backlight/default.nix
# All keys
echo 'R G B' | tee /sys/class/leds/rgb:kbd_backlight*/multi_intensity
# Specific key (e.g., ESC)
echo 'R G B' | tee /sys/class/leds/rgb:kbd_backlight/multi_intensity
```
RGB format: `Red Green Blue` (0-255 each)
### Color Examples
| Color | RGB Value |
|--------|-----------|
| Red | `255 0 0` |
| Green | `0 255 0` |
| Blue | `0 0 255` |
| Cyan | `0 255 255` |
| Magenta | `255 0 255` |
| Yellow | `255 255 0` |
| White | `255 255 255` |
| Orange | `255 150 0` |
| Purple | `150 0 255` |
## Automatic Startup
### Systemd Service
Create `/etc/systemd/system/tuxedo-backlight.service`:
```ini
[Unit]
Description=Tuxedo Keyboard Backlight
After=multi-user.target
[Service]
Type=oneshot
ExecStart=/run/current-system/sw/bin/tuxedo-backlight
[Install]
WantedBy=multi-user.target
```
Enable and start:
```bash
sudo systemctl enable tuxedo-backlight.service
sudo systemctl start tuxedo-backlight.service
```
### NixOS Configuration
```nix
{pkgs, ...}: {
# Run at boot
systemd.services.tuxedo-backlight = {
description = "Set Tuxedo keyboard backlight";
after = ["multi-user.target"];
wantedBy = ["multi-user.target"];
serviceConfig = {
Type = "oneshot";
ExecStart = "${pkgs.tuxedo-backlight}/bin/tuxedo-backlight";
};
};
}
```
## Requirements
### Hardware
- Tuxedo laptop with RGB keyboard backlight
- Linux kernel with appropriate driver support
### System Requirements
- Linux (Tuxedo laptops)
- Write access to `/sys/class/leds/`
### Permissions
The script requires write access to sysfs:
```bash
# Check permissions
ls -la /sys/class/leds/rgb:kbd_backlight*
# If permissions are needed
sudo tuxedo-backlight
```
## Platform Support
- Linux (Tuxedo laptops only)
- macOS (not supported)
- Windows (not supported)
## Troubleshooting
### No Such Device
Error: `No such file or directory`
**Solution**: Ensure you're on a Tuxedo laptop with RGB keyboard:
```bash
# Check if RGB backlight exists
ls -la /sys/class/leds/rgb:kbd_backlight*
```
### Permission Denied
Error: `Permission denied`
**Solution**: Run with sudo or configure udev rules:
```bash
# Run with sudo
sudo tuxedo-backlight
# Or create udev rule for user access
sudo vim /etc/udev/rules.d/99-tuxedo-backlight.rules
```
udev rule:
```
SUBSYSTEM=="leds", ATTR{brightness}=="*", ACTION=="add", RUN+="/usr/bin/chgrp -R input /sys/class/leds/rgb:*"
SUBSYSTEM=="leds", ATTR{brightness}=="*", ACTION=="add", RUN+="/usr/bin/chmod -R g+w /sys/class/leds/rgb:*"
```
### Colors Not Applied
**Solution**:
1. Check RGB backlight is supported:
```bash
cat /sys/class/leds/rgb:kbd_backlight*/multi_intensity
```
2. Ensure driver is loaded:
```bash
# Check for Tuxedo drivers
lsmod | grep tuxedo
# Load if needed
sudo modprobe tuxedo_keyboard
```
## Key Layout Reference
The script sets colors for these key groups:
### Key Numbers
- **All keys**: Main keyboard area (except special keys)
- **15**: DEL key
- **No number**: ESC key
- **1-12, 102**: Function keys (F1-F12, Fn)
- **16-19, 36-39, 56-59, 76-79, 96-99, 117-119**: Numpad and keys above numpad
- **95, 114-116**: Arrow keys
## Build Information
- **Version**: 0.1.0
- **Type**: Shell script
- **License**: MIT
## Related
- [Adding Packages](../guides/adding-packages.md) - How to add new packages
- [Quick Start](../QUICKSTART.md) - Getting started guide
+204
View File
@@ -0,0 +1,204 @@
# zellij-ps
A Zellij project switcher for quickly navigating and opening project workspaces.
## Description
zellij-ps is a Fish script inspired by ThePrimeagen's tmux-sessionizer. It provides a fast, interactive way to switch between project folders in Zellij. Using `fd` for fast directory discovery and `fzf` for fuzzy selection, it helps you quickly jump into your work.
The script searches through your configured project folders (`$PROJECT_FOLDERS`) and either creates a new Zellij session for the selected project or attaches to an existing one.
## Installation
### Via Overlay
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
zellij-ps
];
}
```
### Direct Reference
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
inputs.m3ta-nixpkgs.packages.${pkgs.system}.zellij-ps
];
}
```
### Run Directly
```bash
nix run git+https://code.m3ta.dev/m3tam3re/nixpkgs#zellij-ps
```
## Usage
### Basic Usage
```bash
# Run from outside Zellij to start a project session
zellij-ps
# Or pass a project path directly
zellij-ps ~/projects/my-project
```
This will:
1. Search through your `$PROJECT_FOLDERS` for directories
2. Open fzf for fuzzy project selection (if no argument provided)
3. Create a new Zellij session or attach to existing one for the selected project
### Configuration
Set your project folders in your shell configuration:
**Fish example:**
```fish
set -x PROJECT_FOLDERS ~/projects:~/code:~/work
```
**Bash/Zsh example:**
```bash
export PROJECT_FOLDERS="$HOME/projects:$HOME/code:$HOME/work"
```
Folders should be delimited by `:` and can include `~` for home directory.
## Home Manager Module
### Enable Module
```nix
{config, ...}: {
imports = [m3ta-nixpkgs.homeManagerModules.default];
cli.zellij-ps = {
enable = true;
};
}
```
### Module Options
#### `cli.zellij-ps.enable`
Enable the zellij-ps module.
- Type: `boolean`
- Default: `false`
#### `cli.zellij-ps.package`
Custom package to use.
- Type: `package`
- Default: `pkgs.zellij-ps`
## Requirements
### System Requirements
- Linux or Unix-like system
- Configured `$PROJECT_FOLDERS` environment variable
## Platform Support
- Linux (primary)
- macOS (may work)
- Windows (not supported)
## Build Information
- **Version**: 0.1.0
- **Type**: Fish script
- **License**: MIT
- **Inspired by**: [ThePrimeagen's tmux-sessionizer](https://github.com/ThePrimeagen/.dotfiles/blob/master/bin/.local/scripts/tmux-sessionizer)
- **Source**: [Gitea](https://code.m3ta.dev/m3tam3re/helper-scripts)
## Source Code
The script is available at:
```
https://code.m3ta.dev/m3tam3re/helper-scripts/src/branch/main/zellij-ps.fish
```
## Troubleshooting
### No Projects Found
If fzf shows no results, check your `$PROJECT_FOLDERS` variable:
```bash
# In fish
echo $PROJECT_FOLDERS
# In bash/zsh
echo $PROJECT_FOLDERS
```
Ensure the folders exist and contain subdirectories.
### Already in Zellij Session
If you're already inside a Zellij session, you'll see:
```
You are in a Zellij Session!
Please use the session manager to switch sessions.
```
Use Zellij's built-in session manager (`Ctrl+p``s`) to switch sessions instead.
### fd Not Found
Error: `fd: command not found`
**Solution**: Ensure fd is installed:
```nix
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
fd
];
}
```
### Fish Not Found
Error: `fish: command not found`
**Solution**: Ensure Fish is installed:
```nix
{pkgs, ...}: {
programs.fish = {
enable = true;
};
}
```
### fzf Not Working
Ensure fzf is installed and configured:
```bash
# Check fzf
which fzf
# Test fzf
echo -e "item1\nitem2\nitem3" | fzf
```
## Related
- [zellij-ps Module](../modules/home-manager/cli/zellij-ps.md) - Home Manager module documentation
- [Using Modules](../guides/using-modules.md) - How to use modules
- [Adding Packages](../guides/adding-packages.md) - How to add new packages
- [Quick Start](../QUICKSTART.md) - Getting started guide
+272
View File
@@ -0,0 +1,272 @@
# Library Functions
Documentation for library functions available in m3ta-nixpkgs.
## Overview
The library provides helper functions for your NixOS and Home Manager configurations.
## Available Libraries
### `m3ta-lib.ports`
Port management utilities for managing service ports across hosts.
## Port Management Functions
### `mkPortHelpers`
Create port helper functions from a ports configuration.
#### Signature
```nix
mkPortHelpers :: portsConfig -> portHelpers
```
#### Arguments
`portsConfig` - An attribute set with structure:
```nix
{
ports = { service-name = port-number; ... };
hostPorts = { hostname = { service-name = port-number; ... }; ... };
}
```
#### Returns
An attribute set containing helper functions:
```nix
{
getPort = service: host -> port-number-or-null;
getHostPorts = host -> ports-attrs;
listServices = -> [string];
}
```
#### Usage
```nix
{config, inputs, ...}: let
m3taLib = inputs.m3ta-nixpkgs.lib.${config.system};
myPorts = {
ports = {
nginx = 80;
grafana = 3000;
};
hostPorts = {
laptop = {
nginx = 8080;
};
};
};
portHelpers = m3taLib.ports.mkPortHelpers myPorts;
in {
# Get port with host override
services.nginx.port = portHelpers.getPort "nginx" config.networking.hostName;
# Get all ports for host
laptopPorts = portHelpers.getHostPorts "laptop";
# List all services
allServices = portHelpers.listServices;
}
```
### `getPort` (from portHelpers)
Get port for a service, with optional host-specific override.
#### Signature
```nix
getPort :: string -> string -> int-or-null
```
#### Arguments
1. `service` - The service name (string)
2. `host` - The hostname (string), or `null` for default
#### Returns
Port number (int) or `null` if service not found.
#### Usage
```nix
services.nginx = {
port = portHelpers.getPort "nginx" "laptop"; # Returns host-specific port
# or
port = portHelpers.getPort "nginx" null; # Returns default port
};
```
### `getHostPorts` (from portHelpers)
Get all ports for a specific host (merges defaults with host overrides).
#### Signature
```nix
getHostPorts :: string -> attrs
```
#### Arguments
1. `host` - The hostname (string)
#### Returns
Attribute set of all ports for the host.
#### Usage
```nix
laptopPorts = portHelpers.getHostPorts "laptop";
# Returns: { nginx = 8080; grafana = 3000; prometheus = 9090; ... }
```
### `listServices` (from portHelpers)
List all defined service names.
#### Signature
```nix
listServices :: -> [string]
```
#### Returns
List of service names (strings).
#### Usage
```nix
allServices = portHelpers.listServices;
# Returns: ["nginx" "grafana" "prometheus" "homepage"]
```
### `getDefaultPort`
Simple helper to get a port without host override.
#### Signature
```nix
getDefaultPort :: portsConfig -> string -> int-or-null
```
#### Arguments
1. `portsConfig` - Same structure as `mkPortHelpers`
2. `service` - The service name (string)
#### Returns
Port number (int) or `null` if service not found.
#### Usage
```nix
services.my-service = {
port = m3taLib.ports.getDefaultPort myPorts "my-service";
};
```
## Using Library Functions
### Importing
```nix
{config, inputs, ...}: let
# Import library
m3taLib = inputs.m3ta-nixpkgs.lib.${config.system};
in {
# Use library functions
}
```
### Example: Custom Port Management
```nix
{config, inputs, ...}: let
m3taLib = inputs.m3ta-nixpkgs.lib.${config.system};
myPorts = {
ports = {
web = 80;
api = 8080;
db = 5432;
};
hostPorts = {
dev = {
web = 8080;
api = 8081;
};
};
};
portHelpers = m3taLib.ports.mkPortHelpers myPorts;
hostname = config.networking.hostName;
in {
services.nginx = {
enable = true;
virtualHosts.${hostname} = {
locations."/" = {
proxyPass = "http://localhost:${toString (portHelpers.getPort "api" hostname)}";
};
};
};
services.postgresql = {
enable = true;
port = portHelpers.getPort "db" hostname;
};
}
```
### Example: Generate Config Files
```nix
{inputs, ...}: let
m3taLib = inputs.m3ta-nixpkgs.lib.${system};
myPorts = {
ports = {
service1 = 3000;
service2 = 3001;
};
};
portHelpers = m3taLib.ports.mkPortHelpers myPorts;
in {
environment.etc."ports.toml".text = generators.toTOML {} {
services = portHelpers.getHostPorts "desktop";
};
}
```
## Function Reference Summary
| Function | Purpose | Return Type |
|----------|---------|------------|
| `mkPortHelpers` | Create port helper functions | `portHelpers` attrs |
| `getPort` | Get port with optional host override | `int or null` |
| `getHostPorts` | Get all ports for host | `attrs` |
| `listServices` | List all service names | `[string]` |
| `getDefaultPort` | Get default port only | `int or null` |
## Related
- [Port Management Guide](../guides/port-management.md) - Detailed usage guide
- [NixOS Ports Module](../modules/nixos/ports.md) - Port management module
- [Home Manager Ports Module](../modules/home-manager/ports.md) - User-level port management
- [Architecture](../ARCHITECTURE.md) - Understanding library functions
+498
View File
@@ -0,0 +1,498 @@
# Code Patterns and Anti-Patterns
Common code patterns and anti-patterns used in m3ta-nixpkgs.
## Overview
This document outlines recommended patterns and common pitfalls when working with m3ta-nixpkgs.
## Code Patterns
### Package Pattern
#### CallPackage Registry
Use `callPackage` for lazy evaluation:
```nix
# Good - pkgs/default.nix
{
inherit (pkgs) callPackage;
} rec {
code2prompt = callPackage ./code2prompt {};
mem0 = callPackage ./mem0 {};
}
```
#### Meta Fields
Always include complete `meta` information:
```nix
# Good
meta = with lib; {
description = "My awesome package";
homepage = "https://github.com/author/package";
changelog = "https://github.com/author/package/releases/tag/v${version}";
license = licenses.mit;
platforms = platforms.linux;
mainProgram = "program-name";
};
```
### Module Pattern
#### Standard Module Structure
```nix
# Good
{ config, lib, pkgs, ... }:
with lib; let
cfg = config.m3ta.myModule;
in {
options.m3ta.myModule = {
enable = mkEnableOption "my module";
# ... options
};
config = mkIf cfg.enable {
# ... configuration
};
}
```
#### mkEnableOption
Always use `mkEnableOption` for enable flags:
```nix
# Good
options.m3ta.myModule = {
enable = mkEnableOption "my module";
};
# Bad
options.m3ta.myModule.enable = mkOption {
type = types.bool;
default = false;
};
```
#### Conditional Configuration
Use `mkIf` for conditional config:
```nix
# Good
config = mkIf cfg.enable {
services.my-service.enable = true;
};
```
#### Multiple Conditions
Use `mkMerge` for multiple conditions:
```nix
# Good
config = mkMerge [
(mkIf cfg.feature1.enable {
# config for feature1
})
(mkIf cfg.feature2.enable {
# config for feature2
})
];
```
### Import Pattern
#### Multi-line Imports
Multi-line, trailing commas:
```nix
# Good
{
lib,
stdenv,
fetchFromGitHub,
}:
```
#### Explicit Dependencies
```nix
# Good
{
lib,
stdenv,
openssl,
pkg-config,
}:
stdenv.mkDerivation {
buildInputs = [openssl pkg-config];
}
```
## Anti-Patterns
### lib.fakeHash in Commits
**Bad**: Committing `lib.fakeHash`
```nix
# Bad - Never commit this!
src = fetchFromGitHub {
hash = lib.fakeHash;
};
```
**Solution**: Build to get real hash:
```bash
nix build .#your-package
# Copy actual hash from error message
```
### Flat Module Files
**Bad**: All modules in one file
```nix
# Bad - Hard to maintain
{config, lib, pkgs, ...}: {
options.m3ta.cli = {
tool1 = mkEnableOption "tool1";
tool2 = mkEnableOption "tool2";
# ... many more
};
config = mkMerge [
(mkIf config.cli.tool1.enable {...})
(mkIf config.cli.tool2.enable {...})
# ... many more
];
}
```
**Solution**: Organize by category
```nix
# Good - modules/home-manager/cli/
# modules/home-manager/cli/default.nix
{
imports = [
./tool1.nix
./tool2.nix
];
}
```
### Hardcoded Ports
**Bad**: Hardcoding ports in services
```nix
# Bad
services.nginx = {
enable = true;
httpConfig = ''
server {
listen 80;
}
'';
};
```
**Solution**: Use port management
```nix
# Good
m3ta.ports = {
enable = true;
definitions = {nginx = 80;};
};
services.nginx = {
enable = true;
httpConfig = ''
server {
listen ${toString (config.m3ta.ports.get "nginx")};
}
'';
};
```
### Skipping Meta Fields
**Bad**: Incomplete meta information
```nix
# Bad
meta = {
description = "My package";
};
```
**Solution**: Include all fields
```nix
# Good
meta = with lib; {
description = "My awesome package";
homepage = "https://github.com/author/package";
license = licenses.mit;
platforms = platforms.linux;
mainProgram = "program-name";
};
```
### with pkgs; in Modules
**Bad**: Using `with pkgs;` at module level
```nix
# Bad
{config, lib, pkgs, ...}: with pkgs; {
config.environment.systemPackages = [
vim
git
];
}
```
**Solution**: Explicit package references or limited with
```nix
# Good - Explicit references
{config, lib, pkgs, ...}: {
config.environment.systemPackages = with pkgs; [
vim
git
];
}
# Or - Full references
{config, lib, pkgs, ...}: {
config.environment.systemPackages = [
pkgs.vim
pkgs.git
];
}
```
### Orphaned Package Directories
**Bad**: Creating directory without registering
```nix
# Bad - Package not visible
# pkgs/my-package/default.nix exists
# But pkgs/default.nix doesn't reference it
```
**Solution**: Register in `pkgs/default.nix`
```nix
# Good
{
inherit (pkgs) callPackage;
} rec {
my-package = callPackage ./my-package {};
}
```
## Type Safety
### No Type Suppression
**Bad**: Using `as any`
```nix
# Bad
let
value = someFunction config as any;
in
# ...
```
**Solution**: Fix underlying type issues
```nix
# Good
let
value = someFunction config;
in
# Ensure value has correct type
```
### Proper Type Definitions
```nix
# Good
options.m3ta.myModule = {
enable = mkEnableOption "my module";
port = mkOption {
type = types.port;
default = 8080;
description = "Port to run on";
};
};
```
## Naming Conventions
### Package Names
**Good**: `lowercase-hyphen`
```nix
code2prompt
hyprpaper-random
launch-webapp
```
**Bad**: CamelCase or underscores
```nix
code2Prompt # Bad
hyprpaper_random # Bad
```
### Variables
**Good**: `camelCase`
```nix
portHelpers
configFile
serviceName
```
**Bad**: Snake_case or kebab-case
```nix
port_helpers # Bad
port-helpers # Bad
```
### Module Options
**Good**: `m3ta.*` namespace for m3ta modules, `cli.*` namespace for CLI modules
```nix
m3ta.ports.enable = true;
cli.zellij-ps.enable = true;
```
**Bad**: Flat namespace
```nix
ports.enable = true; # Potential conflict
zellij-ps.enable = true; # Hard to find
```
## Performance
### Lazy Evaluation
**Good**: Use `callPackage`
```nix
# Good - Only builds requested package
code2prompt = callPackage ./code2prompt {};
```
**Bad**: Building all packages
```nix
# Bad - Builds everything even if not used
code2prompt = import ./code2prompt {};
```
### Selective Imports
**Good**: Import only needed modules
```nix
# Good
imports = [
m3ta-nixpkgs.nixosModules.mem0
];
```
**Bad**: Importing all modules
```nix
# Bad - Imports and evaluates all modules
imports = [
m3ta-nixpkgs.nixosModules.default
];
```
## Security
### No Secrets in Store
**Bad**: Putting secrets in configuration
```nix
# Bad - Secret in Nix store
m3ta.mem0.llm.apiKey = "sk-xxx";
```
**Solution**: Use secret files
```nix
# Good - Secret from file
m3ta.mem0.llm.apiKeyFile = "/run/secrets/openai-api-key";
```
### Proper User/Group
**Good**: Dedicated users for services
```nix
# Good
users.users.mem0 = {
isSystemUser = true;
group = "mem0";
};
```
### Service Hardening
**Good**: Enable systemd hardening
```nix
# Good
systemd.services.mem0.serviceConfig = {
NoNewPrivileges = true;
PrivateTmp = true;
ProtectSystem = "strict";
ProtectHome = true;
};
```
## Best Practices Summary
| Practice | Do | Don't |
|----------|-----|--------|
| Hash fetching | Get real hash from build error | Commit `lib.fakeHash` |
| Module organization | Categorize by function | Put all in one file |
| Port management | Use `m3ta.ports` module | Hardcode ports |
| Meta fields | Include all fields | Skip fields |
| Type safety | Fix type errors | Use `as any` |
| Dependencies | Explicit declarations | Implicit deps |
| Imports | Multi-line, trailing comma | Single-line, no comma |
| Naming | Follow conventions | Mix styles |
| Secrets | Use file-based | Put in config |
| Evaluation | Lazy (`callPackage`) | Import everything |
## Related
- [Contributing Guide](../CONTRIBUTING.md) - Code style and guidelines
- [Architecture](../ARCHITECTURE.md) - Understanding repository structure
- [Adding Packages](../guides/adding-packages.md) - Package creation patterns
+193
View File
@@ -0,0 +1,193 @@
# Example Standalone Home Manager Configuration using m3ta-nixpkgs
# This file demonstrates how to use m3ta-nixpkgs with standalone Home Manager
# (without NixOS)
{
description = "Example Home Manager configuration with m3ta-nixpkgs";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};
# Add m3ta-nixpkgs as an input
m3ta-nixpkgs = {
url = "git+https://code.m3ta.dev/m3tam3re/nixpkgs";
# Or use a local path during development:
# url = "path:/home/user/projects/m3ta-nixpkgs";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = {
self,
nixpkgs,
home-manager,
m3ta-nixpkgs,
...
} @ inputs: let
system = "x86_64-linux"; # Change to your system: aarch64-linux, x86_64-darwin, aarch64-darwin
pkgs = import nixpkgs {
inherit system;
config.allowUnfree = true;
# Apply m3ta-nixpkgs overlays
overlays = [
m3ta-nixpkgs.overlays.default
];
};
in {
homeConfigurations = {
# Replace 'm3tam3re' with your actual username
m3tam3re = home-manager.lib.homeManagerConfiguration {
inherit pkgs;
# Pass inputs as extra special args
extraSpecialArgs = {inherit inputs;};
modules = [
# Import m3ta's Home Manager modules
m3ta-nixpkgs.homeManagerModules.default
# Main Home Manager configuration
{
# ============================================
# User Information
# ============================================
home.username = "m3tam3re";
home.homeDirectory = "/home/m3tam3re";
home.stateVersion = "24.05";
# ============================================
# Packages from m3ta-nixpkgs
# ============================================
# Since we applied the overlay above, packages are available directly
home.packages = with pkgs; [
# Custom packages from m3ta-nixpkgs
code2prompt
hyprpaper-random
launch-webapp
msty-studio
pomodoro-timer
zellij-ps
# Regular packages from nixpkgs
git
vim
htop
fzf
ripgrep
];
# ============================================
# Custom Home Manager Modules
# ============================================
# If you've defined custom Home Manager modules
# programs.myProgram = {
# enable = true;
# package = pkgs.myProgram;
# settings = {
# theme = "dark";
# };
# };
# ============================================
# Shell Configuration
# ============================================
programs.bash = {
enable = true;
shellAliases = {
ll = "ls -l";
".." = "cd ..";
};
};
programs.zsh = {
enable = true;
enableCompletion = true;
autosuggestion.enable = true;
syntaxHighlighting.enable = true;
};
# ============================================
# Git Configuration
# ============================================
programs.git = {
enable = true;
userName = "Your Name";
userEmail = "your.email@example.com";
extraConfig = {
init.defaultBranch = "main";
pull.rebase = false;
};
};
# ============================================
# Additional Programs
# ============================================
programs.direnv = {
enable = true;
nix-direnv.enable = true;
};
programs.fzf = {
enable = true;
enableBashIntegration = true;
enableZshIntegration = true;
};
# ============================================
# Environment Variables
# ============================================
home.sessionVariables = {
EDITOR = "vim";
VISUAL = "vim";
};
# ============================================
# File Management
# ============================================
# Create custom config files
home.file.".config/my-app/config.json".text = ''
{
"setting": "value"
}
'';
# ============================================
# Allow Home Manager to manage itself
# ============================================
programs.home-manager.enable = true;
}
];
};
# ============================================
# Minimal Example Configuration
# ============================================
minimal = home-manager.lib.homeManagerConfiguration {
pkgs = import nixpkgs {
inherit system;
overlays = [m3ta-nixpkgs.overlays.default];
};
modules = [
{
home.username = "m3tam3re";
home.homeDirectory = "/home/m3tam3re";
home.stateVersion = "24.05";
# Just use a couple of custom packages
home.packages = with pkgs; [
code2prompt
zellij-ps
];
programs.home-manager.enable = true;
}
];
};
};
};
}
+153
View File
@@ -0,0 +1,153 @@
# Example NixOS Configuration using m3ta-nixpkgs
# This file demonstrates how to integrate m3ta-nixpkgs into your NixOS system
{
description = "Example NixOS configuration with m3ta-nixpkgs";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
# Add m3ta-nixpkgs as an input
m3ta-nixpkgs = {
url = "git+https://code.m3ta.dev/m3tam3re/nixpkgs";
# Or use a local path during development:
# url = "path:/home/user/projects/m3ta-nixpkgs";
inputs.nixpkgs.follows = "nixpkgs";
};
home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = {
self,
nixpkgs,
m3ta-nixpkgs,
home-manager,
...
} @ inputs: {
nixosConfigurations = {
# Replace 'hostname' with your actual hostname
hostname = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
specialArgs = {inherit inputs;};
modules = [
# Your hardware configuration
./hardware-configuration.nix
# Import m3ta's NixOS modules (if any are defined)
m3ta-nixpkgs.nixosModules.default
# Main configuration
({pkgs, ...}: {
# ============================================
# METHOD 1: Using Overlays (Recommended)
# ============================================
# This makes custom packages available as if they were in nixpkgs
nixpkgs.overlays = [
m3ta-nixpkgs.overlays.default
# Or use individual overlays for more control:
# m3ta-nixpkgs.overlays.additions
# m3ta-nixpkgs.overlays.modifications
];
# Now you can use packages normally
environment.systemPackages = with pkgs; [
# Custom packages from m3ta-nixpkgs
code2prompt
hyprpaper-random
msty-studio
pomodoro-timer
tuxedo-backlight
zellij-ps
# Regular nixpkgs packages
vim
git
htop
];
# ============================================
# METHOD 2: Direct Package Reference
# ============================================
# Use this if you don't want to use overlays
# environment.systemPackages = [
# inputs.m3ta-nixpkgs.packages.${pkgs.system}.code2prompt
# inputs.m3ta-nixpkgs.packages.${pkgs.system}.zellij-ps
# ];
# ============================================
# Using Custom NixOS Modules
# ============================================
# If you've defined custom NixOS modules, configure them here
# m3ta.myModule = {
# enable = true;
# # module-specific options
# };
# ============================================
# System Configuration
# ============================================
system.stateVersion = "24.05";
networking.hostName = "hostname";
# Enable flakes
nix.settings.experimental-features = ["nix-command" "flakes"];
})
# ============================================
# Home Manager Integration
# ============================================
home-manager.nixosModules.home-manager
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.users.m3tam3re = {pkgs, ...}: {
# Import m3ta's Home Manager modules
imports = [
m3ta-nixpkgs.homeManagerModules.default
# Or import specific modules:
# m3ta-nixpkgs.homeManagerModules.zellij-ps
];
# Home Manager packages with overlay
home.packages = with pkgs; [
launch-webapp
# Other packages...
];
# Configure custom Home Manager modules
# programs.myProgram = {
# enable = true;
# # options...
# };
home.stateVersion = "24.05";
};
}
];
};
# ============================================
# Alternative: Minimal Configuration
# ============================================
minimal = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
({pkgs, ...}: {
nixpkgs.overlays = [m3ta-nixpkgs.overlays.default];
environment.systemPackages = with pkgs; [
code2prompt
];
system.stateVersion = "24.05";
})
];
};
};
};
}
Generated
+87
View File
@@ -0,0 +1,87 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1772198003,
"narHash": "sha256-I45esRSssFtJ8p/gLHUZ1OUaaTaVLluNkABkk6arQwE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "dd9b079222d43e1943b6ebd802f04fd959dc8e61",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-master": {
"locked": {
"lastModified": 1772329946,
"narHash": "sha256-MQoHdM+oi4d5kEYUmQg/VsX8GmqeaLJwdJ+pdJqdusI=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "7dddcba64f7fee647caedb7f7c3e8500418cb94c",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "master",
"repo": "nixpkgs",
"type": "github"
}
},
"opencode": {
"inputs": {
"nixpkgs": [
"nixpkgs-master"
]
},
"locked": {
"lastModified": 1772094145,
"narHash": "sha256-26MV9TbyAF0KFqZtIHPYu6wqJwf0pNPdW/D3gDQEUlQ=",
"owner": "anomalyco",
"repo": "opencode",
"rev": "799b2623cbb1c0f19e045d87c2c8593e83678bc0",
"type": "github"
},
"original": {
"owner": "anomalyco",
"ref": "v1.2.15",
"repo": "opencode",
"type": "github"
}
},
"openspec": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1772182342,
"narHash": "sha256-9Q0iUyZGcDPLdgvnrBN3GumV8g9akV8TFb8bFkD1yYs=",
"owner": "Fission-AI",
"repo": "OpenSpec",
"rev": "afdca0d5dab1aa109cfd8848b2512333ccad60c3",
"type": "github"
},
"original": {
"owner": "Fission-AI",
"repo": "OpenSpec",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs",
"nixpkgs-master": "nixpkgs-master",
"opencode": "opencode",
"openspec": "openspec"
}
}
},
"root": "root",
"version": 7
}
+125
View File
@@ -0,0 +1,125 @@
{
description = "m3ta's personal Nix repository - Custom packages, overlays, and modules";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
nixpkgs-master.url = "github:NixOS/nixpkgs/master";
# opencode needs newer bun from master
opencode = {
url = "github:anomalyco/opencode/v1.2.15";
inputs.nixpkgs.follows = "nixpkgs-master";
};
# openspec - spec-driven development for AI coding assistants
openspec = {
url = "github:Fission-AI/OpenSpec";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = {
self,
nixpkgs,
...
} @ inputs: let
# Supported systems
systems = ["x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin"];
# Helper function to generate an attrset for each of the systems
forAllSystems = nixpkgs.lib.genAttrs systems;
# Helper to create pkgs for a given system
pkgsFor = system:
import nixpkgs {
inherit system;
config.allowUnfree = true;
};
in {
# Custom packages - accessible via 'nix build .#package-name'
packages = forAllSystems (system: let
pkgs = pkgsFor system;
in
import ./pkgs {inherit pkgs inputs;});
# Overlays - can be imported in your system configuration
overlays = {
# Default overlay: adds all custom packages
default = final: prev:
import ./pkgs {
pkgs = final;
inputs = inputs;
};
# Individual overlays for more granular control
additions = final: prev:
import ./pkgs {
pkgs = final;
inputs = inputs;
};
modifications = final: prev: import ./overlays/mods {inherit prev;};
};
# NixOS modules - for system-level configuration
nixosModules = {
default = ./modules/nixos;
# Individual modules for selective imports
ports = ./modules/nixos/ports.nix;
mem0 = ./modules/nixos/mem0.nix;
};
# Home Manager modules - for user-level configuration
homeManagerModules = {
default = import ./modules/home-manager;
ports = import ./modules/home-manager/ports.nix;
zellij-ps = import ./modules/home-manager/zellij-ps.nix;
};
# Library functions - helper utilities for your configuration
lib = forAllSystems (system: let
pkgs = pkgsFor system;
in
import ./lib {lib = pkgs.lib;});
# Development shells for various programming environments
# Usage: nix develop .#<shell-name>
# Available shells: default, python, devops, opencode
devShells = forAllSystems (system: let
pkgs = pkgsFor system;
in
import ./shells {inherit pkgs inputs;});
# Formatter for 'nix fmt'
formatter = forAllSystems (system: (pkgsFor system).alejandra);
# Checks for 'nix flake check' - verifies all packages build
checks = forAllSystems (system: let
pkgs = pkgsFor system;
packages = import ./pkgs {inherit pkgs inputs;};
in
builtins.mapAttrs (name: pkg: pkgs.lib.hydraJob pkg) packages
// {
formatting = pkgs.runCommand "check-formatting" {} ''
${pkgs.alejandra}/bin/alejandra --check ${./.}
touch $out
'';
});
# Templates for creating new packages/modules
templates = {
package = {
path = ./templates/package;
description = "Template for a new package";
};
nixos-module = {
path = ./templates/nixos-module;
description = "Template for a new NixOS module";
};
home-manager-module = {
path = ./templates/home-manager-module;
description = "Template for a new Home Manager module";
};
};
};
}
+12
View File
@@ -0,0 +1,12 @@
# Library of helper functions for m3ta-nixpkgs
# Usage in your configuration:
# let
# m3taLib = inputs.m3ta-nixpkgs.lib.${system};
# in ...
{lib}: {
# Port management utilities
ports = import ./ports.nix {inherit lib;};
# OpenCode rules injection utilities
opencode-rules = import ./opencode-rules.nix {inherit lib;};
}
+116
View File
@@ -0,0 +1,116 @@
# Opencode rules management utilities
#
# This module provides functions to configure Opencode agent rules across
# multiple projects. Rules are defined in the AGENTS repository and can be
# selectively included based on language, framework, and concerns.
#
# Usage in your configuration:
#
# # In your flake or configuration:
# let
# m3taLib = inputs.m3ta-nixpkgs.lib.${system};
#
# rules = m3taLib.opencode-rules.mkOpencodeRules {
# agents = inputs.agents;
# languages = [ "python" "typescript" ];
# concerns = [ "coding-style" "naming" "documentation" ];
# frameworks = [ "react" "fastapi" ];
# };
# in {
# # Use in your devShell:
# devShells.default = pkgs.mkShell {
# shellHook = rules.shellHook;
# inherit (rules) instructions;
# };
# }
#
# The shellHook creates:
# - A `.opencode-rules/` symlink pointing to the AGENTS repository rules directory
# - An `opencode.json` file with a $schema reference and instructions list
#
# The instructions list contains paths relative to the project root, all prefixed
# with `.opencode-rules/`, making them portable across different project locations.
{lib}: {
# Create Opencode rules configuration from AGENTS repository
#
# Args:
# agents: Path to the AGENTS repository (non-flake input)
# languages: Optional list of language-specific rules to include
# (e.g., [ "python" "typescript" "rust" ])
# concerns: Optional list of concern rules to include
# Default: [ "coding-style" "naming" "documentation" "testing" "git-workflow" "project-structure" ]
# frameworks: Optional list of framework-specific rules to include
# (e.g., [ "react" "fastapi" "django" ])
# extraInstructions: Optional list of additional instruction paths
# (for custom rules outside standard locations)
#
# Returns:
# An attribute set containing:
# - shellHook: Bash code to create symlink and opencode.json
# - instructions: List of rule file paths (relative to project root)
#
# Example:
# mkOpencodeRules {
# agents = inputs.agents;
# languages = [ "python" ];
# frameworks = [ "fastapi" ];
# }
# # Returns:
# # {
# # shellHook = "...";
# # instructions = [
# # ".opencode-rules/concerns/coding-style.md"
# # ".opencode-rules/concerns/naming.md"
# # ".opencode-rules/concerns/documentation.md"
# # ".opencode-rules/concerns/testing.md"
# # ".opencode-rules/concerns/git-workflow.md"
# # ".opencode-rules/concerns/project-structure.md"
# # ".opencode-rules/languages/python.md"
# # ".opencode-rules/frameworks/fastapi.md"
# # ];
# # }
mkOpencodeRules = {
agents,
languages ? [],
concerns ? [
"coding-style"
"naming"
"documentation"
"testing"
"git-workflow"
"project-structure"
],
frameworks ? [],
extraInstructions ? [],
}: let
rulesDir = ".opencode-rules";
# Build instructions list by mapping concerns, languages, frameworks to their file paths
# All paths are relative to project root via the rulesDir symlink
instructions =
(map (c: "${rulesDir}/concerns/${c}.md") concerns)
++ (map (l: "${rulesDir}/languages/${l}.md") languages)
++ (map (f: "${rulesDir}/frameworks/${f}.md") frameworks)
++ extraInstructions;
# Generate JSON configuration for Opencode
opencodeConfig = {
"$schema" = "https://opencode.ai/config.json";
inherit instructions;
};
in {
inherit instructions;
# Shell hook to set up rules in the project
# Creates a symlink to the AGENTS rules directory and generates opencode.json
shellHook = ''
# Create/update symlink to AGENTS rules directory
ln -sfn ${agents}/rules ${rulesDir}
# Generate opencode.json configuration file
cat > opencode.json <<'OPENCODE_EOF'
${builtins.toJSON opencodeConfig}
OPENCODE_EOF
'';
};
}
+113
View File
@@ -0,0 +1,113 @@
# Port management utilities
#
# This module provides functions to manage service ports across multiple hosts
# in a centralized way. Ports are defined in your configuration and can have
# host-specific overrides.
#
# Usage in your configuration:
#
# # In your flake or configuration, define your ports:
# let
# m3taLib = inputs.m3ta-nixpkgs.lib.${system};
#
# myPorts = {
# ports = {
# nginx = 80;
# grafana = 3000;
# prometheus = 9090;
# homepage = 8080;
# };
# hostPorts = {
# laptop = {
# nginx = 8080; # Override nginx port on laptop
# };
# server = {
# homepage = 3001; # Override homepage port on server
# };
# };
# };
#
# portHelpers = m3taLib.ports.mkPortHelpers myPorts;
# in {
# # Use in your config:
# services.nginx.port = portHelpers.getPort "nginx" "laptop";
# # Returns: 8080 (host-specific override)
#
# services.grafana.port = portHelpers.getPort "grafana" "laptop";
# # Returns: 3000 (default port)
#
# # Get all ports for a specific host (defaults + overrides):
# allLaptopPorts = portHelpers.getHostPorts "laptop";
# # Returns: { nginx = 8080; grafana = 3000; prometheus = 9090; homepage = 8080; }
# }
{lib}: {
# Create port helper functions from a ports configuration
#
# Args:
# portsConfig: An attribute set with structure:
# {
# ports = { service-name = port-number; ... };
# hostPorts = { hostname = { service-name = port-number; ... }; ... };
# }
#
# Returns:
# An attribute set containing helper functions:
# - getPort: Get port for a service with optional host override
# - getHostPorts: Get all ports for a specific host
# - listServices: List all defined services
mkPortHelpers = portsConfig: let
ports = portsConfig.ports or {};
hostPorts = portsConfig.hostPorts or {};
in {
# Get port for a service, with optional host-specific override
#
# Args:
# service: The service name (string)
# host: The hostname (string)
#
# Returns:
# Port number (int) or null if service not found
#
# Example:
# getPort "nginx" "laptop" # Returns host-specific port if defined
# getPort "nginx" null # Returns default port
getPort = service: host:
if host != null && hostPorts ? ${host} && hostPorts.${host} ? ${service}
then hostPorts.${host}.${service}
else ports.${service} or null;
# Get all ports for a specific host (merges defaults with host overrides)
#
# Args:
# host: The hostname (string)
#
# Returns:
# Attribute set of all ports for the host
#
# Example:
# getHostPorts "laptop" # { nginx = 8080; grafana = 3000; ... }
getHostPorts = host:
ports // (hostPorts.${host} or {});
# List all defined service names
#
# Returns:
# List of service names (strings)
listServices = lib.attrNames ports;
};
# Simple helper to get a port without host override
# Useful when you don't need host-specific ports
#
# Args:
# portsConfig: Same structure as mkPortHelpers
# service: The service name (string)
#
# Returns:
# Port number (int) or null if service not found
#
# Example:
# getDefaultPort myPorts "nginx" # Returns default port only
getDefaultPort = portsConfig: service:
portsConfig.ports.${service} or null;
}
+74
View File
@@ -0,0 +1,74 @@
# Home Manager Modules
User-level configuration modules organized by functional category.
## Structure
```
home-manager/
├── default.nix # Aggregator: imports all categories + ports.nix
├── ports.nix # Port management (HM-specific: generateEnvVars)
├── cli/ # Terminal/CLI tools
│ ├── default.nix # Category aggregator
│ └── zellij-ps.nix
└── coding/ # Development tools
├── default.nix # Category aggregator
└── editors.nix # Neovim + Zed configs
```
## Where to Look
| Task | Location |
|------|----------|
| Add CLI module | `cli/<name>.nix`, import in `cli/default.nix` |
| Add coding module | `coding/<name>.nix`, import in `coding/default.nix` |
| Add new category | Create `<category>/default.nix`, import in root `default.nix` |
| Module with host ports | Import `../../lib/ports.nix`, use `mkPortHelpers` |
## Option Namespaces
- `cli.*` - CLI tools (e.g., `cli.zellij-ps.enable`)
- `coding.editors.*` - Editor configs (e.g., `coding.editors.neovim.enable`)
- `m3ta.ports.*` - Port management (shared with NixOS)
## Patterns
**Category aggregator** (`cli/default.nix`):
```nix
{
imports = [
./zellij-ps.nix
# Add new modules here
];
}
```
**Simple module** (zellij-ps):
```nix
options.cli.zellij-ps = {
enable = mkEnableOption "...";
projectFolders = mkOption { type = types.listOf types.path; ... };
};
config = mkIf cfg.enable {
home.packages = [ pkgs.zellij-ps ];
home.sessionVariables.PROJECT_FOLDERS = ...;
};
```
**Multi-config module** (editors.nix):
```nix
config = mkMerge [
(mkIf cfg.neovim.enable { programs.neovim = {...}; })
(mkIf cfg.zed.enable { programs.zed-editor = {...}; })
(mkIf (cfg.neovim.enable || cfg.zed.enable) { home.packages = [...]; })
];
```
## HM vs NixOS Differences
| Feature | Home Manager | NixOS |
|---------|--------------|-------|
| `currentHost` default | `null` (must set) | `config.networking.hostName` |
| `generateEnvVars` | Available | Not available |
| Output file | `~/.config/m3ta/ports.json` | `/etc/m3ta/ports.json` |
| Package access | `pkgs.*` via overlay | `pkgs.*` via overlay |
+8
View File
@@ -0,0 +1,8 @@
# CLI/Terminal-related Home Manager modules
{
imports = [
./rofi-project-opener.nix
./stt-ptt.nix
./zellij-ps.nix
];
}
@@ -0,0 +1,134 @@
{
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.cli.rofi-project-opener;
# Project directory submodule type
projectDirType = types.submodule {
options = {
path = mkOption {
type = types.str;
description = "Base directory path to scan for project subdirectories.";
example = "~/dev";
};
args = mkOption {
type = types.str;
default = "";
description = "Additional arguments to pass to opencode when launching projects from this directory.";
example = "--agent Planner-Sisyphus";
};
};
};
# Convert projectDirs attrset to JSON for config file
projectDirsJson = builtins.toJSON (
mapAttrs (name: value: {
path = value.path;
args = value.args;
})
cfg.projectDirs
);
in {
options.cli.rofi-project-opener = {
enable = mkEnableOption "Rofi-based project directory launcher";
projectDirs = mkOption {
type = types.attrsOf projectDirType;
default = {
dev = {path = "~/dev";};
projects = {path = "~/projects";};
};
description = ''
Attribute set of base directories to scan for project subdirectories.
Each directory will be scanned for immediate subdirectories (non-hidden).
Projects are displayed as "base_dir/project_name" in rofi.
Each entry can specify:
- path: Base directory path (supports ~ for home directory)
- args: Optional arguments to pass to opencode for projects in this directory
'';
example = literalExpression ''
{
nixpkgs = { path = "~/p/NIX/nixpkgs"; args = "--agent Planner-Sisyphus"; };
dev = { path = "~/dev"; };
work = { path = "~/work"; args = "--agent work-agent"; };
}
'';
};
terminal = mkOption {
type = types.either types.str types.package;
default = "kitty";
description = "Terminal emulator to use for launching opencode. Can be a string or package.";
example = literalExpression "pkgs.alacritty";
};
terminalCommand = mkOption {
type = types.str;
default = "";
description = ''
Custom command to run in the terminal.
Placeholders:
- %s = project path
- %a = project args (from projectDirs.<name>.args)
If empty, defaults to: cd to project, run "opencode %a"
Examples:
- "" (empty) - Uses default: cd to project, run opencode with args
- "opencode %a" - Run opencode with project-specific args
- "nvim" - Open editor (no args)
- "myapp %s %a" - Custom app with path and args
'';
example = literalExpression ''"opencode %a"'';
};
rofiPrompt = mkOption {
type = types.str;
default = "Select project";
description = "Prompt text displayed in rofi.";
example = "Open project:";
};
rofiArgs = mkOption {
type = types.listOf types.str;
default = ["-dmenu" "-i"];
description = ''
Arguments to pass to rofi.
Common options:
- "-dmenu" - Enable dmenu mode (required)
- "-i" - Case-insensitive matching
- "-theme <theme>" - Use specific rofi theme
- "-width <percentage>" - Window width
- "-lines <number>" - Number of visible lines
'';
example = literalExpression ''["-dmenu" "-i" "-theme gruvbox"]'';
};
};
config = mkIf cfg.enable {
home.packages = [pkgs.rofi-project-opener];
# Write JSON config file for project directories
xdg.configFile."rofi-project-opener/projects.json".text = projectDirsJson;
# Write shell config file for other settings
xdg.configFile."rofi-project-opener/config".text = ''
# rofi-project-opener configuration
TERMINAL="${
if isDerivation cfg.terminal
then "${cfg.terminal}/bin/${cfg.terminal.pname or (builtins.baseNameOf (toString cfg.terminal))}"
else cfg.terminal
}"
${optionalString (cfg.terminalCommand != "") ''TERMINAL_CMD="${cfg.terminalCommand}"''}
ROFI_PROMPT="${cfg.rofiPrompt}"
ROFI_ARGS="${escapeShellArgs cfg.rofiArgs}"
'';
};
}
+158
View File
@@ -0,0 +1,158 @@
{
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.cli.stt-ptt;
# Build stt-ptt package with the selected whisper package
sttPttPackage = pkgs.stt-ptt.override {
whisper-cpp = cfg.whisperPackage;
};
modelDir = "${config.xdg.dataHome}/stt-ptt/models";
modelPath = "${modelDir}/${cfg.model}.bin";
# HuggingFace URL for whisper.cpp models
modelUrl = "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/${cfg.model}.bin";
in {
options.cli.stt-ptt = {
enable = mkEnableOption "Push to Talk Speech to Text using Whisper";
whisperPackage = mkOption {
type = types.package;
default = pkgs.whisper-cpp;
description = ''
The whisper-cpp package to use. Available options:
Pre-built variants:
- `pkgs.whisper-cpp` - CPU-based inference (default)
- `pkgs.whisper-cpp-vulkan` - Vulkan GPU acceleration
Override options (can be combined):
- `cudaSupport` - NVIDIA CUDA support
- `rocmSupport` - AMD ROCm support
- `vulkanSupport` - Vulkan support
- `coreMLSupport` - Apple CoreML (macOS only)
- `metalSupport` - Apple Metal (macOS ARM only)
Example overrides:
- `pkgs.whisper-cpp.override { cudaSupport = true; }` - NVIDIA GPU
- `pkgs.whisper-cpp.override { rocmSupport = true; }` - AMD GPU
- `pkgs.whisper-cpp.override { vulkanSupport = true; }` - Vulkan
'';
example = literalExpression "pkgs.whisper-cpp.override { cudaSupport = true; }";
};
model = mkOption {
type = types.str;
default = "ggml-large-v3-turbo";
description = ''
The Whisper model to use. Models are downloaded from HuggingFace.
Available models (sorted by size/quality):
- `ggml-tiny` / `ggml-tiny.en` - 75MB, fastest, lowest quality
- `ggml-base` / `ggml-base.en` - 142MB, fast, basic quality
- `ggml-small` / `ggml-small.en` - 466MB, balanced
- `ggml-medium` / `ggml-medium.en` - 1.5GB, good quality
- `ggml-large-v1` - 2.9GB, high quality (original)
- `ggml-large-v2` - 2.9GB, high quality (improved)
- `ggml-large-v3` - 2.9GB, highest quality
- `ggml-large-v3-turbo` - 1.6GB, high quality, optimized speed (recommended)
Models ending in `.en` are English-only and slightly faster for English.
Quantized versions (q5_0, q5_1, q8_0) are also available for reduced size.
'';
example = "ggml-base.en";
};
notifyTimeout = mkOption {
type = types.int;
default = 3000;
description = ''
Notification timeout in milliseconds for the recording indicator.
Set to 0 for persistent notifications.
'';
example = 5000;
};
language = mkOption {
type = types.enum [
"auto"
"en"
"es"
"fr"
"de"
"it"
"pt"
"ru"
"zh"
"ja"
"ko"
"ar"
"hi"
"tr"
"pl"
"nl"
"sv"
"da"
"fi"
"no"
"vi"
"th"
"id"
"uk"
"cs"
];
default = "auto";
description = ''
Language for speech recognition. Use "auto" for automatic language detection,
or specify a language code (ISO 639-1 standard) for better accuracy.
Auto-detection analyzes the audio to determine the spoken language automatically.
Specifying a language can improve accuracy if you know the language in advance.
Common language codes:
- en: English
- es: Spanish
- fr: French
- de: German
- zh: Chinese
- ja: Japanese
- ko: Korean
whisper.cpp supports 100+ languages. See whisper.cpp documentation for the full list.
'';
example = "en";
};
};
config = mkIf cfg.enable {
home.packages = [sttPttPackage];
home.sessionVariables = {
STT_MODEL = modelPath;
STT_LANGUAGE = cfg.language;
STT_NOTIFY_TIMEOUT = toString cfg.notifyTimeout;
};
# Create model directory and download model if not present
home.activation.downloadWhisperModel = lib.hm.dag.entryAfter ["writeBoundary"] ''
MODEL_DIR="${modelDir}"
MODEL_PATH="${modelPath}"
MODEL_URL="${modelUrl}"
$DRY_RUN_CMD mkdir -p "$MODEL_DIR"
if [ ! -f "$MODEL_PATH" ]; then
echo "Downloading Whisper model: ${cfg.model}..."
$DRY_RUN_CMD ${pkgs.curl}/bin/curl -L -o "$MODEL_PATH" "$MODEL_URL" || {
echo "Failed to download model from $MODEL_URL"
echo "Please download manually and place at: $MODEL_PATH"
}
fi
'';
};
}
+45
View File
@@ -0,0 +1,45 @@
{
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.cli.zellij-ps;
in {
options.cli.zellij-ps = {
enable = mkEnableOption "Zellij Project Selector";
projectFolders = mkOption {
type = types.listOf types.path;
description = "List of project folders for zellij-ps.";
default = ["${config.home.homeDirectory}/projects"];
};
layout = mkOption {
type = types.str;
description = "Layout for zellij";
default = ''
layout {
pane size=1 borderless=true {
plugin location="zellij:tab-bar"
}
pane
pane split_direction="vertical" {
pane
pane command="htop"
}
pane size=2 borderless=true {
plugin location="zellij:status-bar"
}
}
'';
};
};
config = mkIf cfg.enable {
home.packages = [pkgs.zellij-ps];
home.sessionVariables.PROJECT_FOLDERS = lib.concatStringsSep ":" cfg.projectFolders;
home.file.".config/zellij/layouts/zellij-ps.kdl".text = cfg.layout;
};
}
+6
View File
@@ -0,0 +1,6 @@
# Coding-related Home Manager modules
{
imports = [
./editors.nix
];
}
+199
View File
@@ -0,0 +1,199 @@
{
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.coding.editors;
in {
options.coding.editors = {
neovim = {
enable = mkEnableOption "neovim with LazyVim configuration";
};
zed = {
enable = mkEnableOption "zed editor with custom configuration";
};
};
config = mkMerge [
# Neovim configuration
(mkIf cfg.neovim.enable {
programs.neovim = {
enable = true;
defaultEditor = true;
viAlias = true;
vimAlias = true;
vimdiffAlias = true;
withNodeJs = true;
withPython3 = true;
# This is your init.lua content (extraLuaConfig for compatibility with older home-manager)
extraLuaConfig = ''
-- Bootstrap lazy.nvim
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
vim.fn.system({
"git",
"clone",
"--filter=blob:none",
"https://github.com/folke/lazy.nvim.git",
"--branch=stable",
lazypath,
})
end
vim.opt.rtp:prepend(lazypath)
-- Bootstrap LazyVim via lazy.nvim
-- Docs: https://github.com/folke/lazy.nvim and https://www.lazyvim.org/
require("lazy").setup({
spec = {
{ "LazyVim/LazyVim", import = "lazyvim.plugins" },
{ import = "lazyvim.plugins.extras.lang.typescript" },
{ import = "lazyvim.plugins.extras.lang.python" },
{ import = "lazyvim.plugins.extras.lang.go" },
{ import = "lazyvim.plugins.extras.lang.nix" },
{ import = "lazyvim.plugins.extras.lang.rust" },
{ import = "lazyvim.plugins.extras.lang.nushell" },
{ "Mofiqul/dracula.nvim" },
},
defaults = { lazy = false, version = false },
install = { colorscheme = { "dracula", "tokyonight", "habamax" } },
checker = { enabled = false },
performance = {
rtp = {
disabled_plugins = {
"gzip", "tarPlugin", "tohtml", "tutor", "zipPlugin",
},
},
},
})
vim.o.termguicolors = true
vim.cmd.colorscheme("dracula")
'';
};
})
# Zed editor configuration
(mkIf cfg.zed.enable {
programs.zed-editor = {
enable = true;
userSettings = {
# UI and Theme
theme = "Dracula";
ui_font_size = 16;
buffer_font_size = 16;
buffer_font_family = "FiraCode Nerd Font";
# Editor Behavior
vim_mode = true;
auto_update = false;
format_on_save = "on";
load_direnv = "shell_hook";
# AI Features
features = {
edit_prediction_provider = "zed";
};
edit_predictions = {
mode = "subtle";
};
show_edit_predictions = true;
agent = {
default_model = {
provider = "zed.dev";
model = "claude-sonnet-4";
};
};
assistant = {
version = "2";
default_model = {
provider = "anthropic";
model = "claude-4";
};
};
# Language Models
language_models = {
anthropic = {
api_url = "https://api.anthropic.com";
};
openai = {
api_url = "https://api.openai.com/v1";
};
ollama = {
api_url = "http://localhost:11434";
};
};
# Languages Configuration
languages = {
Nix = {
language_servers = ["nixd"];
formatter = {
external = {
command = "alejandra";
arguments = [
"-q"
"-"
];
};
};
};
Python = {
language_servers = ["pyrefly"];
formatter = {
external = {
command = "black";
arguments = ["-"];
};
};
};
};
# LSP Configuration
lsp = {
rust-analyzer = {
initialization_options = {
check = {
command = "clippy";
};
};
};
pyrefly = {
binary = {
arguments = ["--lsp"];
};
};
};
# Context Servers
context_servers = {
some-context-server = {
source = "custom";
command = "some-command";
args = [
"arg-1"
"arg-2"
];
env = {};
};
};
# Privacy
telemetry = {
metrics = false;
};
};
};
})
# Common packages (always installed if either editor is enabled)
(mkIf (cfg.neovim.enable || cfg.zed.enable) {
home.packages = with pkgs; [zig];
})
];
}
+8
View File
@@ -0,0 +1,8 @@
# Home Manager modules organized by category
{
imports = [
./cli
./coding
./ports.nix
];
}
+159
View File
@@ -0,0 +1,159 @@
# Home Manager Module for Port Management
#
# This module provides centralized port management for Home Manager configurations.
# Define ports once and use them consistently across user services, with support
# for host-specific overrides.
#
# Usage in your Home Manager configuration:
#
# # In your home.nix or flake:
# imports = [ inputs.m3ta-nixpkgs.homeManagerModules.default ];
#
# m3ta.ports = {
# enable = true;
#
# # Define your default ports
# definitions = {
# vscodium = 8080;
# jupyter = 8888;
# dev-server = 3000;
# local-api = 8000;
# docs-preview = 4000;
# };
#
# # Define host-specific overrides
# hostOverrides = {
# laptop = {
# dev-server = 3001;
# vscodium = 8081;
# };
# desktop = {
# jupyter = 9999;
# };
# };
#
# # Set the current hostname
# currentHost = "laptop"; # Or use config.networking.hostName if available
# };
#
# # Use ports in your configuration:
# home.file.".config/myapp/config.json".text = builtins.toJSON {
# port = config.m3ta.ports.get "dev-server";
# };
#
# # Generate environment variables:
# home.sessionVariables = {
# DEV_SERVER_PORT = toString (config.m3ta.ports.get "dev-server");
# JUPYTER_PORT = toString (config.m3ta.ports.get "jupyter");
# };
{
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.m3ta.ports;
portsLib = import ../../lib/ports.nix {inherit lib;};
portHelpers =
if cfg.enable
then
portsLib.mkPortHelpers {
ports = cfg.definitions;
hostPorts = cfg.hostOverrides;
}
else null;
in {
options.m3ta.ports = {
enable = mkEnableOption "centralized port management for Home Manager";
definitions = mkOption {
type = types.attrsOf types.port;
default = {};
description = "Default port definitions for user services.";
};
hostOverrides = mkOption {
type = types.attrsOf (types.attrsOf types.port);
default = {};
description = "Host-specific port overrides.";
};
currentHost = mkOption {
type = types.nullOr types.str;
default = null;
description = "Hostname to use for port resolution.";
};
# Internal computed options
get = mkOption {
type = types.raw;
readOnly = true;
internal = true;
};
getForHost = mkOption {
type = types.raw;
readOnly = true;
internal = true;
};
all = mkOption {
type = types.attrsOf types.port;
readOnly = true;
internal = true;
};
allForHost = mkOption {
type = types.raw;
readOnly = true;
internal = true;
};
services = mkOption {
type = types.listOf types.str;
readOnly = true;
internal = true;
};
# Env var generation
generateEnvVars = mkOption {
type = types.bool;
default = false;
description = "Generate environment variables for all ports.";
};
envVarPrefix = mkOption {
type = types.str;
default = "PORT_";
description = "Prefix for generated environment variables.";
};
};
config = mkIf cfg.enable {
m3ta.ports.get = service: portHelpers.getPort service cfg.currentHost;
m3ta.ports.getForHost = host: service: portHelpers.getPort service host;
m3ta.ports.all = portHelpers.getHostPorts cfg.currentHost;
m3ta.ports.allForHost = portHelpers.getHostPorts;
m3ta.ports.services = portHelpers.listServices;
home.sessionVariables = mkIf cfg.generateEnvVars (
let
toEnvVarName = service:
cfg.envVarPrefix + (lib.toUpper (builtins.replaceStrings ["-"] ["_"] service));
in
builtins.listToAttrs (
map (service: {
name = toEnvVarName service;
value = toString (cfg.get service);
})
cfg.services
)
);
home.file.".config/m3ta/ports.json".text = builtins.toJSON {
hostname = cfg.currentHost;
ports = cfg.all;
allDefinitions = cfg.definitions;
hostOverrides = cfg.hostOverrides;
};
};
}
+30
View File
@@ -0,0 +1,30 @@
# NixOS Modules
# Import this in your NixOS configuration with:
# imports = [ inputs.m3ta-nixpkgs.nixosModules.default ];
{
config,
lib,
pkgs,
...
}: {
# This is the main entry point for all custom NixOS modules
# Add your custom modules here as imports or inline definitions
imports = [
./mem0.nix
./ports.nix
# Example: ./my-service.nix
# Add more module files here as you create them
];
# You can also define inline options here
# options = {
# m3ta = {
# # Your custom options
# };
# };
# config = {
# # Your custom configuration
# };
}
+363
View File
@@ -0,0 +1,363 @@
# NixOS Module for Mem0 REST API Server
#
# This module provides a systemd service for the Mem0 REST API server,
# allowing you to run mem0 as a system service with configurable vector storage.
#
# Usage in your NixOS configuration:
#
# # In your flake.nix or configuration.nix:
# imports = [ inputs.m3ta-nixpkgs.nixosModules.default ];
#
# m3ta.mem0 = {
# enable = true;
# port = 8000;
# host = "127.0.0.1";
#
# # LLM Configuration
# llm = {
# provider = "openai";
# apiKeyFile = "/run/secrets/openai-api-key"; # Use agenix or sops-nix
# model = "gpt-4";
# };
#
# # Vector Storage Configuration
# vectorStore = {
# provider = "qdrant"; # or "chroma", "pinecone", etc.
# config = {
# host = "localhost";
# port = 6333;
# };
# };
#
# # Optional: Environment variables
# environmentFile = "/etc/mem0/environment";
# };
#
# Using with m3ta.ports (recommended):
#
# m3ta.ports = {
# enable = true;
# definitions = { mem0 = 8000; };
# hostOverrides.laptop = { mem0 = 8080; };
# currentHost = config.networking.hostName;
# };
#
# m3ta.mem0 = {
# enable = true;
# port = config.m3ta.ports.get "mem0"; # Automatically uses host-specific port
# };
{
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.m3ta.mem0;
# Python environment with mem0
pythonEnv = pkgs.python3.withPackages (ps:
with ps; [
cfg.package
]);
# Convert vector store config to environment variables
vectorStoreEnv =
if cfg.vectorStore.provider == "qdrant"
then {
MEM0_VECTOR_PROVIDER = "qdrant";
QDRANT_HOST = cfg.vectorStore.config.host or "localhost";
QDRANT_PORT = toString (cfg.vectorStore.config.port or 6333);
QDRANT_COLLECTION = cfg.vectorStore.config.collection_name or "mem0_memories";
}
else if cfg.vectorStore.provider == "pgvector"
then {
MEM0_VECTOR_PROVIDER = "pgvector";
POSTGRES_HOST = cfg.vectorStore.config.host or "localhost";
POSTGRES_PORT = toString (cfg.vectorStore.config.port or 5432);
POSTGRES_DB = cfg.vectorStore.config.dbname or "postgres";
POSTGRES_USER = cfg.vectorStore.config.user or "postgres";
POSTGRES_PASSWORD = cfg.vectorStore.config.password or "postgres";
POSTGRES_COLLECTION = cfg.vectorStore.config.collection_name or "mem0_memories";
}
else if cfg.vectorStore.provider == "chroma"
then {
MEM0_VECTOR_PROVIDER = "chroma";
CHROMA_HOST = cfg.vectorStore.config.host or "localhost";
CHROMA_PORT = toString (cfg.vectorStore.config.port or 8000);
CHROMA_COLLECTION = cfg.vectorStore.config.collection_name or "mem0_memories";
}
else {};
# Start script that sets up environment and runs the server
startScript = pkgs.writeShellScript "mem0-start" ''
set -e
# Load environment file if specified
${optionalString (cfg.environmentFile != null) ''
if [ -f "${cfg.environmentFile}" ]; then
set -a
source "${cfg.environmentFile}"
set +a
fi
''}
# Load API key from file if specified
${optionalString (cfg.llm.apiKeyFile != null) ''
if [ -f "${cfg.llm.apiKeyFile}" ]; then
export OPENAI_API_KEY="$(cat ${cfg.llm.apiKeyFile})"
fi
''}
# Create state directory
mkdir -p ${cfg.stateDir}
cd ${cfg.stateDir}
# Run the server
exec ${pythonEnv}/bin/mem0-server
'';
in {
options.m3ta.mem0 = {
enable = mkEnableOption "Mem0 REST API server";
package = mkOption {
type = types.package;
default = pkgs.mem0;
defaultText = literalExpression "pkgs.mem0";
description = "The mem0 package to use.";
};
host = mkOption {
type = types.str;
default = "127.0.0.1";
description = "Host address to bind the server to.";
};
port = mkOption {
type = types.port;
default = 8000;
description = "Port to run the REST API server on.";
};
workers = mkOption {
type = types.int;
default = 1;
description = "Number of worker processes.";
};
logLevel = mkOption {
type = types.enum ["critical" "error" "warning" "info" "debug" "trace"];
default = "info";
description = "Logging level for the server.";
};
stateDir = mkOption {
type = types.path;
default = "/var/lib/mem0";
description = "Directory to store mem0 data and state.";
};
user = mkOption {
type = types.str;
default = "mem0";
description = "User account under which mem0 runs.";
};
group = mkOption {
type = types.str;
default = "mem0";
description = "Group under which mem0 runs.";
};
environmentFile = mkOption {
type = types.nullOr types.path;
default = null;
description = ''
Environment file containing additional configuration.
This file should contain KEY=value pairs, one per line.
Useful for secrets that shouldn't be in the Nix store.
'';
example = "/etc/mem0/environment";
};
# LLM Configuration
llm = {
provider = mkOption {
type = types.enum ["openai" "anthropic" "azure" "groq" "together" "ollama" "litellm"];
default = "openai";
description = "LLM provider to use for memory operations.";
};
model = mkOption {
type = types.str;
default = "gpt-4o-mini";
description = "Model name to use for the LLM.";
};
apiKeyFile = mkOption {
type = types.nullOr types.path;
default = null;
description = ''
Path to file containing the API key for the LLM provider.
The file should contain only the API key.
This is more secure than putting the key in the Nix store.
'';
example = "/run/secrets/openai-api-key";
};
temperature = mkOption {
type = types.nullOr types.float;
default = null;
description = "Temperature parameter for LLM generation.";
};
maxTokens = mkOption {
type = types.nullOr types.int;
default = null;
description = "Maximum tokens for LLM generation.";
};
extraConfig = mkOption {
type = types.attrs;
default = {};
description = "Additional LLM configuration options.";
example = {
top_p = 1.0;
frequency_penalty = 0.0;
};
};
};
# Vector Store Configuration
vectorStore = {
provider = mkOption {
type = types.enum [
"qdrant"
"chroma"
"pinecone"
"weaviate"
"faiss"
"pgvector"
"redis"
"elasticsearch"
"milvus"
];
default = "qdrant";
description = "Vector database provider to use.";
};
config = mkOption {
type = types.attrs;
default = {};
description = ''
Configuration for the vector store.
The structure depends on the provider.
'';
example = literalExpression ''
{
host = "localhost";
port = 6333;
collection_name = "mem0_memories";
}
'';
};
};
# Embedder Configuration
embedder = {
provider = mkOption {
type = types.nullOr (types.enum ["openai" "huggingface" "ollama" "vertexai"]);
default = null;
description = "Embedding model provider. If null, uses default.";
};
model = mkOption {
type = types.nullOr types.str;
default = null;
description = "Embedding model name to use.";
example = "text-embedding-3-small";
};
config = mkOption {
type = types.attrs;
default = {};
description = "Configuration for the embedder.";
example = {
model = "text-embedding-3-small";
};
};
};
};
config = mkIf cfg.enable {
# Create user and group
users.users.${cfg.user} = {
isSystemUser = true;
group = cfg.group;
description = "Mem0 service user";
home = cfg.stateDir;
createHome = true;
};
users.groups.${cfg.group} = {};
# Systemd service
systemd.services.mem0 = {
description = "Mem0 REST API Server";
after = ["network.target"];
wantedBy = ["multi-user.target"];
serviceConfig = {
Type = "simple";
User = cfg.user;
Group = cfg.group;
ExecStart = startScript;
Restart = "on-failure";
RestartSec = "5s";
# Security hardening
NoNewPrivileges = true;
PrivateTmp = true;
ProtectSystem = "strict";
ProtectHome = true;
ReadWritePaths = [cfg.stateDir];
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectControlGroups = true;
RestrictRealtime = true;
RestrictNamespaces = true;
LockPersonality = true;
MemoryDenyWriteExecute = false; # Python needs this
RestrictAddressFamilies = ["AF_UNIX" "AF_INET" "AF_INET6"];
};
environment =
{
PYTHONUNBUFFERED = "1";
MEM0_HOST = cfg.host;
MEM0_PORT = toString cfg.port;
MEM0_LLM_PROVIDER = cfg.llm.provider;
MEM0_LLM_MODEL = cfg.llm.model;
MEM0_HISTORY_DB_PATH = "${cfg.stateDir}/history.db";
MEM0_WORKERS = toString cfg.workers;
MEM0_LOG_LEVEL = cfg.logLevel;
}
// optionalAttrs (cfg.llm.temperature != null) {
MEM0_LLM_TEMPERATURE = toString cfg.llm.temperature;
}
// optionalAttrs (cfg.llm.extraConfig != {}) {
MEM0_LLM_EXTRA_CONFIG = builtins.toJSON cfg.llm.extraConfig;
}
// optionalAttrs (cfg.embedder.provider != null) {
MEM0_EMBEDDER_PROVIDER = cfg.embedder.provider;
}
// optionalAttrs (cfg.embedder.model != null) {
MEM0_EMBEDDER_MODEL = cfg.embedder.model;
}
// vectorStoreEnv;
};
# Open firewall port if binding to non-localhost
networking.firewall.allowedTCPPorts = mkIf (cfg.host != "127.0.0.1" && cfg.host != "localhost") [cfg.port];
};
}
+124
View File
@@ -0,0 +1,124 @@
# NixOS Module for Port Management
#
# This module provides centralized port management across your NixOS systems.
# Define ports once and use them consistently across all services, with
# support for host-specific overrides.
#
# Usage in your NixOS configuration:
#
# # In your flake.nix or configuration.nix:
# imports = [ inputs.m3ta-nixpkgs.nixosModules.default ];
#
# m3ta.ports = {
# enable = true;
#
# # Define your default ports
# definitions = {
# nginx = 80;
# grafana = 3000;
# prometheus = 9090;
# homepage = 8080;
# ssh = 22;
# };
#
# # Define host-specific overrides
# hostOverrides = {
# laptop = {
# nginx = 8080; # Use non-privileged port on laptop
# ssh = 2222;
# };
# server = {
# homepage = 3001;
# };
# };
#
# # Optionally set the current hostname for automatic port resolution
# currentHost = config.networking.hostName;
# };
#
# # Use ports in your configuration:
# services.nginx.defaultHTTPListenPort = config.m3ta.ports.get "nginx";
# services.grafana.settings.server.http_port = config.m3ta.ports.get "grafana";
#
# # Or access all ports for the current host:
# environment.etc."my-ports.json".text = builtins.toJSON config.m3ta.ports.all;
{
config,
lib,
...
}:
with lib; let
cfg = config.m3ta.ports;
portsLib = import ../../lib/ports.nix {inherit lib;};
portHelpers =
if cfg.enable
then
portsLib.mkPortHelpers {
ports = cfg.definitions;
hostPorts = cfg.hostOverrides;
}
else null;
in {
options.m3ta.ports = {
enable = mkEnableOption "centralized port management";
definitions = mkOption {
type = types.attrsOf types.port;
default = {};
description = "Default port definitions for services.";
};
hostOverrides = mkOption {
type = types.attrsOf (types.attrsOf types.port);
default = {};
description = "Host-specific port overrides.";
};
currentHost = mkOption {
type = types.str;
default = config.networking.hostName;
description = "Hostname to use for port resolution.";
};
# Internal computed options
get = mkOption {
type = types.raw;
readOnly = true;
internal = true;
};
getForHost = mkOption {
type = types.raw;
readOnly = true;
internal = true;
};
all = mkOption {
type = types.attrsOf types.port;
readOnly = true;
internal = true;
};
allForHost = mkOption {
type = types.raw;
readOnly = true;
internal = true;
};
services = mkOption {
type = types.listOf types.str;
readOnly = true;
internal = true;
};
};
config = mkIf cfg.enable {
m3ta.ports.get = service: portHelpers.getPort service cfg.currentHost;
m3ta.ports.getForHost = host: service: portHelpers.getPort service host;
m3ta.ports.all = portHelpers.getHostPorts cfg.currentHost;
m3ta.ports.allForHost = portHelpers.getHostPorts;
m3ta.ports.services = portHelpers.listServices;
};
}
+70
View File
@@ -0,0 +1,70 @@
{inputs, ...}: {
# This one brings our custom packages from the 'pkgs' directory
additions = final: prev:
(import ../pkgs {pkgs = final;})
# // (inputs.hyprpanel.overlay final prev)
// {rose-pine-hyprcursor = inputs.rose-pine-hyprcursor.packages.${prev.system}.default;};
# This one contains whatever you want to overlay
# You can change versions, add patches, set compilation flags, anything really.
# https://nixos.wiki/wiki/Overlays
modifications = final: prev:
# Import all package modifications from mods directory
(import ./mods/default.nix {inherit prev;})
// {
# Direct configuration overrides
brave = prev.brave.override {
commandLineArgs = "--password-store=gnome-libsecret";
};
# nodejs_24 = inputs.nixpkgs-stable.legacyPackages.${prev.system}.nodejs_24;
# paperless-ngx = inputs.nixpkgs-45570c2.legacyPackages.${prev.system}.paperless-ngx;
# anytype-heart = inputs.nixpkgs-9e58ed7.legacyPackages.${prev.system}.anytype-heart;
# trezord = inputs.nixpkgs-2744d98.legacyPackages.${prev.system}.trezord;
# mesa = inputs.nixpkgs-master.legacyPackages.${prev.system}.mesa;
# hyprpanel = inputs.hyprpanel.packages.${prev.system}.default.overrideAttrs (prev: {
# version = "latest"; # or whatever version you want
# src = final.fetchFromGitHub {
# owner = "Jas-SinghFSU";
# repo = "HyprPanel";
# rev = "master"; # or a specific commit hash
# hash = "sha256-l623fIVhVCU/ylbBmohAtQNbK0YrWlEny0sC/vBJ+dU=";
# };
# });
};
temp-packages = final: _prev: {
temp = import inputs.nixpkgs-9e9486b {
system = final.system;
config.allowUnfree = true;
};
};
stable-packages = final: _prev: {
stable = import inputs.nixpkgs-stable {
system = final.system;
config.allowUnfree = true;
};
};
pinned-packages = final: _prev: {
pinned = import inputs.nixpkgs-9472de4 {
system = final.system;
config.allowUnfree = true;
};
};
locked-packages = final: _prev: {
locked = import inputs.nixpkgs-locked {
system = final.system;
config.allowUnfree = true;
};
};
master-packages = final: _prev: {
master = import inputs.nixpkgs-master {
system = final.system;
config.allowUnfree = true;
};
};
}
+16
View File
@@ -0,0 +1,16 @@
{prev}:
prev.beads.overrideAttrs (oldAttrs: rec {
version = "0.47.1";
src = prev.fetchFromGitHub {
owner = "steveyegge";
repo = "beads";
tag = "v${version}";
hash = "sha256-DwIR/r1TJnpVd/CT1E2OTkAjU7k9/KHbcVwg5zziFVg=";
};
vendorHash = "sha256-pY5m5ODRgqghyELRwwxOr+xlW41gtJWLXaW53GlLaFw=";
# Tests require git worktree operations that fail in Nix sandbox
doCheck = false;
})
+10
View File
@@ -0,0 +1,10 @@
{prev}: {
# Package modifications
# This overlay contains package overrides and modifications
# n8n = import ./n8n.nix {inherit prev;};
# beads = import ./beads.nix {inherit prev;};
# Add more modifications here as needed
# example-package = prev.example-package.override { ... };
}
+18
View File
@@ -0,0 +1,18 @@
{prev}:
prev.n8n.overrideAttrs (oldAttrs: rec {
version = "2.4.1";
src = prev.fetchFromGitHub {
owner = "n8n-io";
repo = "n8n";
rev = "n8n@${version}";
hash = "sha256-EQP9ZI8kt30SUYE1+/UUpxQXpavzKqDu8qE24zsNifg=";
};
pnpmDeps = prev.pnpm_10.fetchDeps {
pname = oldAttrs.pname;
inherit version src;
fetcherVersion = 1;
hash = "sha256-Q30IuFEQD3896Hg0HCLd38YE2i8fJn74JY0o95LKJis=";
};
})
+33
View File
@@ -0,0 +1,33 @@
# pkgs/ AGENTS.md
## OVERVIEW
Custom package registry using `callPackage` pattern for flake-wide availability.
## STRUCTURE
- `default.nix`: Central registry (entry point for overlays)
- `code2prompt/`: Rust package
- `hyprpaper-random/`: Bash script
- `launch-webapp/`: Webapp wrapper
- `mem0/`: Python package + custom `server.py`
- `msty-studio/`: AppImage wrapper
- `pomodoro-timer/`: Timer utility
- `tuxedo-backlight/`: Hardware control
- `zellij-ps/`: Gitea-hosted package
## WHERE TO LOOK
- **Register new pkg**: Add entry to `pkgs/default.nix` attribute set
- **Modify pkg**: Edit `pkgs/<name>/default.nix` (version, hash, deps)
- **Check visibility**: `nix flake show` (uses `pkgs/default.nix` via `overlays/default.nix`)
- **Add scripts**: Place alongside `default.nix` in package folder (e.g., `mem0/server.py`)
## CONVENTIONS
- **CallPackage**: Always use `pkgs.callPackage ./dir {}` in registry
- **Dir == Attr**: Package directory name MUST match its registry attribute
- **Path literals**: Reference local assets using `./file` within derivations
- **Self-contained**: Keep all package-specific files in their own directory
## ANTI-PATTERNS
- **Orphaned dirs**: Creating `pkgs/new-pkg/` without updating `pkgs/default.nix`
- **Direct flake imports**: Importing packages in `flake.nix` instead of through the registry
- **Implicit deps**: Not declaring dependencies in the package function arguments
- **Non-derivations**: Placing NixOS/HM modules here (use `modules/` instead)
+64
View File
@@ -0,0 +1,64 @@
{
lib,
stdenv,
buildGoModule,
fetchFromGitHub,
gitMinimal,
installShellFiles,
nix-update-script,
versionCheckHook,
writableTmpDirAsHomeHook,
}:
buildGoModule (finalAttrs: {
pname = "beads";
version = "0.56.1";
src = fetchFromGitHub {
owner = "steveyegge";
repo = "beads";
tag = "v${finalAttrs.version}";
hash = "sha256-hp+mKVCSzxxxUtOqspXuTbOJpeC8K9+UmmXSDr5Xa0k=";
};
vendorHash = "sha256-DlEnIVNLHWetwQxTmUNOAuDbHGZ9mmLdITwDdviphPs=";
subPackages = ["cmd/bd"];
ldflags = ["-s" "-w"];
nativeBuildInputs = [installShellFiles];
nativeCheckInputs = [gitMinimal writableTmpDirAsHomeHook];
# Skip security tests on Darwin - they check for /etc/passwd which isn't available in sandbox
checkFlags =
lib.optionals stdenv.hostPlatform.isDarwin
["-skip=TestCleanupMergeArtifacts_CommandInjectionPrevention"];
preCheck = ''
export PATH="$out/bin:$PATH"
'';
postInstall = lib.optionalString (stdenv.buildPlatform.canExecute stdenv.hostPlatform) ''
installShellCompletion --cmd bd \
--bash <($out/bin/bd completion bash) \
--fish <($out/bin/bd completion fish) \
--zsh <($out/bin/bd completion zsh)
'';
nativeInstallCheckInputs = [versionCheckHook writableTmpDirAsHomeHook];
versionCheckProgramArg = "version";
doInstallCheck = true;
doCheck = false;
passthru.updateScript = nix-update-script {};
meta = {
description = "Lightweight memory system for AI coding agents with graph-based issue tracking";
homepage = "https://github.com/steveyegge/beads";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [kedry];
mainProgram = "bd";
};
})
+40
View File
@@ -0,0 +1,40 @@
{
lib,
fetchFromGitHub,
nix-update-script,
rustPlatform,
pkg-config,
perl,
openssl,
}:
rustPlatform.buildRustPackage rec {
pname = "code2prompt";
version = "4.2.0";
src = fetchFromGitHub {
owner = "mufeedvh";
repo = "code2prompt";
rev = "v${version}";
hash = "sha256-Gh8SsSTZW7QlyyC3SWJ5pOK2x85/GT7+LPJn2Jeczpc=";
};
cargoLock = {
lockFile = src + "/Cargo.lock";
};
buildAndTestSubdir = "crates/code2prompt";
nativeBuildInputs = [pkg-config perl];
buildInputs = [openssl];
passthru.updateScript = nix-update-script {};
meta = with lib; {
description = "A CLI tool that converts your codebase into a single LLM prompt with a source tree, prompt templating, and token counting";
homepage = "https://github.com/mufeedvh/code2prompt";
license = licenses.mit;
platforms = platforms.linux;
mainProgram = "code2prompt";
};
}
+28
View File
@@ -0,0 +1,28 @@
{
pkgs,
inputs ? null,
...
}: {
# Custom packages registry
# Each package is defined in its own directory under pkgs/
beads = pkgs.callPackage ./beads {};
sidecar = pkgs.callPackage ./sidecar {};
td = pkgs.callPackage ./td {};
code2prompt = pkgs.callPackage ./code2prompt {};
hyprpaper-random = pkgs.callPackage ./hyprpaper-random {};
launch-webapp = pkgs.callPackage ./launch-webapp {};
mem0 = pkgs.callPackage ./mem0 {};
msty-studio = pkgs.callPackage ./msty-studio {};
notesmd-cli = pkgs.callPackage ./notesmd-cli {};
n8n = pkgs.callPackage ./n8n {};
pomodoro-timer = pkgs.callPackage ./pomodoro-timer {};
rofi-project-opener = pkgs.callPackage ./rofi-project-opener {};
stt-ptt = pkgs.callPackage ./stt-ptt {};
tuxedo-backlight = pkgs.callPackage ./tuxedo-backlight {};
zellij-ps = pkgs.callPackage ./zellij-ps {};
# Imported from flake inputs
opencode = inputs.opencode.packages.${pkgs.system}.opencode;
opencode-desktop = pkgs.callPackage ./opencode-desktop {inherit inputs;};
openspec = inputs.openspec.packages.${pkgs.system}.default;
}
+72
View File
@@ -0,0 +1,72 @@
{
lib,
stdenv,
writeShellScriptBin,
fd,
hyprland,
coreutils,
gawk,
}: let
script = writeShellScriptBin "hyprpaper-random" ''
#!/usr/bin/env bash
set -euo pipefail
# Directory (override with WALLPAPER_DIR)
DIR="''${WALLPAPER_DIR:-''${XDG_CONFIG_HOME:-$HOME/.config}/hypr/wallpapers}"
HYPRCTL="${hyprland}/bin/hyprctl"
FD="${fd}/bin/fd"
SHUF="${coreutils}/bin/shuf"
TR="${coreutils}/bin/tr"
AWK="${gawk}/bin/awk"
# Pick one random image (null-safe)
WALLPAPER="$(
"$FD" . "$DIR" -t f -e jpg -e jpeg -e png -e webp -e avif -0 --follow --hidden \
| "$SHUF" -z -n1 \
| "$TR" -d '\0'
)"
if [[ -z "''${WALLPAPER:-}" ]]; then
echo "No wallpapers found in: $DIR" >&2
exit 1
fi
# Preload so hyprpaper can use it
"$HYPRCTL" hyprpaper preload "$WALLPAPER" >/dev/null 2>&1 || true
# Apply to all monitors
"$HYPRCTL" monitors \
| "$AWK" '/^Monitor /{print $2}' \
| while IFS= read -r mon; do
[ -n "$mon" ] && "$HYPRCTL" hyprpaper wallpaper "$mon,$WALLPAPER"
done
exit 0
'';
in
stdenv.mkDerivation {
pname = "hyprpaper-random";
version = "0.1.1";
dontUnpack = true;
buildInputs = [
fd
hyprland
coreutils
gawk
];
installPhase = ''
mkdir -p "$out/bin"
ln -s ${script}/bin/hyprpaper-random "$out/bin/hyprpaper-random"
'';
meta = {
description = "Minimal random wallpaper setter for Hyprpaper";
license = lib.licenses.mit;
platforms = lib.platforms.linux;
mainProgram = "hyprpaper-random";
};
}
+41
View File
@@ -0,0 +1,41 @@
{
lib,
stdenv,
writeShellScriptBin,
}: let
launcher = writeShellScriptBin "launch-webapp" ''
#!/usr/bin/env bash
browser=$(xdg-settings get default-web-browser)
case "$browser" in
google-chrome*) browser_bin="google-chrome" ;;
brave-browser*) browser_bin="brave-browser" ;;
microsoft-edge*) browser_bin="microsoft-edge" ;;
opera*) browser_bin="opera" ;;
vivaldi*) browser_bin="vivaldi" ;;
*) browser_bin="chromium" ;;
esac
exec_cmd="/etc/profiles/per-user/$USER/bin/$browser_bin"
exec setsid uwsm app -- "$exec_cmd" --app="$1" ''${@:2}
'';
in
stdenv.mkDerivation {
pname = "launch-webapp";
version = "0.1.0";
dontUnpack = true;
installPhase = ''
mkdir -p $out/bin
ln -s ${launcher}/bin/launch-webapp $out/bin/launch-webapp
'';
meta = {
description = "Launches a web app using your default browser in app mode.";
license = lib.licenses.mit;
platforms = lib.platforms.linux;
mainProgram = "launch-webapp";
};
}
+102
View File
@@ -0,0 +1,102 @@
{
lib,
nix-update-script,
python3,
fetchFromGitHub,
}:
python3.pkgs.buildPythonPackage rec {
pname = "mem0ai";
version = "1.0.4";
pyproject = true;
src = fetchFromGitHub {
owner = "mem0ai";
repo = "mem0";
rev = "v${version}";
hash = "sha256-XH8yfv4K3mFOSbSOXgWxbDmEpPaMyU/H0rl88s6RpzI=";
};
# Relax Python dependency version constraints
# mem0 has strict version pins that may not match nixpkgs versions
pythonRelaxDeps = true;
build-system = with python3.pkgs; [
hatchling
];
dependencies = with python3.pkgs; [
litellm
qdrant-client
pydantic
openai
posthog
pytz
sqlalchemy
protobuf
uvicorn
fastapi
];
optional-dependencies = with python3.pkgs; {
graph = [
# Note: some graph dependencies may not be available in nixpkgs
# neo4j is available, others will need to be packaged separately
];
vector_stores = [
# chromadb # available in nixpkgs
# pinecone-client # may need packaging
# weaviate-client # may need packaging
# faiss # available as faiss-cpu
psycopg
pymongo
pymysql
redis
elasticsearch
];
llms = [
groq
openai
# together # may need packaging
# litellm # may need packaging
# ollama # may need packaging
# google-generativeai # may need packaging
];
extras = [
boto3
# langchain-community # may need packaging
# sentence-transformers # may need packaging
elasticsearch
# fastembed # may need packaging
];
};
# Skip tests for now since they require additional test dependencies
doCheck = false;
# Disable imports check because mem0 tries to create directories at import time
# which fails in the Nix sandbox (/homeless-shelter)
pythonImportsCheck = [];
postInstall = ''
install -Dm755 ${./server.py} $out/bin/mem0-server
'';
passthru.updateScript = nix-update-script {};
meta = with lib; {
description = "Long-term memory layer for AI agents with REST API support";
longDescription = ''
Mem0 provides a sophisticated memory layer for AI applications, offering:
- Memory management for AI agents (add, search, update, delete)
- REST API server for easy integration
- Support for multiple vector storage backends (Qdrant, Chroma, etc.)
- Graph memory capabilities
- Multi-modal support
- Configurable LLM and embedding models
'';
homepage = "https://github.com/mem0ai/mem0";
changelog = "https://github.com/mem0ai/mem0/releases/tag/v${version}";
license = licenses.asl20;
platforms = platforms.linux;
};
}
+301
View File
@@ -0,0 +1,301 @@
#!/usr/bin/env python3
"""
Mem0 REST API Server
A FastAPI-based REST server for mem0 memory operations.
"""
import logging
import os
import sys
from typing import Any, Dict, List, Optional
from fastapi import FastAPI, HTTPException
from fastapi.responses import JSONResponse, RedirectResponse
from pydantic import BaseModel, Field
from mem0 import Memory
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
# Configuration from environment variables
def get_config_from_env() -> Dict[str, Any]:
"""Build mem0 configuration from environment variables."""
config = {"version": "v1.1"}
# Vector store configuration
vector_provider = os.environ.get("MEM0_VECTOR_PROVIDER", "qdrant")
config["vector_store"] = {"provider": vector_provider}
if vector_provider == "qdrant":
config["vector_store"]["config"] = {
"host": os.environ.get("QDRANT_HOST", "localhost"),
"port": int(os.environ.get("QDRANT_PORT", "6333")),
"collection_name": os.environ.get("QDRANT_COLLECTION", "mem0_memories"),
}
elif vector_provider == "pgvector":
config["vector_store"]["config"] = {
"host": os.environ.get("POSTGRES_HOST", "localhost"),
"port": int(os.environ.get("POSTGRES_PORT", "5432")),
"dbname": os.environ.get("POSTGRES_DB", "postgres"),
"user": os.environ.get("POSTGRES_USER", "postgres"),
"password": os.environ.get("POSTGRES_PASSWORD", "postgres"),
"collection_name": os.environ.get("POSTGRES_COLLECTION", "mem0_memories"),
}
elif vector_provider == "chroma":
config["vector_store"]["config"] = {
"host": os.environ.get("CHROMA_HOST", "localhost"),
"port": int(os.environ.get("CHROMA_PORT", "8000")),
"collection_name": os.environ.get("CHROMA_COLLECTION", "mem0_memories"),
}
# LLM configuration
llm_provider = os.environ.get("MEM0_LLM_PROVIDER", "openai")
config["llm"] = {
"provider": llm_provider,
"config": {
"model": os.environ.get("MEM0_LLM_MODEL", "gpt-4o-mini"),
}
}
# Temperature: only include if set (null means use provider default)
temperature = os.environ.get("MEM0_LLM_TEMPERATURE")
if temperature is not None:
config["llm"]["config"]["temperature"] = float(temperature)
# Extra config: merge JSON env var if provided
extra_config_json = os.environ.get("MEM0_LLM_EXTRA_CONFIG")
if extra_config_json:
import json
try:
extra_config = json.loads(extra_config_json)
config["llm"]["config"].update(extra_config)
except json.JSONDecodeError:
logging.warning(f"Failed to parse MEM0_LLM_EXTRA_CONFIG: {extra_config_json}")
# Add API key if available
if llm_provider == "openai":
api_key = os.environ.get("OPENAI_API_KEY")
if api_key:
config["llm"]["config"]["api_key"] = api_key
# Embedder configuration
embedder_provider = os.environ.get("MEM0_EMBEDDER_PROVIDER", "openai")
config["embedder"] = {
"provider": embedder_provider,
}
# Embedder model: only include if provider is set
if embedder_provider:
embedder_config = {}
embedder_model = os.environ.get("MEM0_EMBEDDER_MODEL")
if embedder_model:
embedder_config["model"] = embedder_model
config["embedder"]["config"] = embedder_config
if embedder_provider == "openai":
api_key = os.environ.get("OPENAI_API_KEY")
if api_key:
config["embedder"]["config"]["api_key"] = api_key
# History DB path
history_db_path = os.environ.get("MEM0_HISTORY_DB_PATH", "/var/lib/mem0/history.db")
config["history_db_path"] = history_db_path
return config
# Initialize Memory instance
try:
config = get_config_from_env()
logging.info(f"Initializing mem0 with config: {config}")
# Validate API key is set for OpenAI provider
if config.get("llm", {}).get("provider") == "openai":
if not config.get("llm", {}).get("config", {}).get("api_key"):
logging.error("OPENAI_API_KEY environment variable is required but not set.")
logging.error("Please set OPENAI_API_KEY environment variable or configure apiKeyFile in NixOS module.")
sys.exit(1)
MEMORY_INSTANCE = Memory.from_config(config)
logging.info("Memory instance initialized successfully")
except Exception as e:
logging.error(f"Failed to initialize Memory: {e}")
logging.error("Please check your configuration and ensure all required services are running.")
sys.exit(1)
app = FastAPI(
title="Mem0 REST API",
description="A REST API for managing and searching memories for your AI Agents and Apps.",
version="1.0.0",
)
class Message(BaseModel):
role: str = Field(..., description="Role of the message (user or assistant).")
content: str = Field(..., description="Message content.")
class MemoryCreate(BaseModel):
messages: List[Message] = Field(..., description="List of messages to store.")
user_id: Optional[str] = None
agent_id: Optional[str] = None
run_id: Optional[str] = None
metadata: Optional[Dict[str, Any]] = None
class SearchRequest(BaseModel):
query: str = Field(..., description="Search query.")
user_id: Optional[str] = None
run_id: Optional[str] = None
agent_id: Optional[str] = None
filters: Optional[Dict[str, Any]] = None
@app.get("/", summary="Redirect to documentation", include_in_schema=False)
def home():
"""Redirect to the OpenAPI documentation."""
return RedirectResponse(url="/docs")
@app.get("/health", summary="Health check")
def health():
"""Check if the server is running."""
return {"status": "healthy", "service": "mem0-api"}
@app.post("/configure", summary="Configure Mem0")
def set_config(config: Dict[str, Any]):
"""Set memory configuration."""
global MEMORY_INSTANCE
MEMORY_INSTANCE = Memory.from_config(config)
return {"message": "Configuration set successfully"}
@app.post("/memories", summary="Create memories")
def add_memory(memory_create: MemoryCreate):
"""Store new memories."""
if not any([memory_create.user_id, memory_create.agent_id, memory_create.run_id]):
raise HTTPException(status_code=400, detail="At least one identifier (user_id, agent_id, run_id) is required.")
params = {k: v for k, v in memory_create.model_dump().items() if v is not None and k != "messages"}
try:
response = MEMORY_INSTANCE.add(messages=[m.model_dump() for m in memory_create.messages], **params)
return JSONResponse(content=response)
except Exception as e:
logging.exception("Error in add_memory:")
raise HTTPException(status_code=500, detail=str(e))
@app.get("/memories", summary="Get memories")
def get_all_memories(
user_id: Optional[str] = None,
run_id: Optional[str] = None,
agent_id: Optional[str] = None,
):
"""Retrieve stored memories."""
if not any([user_id, run_id, agent_id]):
raise HTTPException(status_code=400, detail="At least one identifier is required.")
try:
params = {
k: v for k, v in {"user_id": user_id, "run_id": run_id, "agent_id": agent_id}.items() if v is not None
}
return MEMORY_INSTANCE.get_all(**params)
except Exception as e:
logging.exception("Error in get_all_memories:")
raise HTTPException(status_code=500, detail=str(e))
@app.get("/memories/{memory_id}", summary="Get a memory")
def get_memory(memory_id: str):
"""Retrieve a specific memory by ID."""
try:
return MEMORY_INSTANCE.get(memory_id)
except Exception as e:
logging.exception("Error in get_memory:")
raise HTTPException(status_code=500, detail=str(e))
@app.post("/search", summary="Search memories")
def search_memories(search_req: SearchRequest):
"""Search for memories based on a query."""
try:
params = {k: v for k, v in search_req.model_dump().items() if v is not None and k != "query"}
return MEMORY_INSTANCE.search(query=search_req.query, **params)
except Exception as e:
logging.exception("Error in search_memories:")
raise HTTPException(status_code=500, detail=str(e))
@app.put("/memories/{memory_id}", summary="Update a memory")
def update_memory(memory_id: str, updated_memory: Dict[str, Any]):
"""Update an existing memory with new content."""
try:
return MEMORY_INSTANCE.update(memory_id=memory_id, data=updated_memory)
except Exception as e:
logging.exception("Error in update_memory:")
raise HTTPException(status_code=500, detail=str(e))
@app.get("/memories/{memory_id}/history", summary="Get memory history")
def memory_history(memory_id: str):
"""Retrieve memory history."""
try:
return MEMORY_INSTANCE.history(memory_id=memory_id)
except Exception as e:
logging.exception("Error in memory_history:")
raise HTTPException(status_code=500, detail=str(e))
@app.delete("/memories/{memory_id}", summary="Delete a memory")
def delete_memory(memory_id: str):
"""Delete a specific memory by ID."""
try:
MEMORY_INSTANCE.delete(memory_id=memory_id)
return {"message": "Memory deleted successfully"}
except Exception as e:
logging.exception("Error in delete_memory:")
raise HTTPException(status_code=500, detail=str(e))
@app.delete("/memories", summary="Delete all memories")
def delete_all_memories(
user_id: Optional[str] = None,
run_id: Optional[str] = None,
agent_id: Optional[str] = None,
):
"""Delete all memories for a given identifier."""
if not any([user_id, run_id, agent_id]):
raise HTTPException(status_code=400, detail="At least one identifier is required.")
try:
params = {
k: v for k, v in {"user_id": user_id, "run_id": run_id, "agent_id": agent_id}.items() if v is not None
}
MEMORY_INSTANCE.delete_all(**params)
return {"message": "All relevant memories deleted"}
except Exception as e:
logging.exception("Error in delete_all_memories:")
raise HTTPException(status_code=500, detail=str(e))
@app.post("/reset", summary="Reset all memories")
def reset_memory():
"""Completely reset stored memories."""
try:
MEMORY_INSTANCE.reset()
return {"message": "All memories reset"}
except Exception as e:
logging.exception("Error in reset_memory:")
raise HTTPException(status_code=500, detail=str(e))
if __name__ == "__main__":
import uvicorn
host = os.environ.get("MEM0_HOST", "127.0.0.1")
port = int(os.environ.get("MEM0_PORT", "8000"))
workers = int(os.environ.get("MEM0_WORKERS", "1"))
log_level = os.environ.get("MEM0_LOG_LEVEL", "info")
uvicorn.run(app, host=host, port=port, workers=workers, log_level=log_level)
+45
View File
@@ -0,0 +1,45 @@
{
appimageTools,
fetchurl,
lib,
nodejs,
nodePackages,
uv,
python3,
makeWrapper,
}: let
pname = "msty-studio";
version = "2.0.0-beta.4";
src = fetchurl {
url = "https://next-assets.msty.studio/app/alpha/linux/MstyStudio_x86_64.AppImage";
sha256 = "sha256-zJcGK7QEL3ROgVJy13mMdY/437H3Zx8EwSXy7rEhV9w=";
};
appimageContents = appimageTools.extractType2 {inherit pname version src;};
in
appimageTools.wrapType2 {
inherit pname version src;
nativeBuildInputs = [makeWrapper];
extraPkgs = pkgs: [
nodejs
nodePackages.npm
uv
python3
];
extraInstallCommands = ''
install -m 444 -D ${appimageContents}/MstyStudio.desktop -t $out/share/applications
substituteInPlace $out/share/applications/MstyStudio.desktop \
--replace 'Exec=AppRun' 'Exec=${pname}'
install -m 444 -D ${appimageContents}/MstyStudio.png \
$out/share/icons/hicolor/256x256/apps/MstyStudio.png
wrapProgram $out/bin/${pname} \
--prefix PATH : ${nodejs}/bin:${nodePackages.npm}/bin:${uv}/bin:${python3}/bin
'';
meta = {
description = "Msty Studio enables advanced, privacypreserving AI workflows entirely on your local machine.";
license = lib.licenses.unfree;
platforms = lib.platforms.linux;
mainProgram = "msty-studio";
};
}
+127
View File
@@ -0,0 +1,127 @@
{
stdenv,
lib,
nixosTests,
fetchFromGitHub,
nodejs,
pnpm_10,
fetchPnpmDeps,
pnpmConfigHook,
python3,
node-gyp,
cctools,
xcbuild,
libkrb5,
libmongocrypt,
libpq,
makeWrapper,
}: let
python = python3.withPackages (ps: with ps; [websockets]);
in
stdenv.mkDerivation (finalAttrs: {
pname = "n8n";
version = "2.9.4";
src = fetchFromGitHub {
owner = "n8n-io";
repo = "n8n";
tag = "n8n@${finalAttrs.version}";
hash = "sha256-XXQPZHtY66gOQ+nYH+Q1IjbR+SRZ9g06sgBy2x8gGh4=";
};
pnpmDeps = fetchPnpmDeps {
inherit (finalAttrs) pname version src;
pnpm = pnpm_10;
fetcherVersion = 3;
hash = "sha256-TU7HIShYj20QtdcthP0nQdubYl0bdy+XM3CoX5Rvhzk=";
};
nativeBuildInputs =
[
pnpmConfigHook
pnpm_10
python3 # required to build sqlite3 bindings
node-gyp # required to build sqlite3 bindings
makeWrapper
]
++ lib.optional stdenv.hostPlatform.isDarwin [cctools xcbuild];
buildInputs = [nodejs libkrb5 libmongocrypt libpq];
buildPhase = ''
runHook preBuild
pushd node_modules/sqlite3
node-gyp rebuild
popd
# TODO: use deploy after resolved https://github.com/pnpm/pnpm/issues/5315
pnpm build --filter=n8n
runHook postBuild
'';
preInstall = ''
echo "Removing non-deterministic and unnecessary files"
find -type d -name .turbo -exec rm -rf {} +
rm node_modules/.modules.yaml
rm packages/nodes-base/dist/types/nodes.json
CI=true pnpm --ignore-scripts prune --prod
find -type f \( -name "*.ts" -o -name "*.map" \) -exec rm -rf {} +
rm -rf node_modules/.pnpm/{typescript*,prettier*}
shopt -s globstar
# https://github.com/pnpm/pnpm/issues/3645
find node_modules packages/**/node_modules -xtype l -delete
echo "Removed non-deterministic and unnecessary files"
'';
installPhase = ''
runHook preInstall
mkdir -p $out/{bin,lib/n8n}
cp -r {packages,node_modules} $out/lib/n8n
makeWrapper $out/lib/n8n/packages/cli/bin/n8n $out/bin/n8n \
--set N8N_RELEASE_TYPE "stable"
# JavaScript runner
makeWrapper ${nodejs}/bin/node $out/bin/n8n-task-runner \
--add-flags "$out/lib/n8n/packages/@n8n/task-runner/dist/start.js"
# Python runner
mkdir -p $out/lib/n8n-task-runner-python
cp -r packages/@n8n/task-runner-python/* $out/lib/n8n-task-runner-python/
makeWrapper ${python}/bin/python $out/bin/n8n-task-runner-python \
--add-flags "$out/lib/n8n-task-runner-python/src/main.py" \
--prefix PYTHONPATH : "$out/lib/n8n-task-runner-python"
runHook postInstall
'';
passthru = {
tests = nixosTests.n8n;
updateScript = ./update.sh;
};
# this package has ~80000 files, these take too long and seem to be unnecessary
dontStrip = true;
dontPatchELF = true;
dontRewriteSymlinks = true;
meta = {
description = "Free and source-available fair-code licensed workflow automation tool";
longDescription = ''
Free and source-available fair-code licensed workflow automation tool.
Easily automate tasks across different services.
'';
homepage = "https://n8n.io";
changelog = "https://github.com/n8n-io/n8n/releases/tag/n8n@${finalAttrs.version}";
maintainers = with lib.maintainers; [gepbird AdrienLemaire sweenu];
license = lib.licenses.sustainableUse;
mainProgram = "n8n";
platforms = lib.platforms.unix;
};
})
+6
View File
@@ -0,0 +1,6 @@
#!/usr/bin/env nix-shell
#!nix-shell --pure -i bash -p bash curl jq nix-update cacert git
set -euo pipefail
new_version="$(curl -s "https://api.github.com/repos/n8n-io/n8n/releases/latest" | jq --raw-output '.tag_name | ltrimstr("n8n@")')"
nix-update n8n --flake --version "$new_version"
+31
View File
@@ -0,0 +1,31 @@
{
lib,
buildGoModule,
fetchFromGitHub,
nix-update-script,
}:
buildGoModule (finalAttrs: {
pname = "notesmd-cli";
version = "0.3.1";
src = fetchFromGitHub {
owner = "Yakitrak";
repo = "notesmd-cli";
tag = "v${finalAttrs.version}";
hash = "sha256-ruXayv1tKUtDAlj3yPtSF0D28bompbznx04+F3MAq14=";
};
vendorHash = null;
ldflags = ["-s" "-w"];
passthru.updateScript = nix-update-script {};
meta = {
description = "Obsidian CLI (Community) - Interact with Obsidian in the terminal";
homepage = "https://github.com/Yakitrak/notesmd-cli";
license = lib.licenses.mit;
platforms = lib.platforms.unix;
mainProgram = "notesmd-cli";
};
})
+106
View File
@@ -0,0 +1,106 @@
{
lib,
stdenv,
symlinkJoin,
makeWrapper,
rustPlatform,
pkg-config,
cargo-tauri,
bun,
nodejs,
cargo,
rustc,
jq,
wrapGAppsHook4,
dbus,
glib,
gtk4,
libsoup_3,
librsvg,
libappindicator,
glib-networking,
openssl,
webkitgtk_4_1,
gst_all_1,
inputs ? null,
}: let
# Get upstream opencode package for shared attributes
opencode = inputs.opencode.packages.${stdenv.hostPlatform.system}.default;
# Workaround for https://github.com/anomalyco/opencode/issues/11755
# Upstream is missing outputHashes for git dependencies
opencode-desktop = rustPlatform.buildRustPackage (finalAttrs: {
pname = "opencode-desktop";
inherit (opencode) version src node_modules patches;
cargoRoot = "packages/desktop/src-tauri";
cargoLock = {
lockFile = finalAttrs.src + "/packages/desktop/src-tauri/Cargo.lock";
outputHashes = {
"specta-2.0.0-rc.22" = "sha256-YsyOAnXELLKzhNlJ35dHA6KGbs0wTAX/nlQoW8wWyJQ=";
"tauri-2.9.5" = "sha256-dv5E/+A49ZBvnUQUkCGGJ21iHrVvrhHKNcpUctivJ8M=";
"tauri-specta-2.0.0-rc.21" = "sha256-n2VJ+B1nVrh6zQoZyfMoctqP+Csh7eVHRXwUQuiQjaQ=";
};
};
buildAndTestSubdir = finalAttrs.cargoRoot;
nativeBuildInputs =
[pkg-config cargo-tauri.hook bun nodejs cargo rustc jq makeWrapper]
++ lib.optionals stdenv.hostPlatform.isLinux [wrapGAppsHook4];
buildInputs = lib.optionals stdenv.isLinux [
dbus
glib
gtk4
libsoup_3
librsvg
libappindicator
glib-networking
openssl
webkitgtk_4_1
gst_all_1.gstreamer
gst_all_1.gst-plugins-base
gst_all_1.gst-plugins-good
gst_all_1.gst-plugins-bad
];
strictDeps = true;
preBuild = ''
cp -a ${finalAttrs.node_modules}/{node_modules,packages} .
chmod -R u+w node_modules packages
patchShebangs node_modules
patchShebangs packages/desktop/node_modules
mkdir -p packages/desktop/src-tauri/sidecars
cp ${opencode}/bin/opencode packages/desktop/src-tauri/sidecars/opencode-cli-${stdenv.hostPlatform.rust.rustcTarget}
'';
tauriBuildFlags = ["--config" "tauri.prod.conf.json" "--no-sign"];
postFixup = lib.optionalString stdenv.hostPlatform.isLinux ''
mv $out/bin/OpenCode $out/bin/opencode-desktop
sed -i 's|^Exec=OpenCode$|Exec=opencode-desktop|' $out/share/applications/OpenCode.desktop
'';
});
# Wrapper for Wayland support
in
symlinkJoin {
name = "opencode-desktop";
paths = [opencode-desktop];
nativeBuildInputs = [makeWrapper];
postBuild = ''
wrapProgram $out/bin/opencode-desktop \
--run 'if [[ "$NIXOS_OZONE_WL" == "1" ]]; then export OC_ALLOW_WAYLAND=1; fi'
'';
meta = {
description = "OpenCode Desktop App with Wayland support";
homepage = "https://opencode.ai";
license = lib.licenses.mit;
platforms = lib.platforms.linux;
mainProgram = "opencode-desktop";
};
}
+92
View File
@@ -0,0 +1,92 @@
{
lib,
stdenv,
writeShellScriptBin,
timer,
kitty,
rofi,
libnotify,
speechd,
}: let
launcher = writeShellScriptBin "launch-timer" ''
#!/bin/bash
validate_time() {
local input=$1
if [[ $input =~ ^[0-9]+[mhs]$ ]]; then
return 0
else
return 1
fi
}
notify_end() {
local session_name=$1
${libnotify}/bin/notify-send "Pomodoro" "$session_name session ended!"
${speechd}/bin/spd-say "$session_name session ended"
}
start_timer() {
local duration=$1
local session_name=$2
kitty \
--class="floating-pomodoro" \
--title="floating-pomodoro" \
${timer}/bin/timer $duration
notify_end "$session_name"
}
# Show rofi menu with options
selected=$(printf "work\nbreak\ncustom" | rofi -dmenu -p "Work Timer:" -l 3)
# Exit if no selection was made
[ -z "$selected" ] && exit
case $selected in
"work")
start_timer "45m" "work"
;;
"break")
start_timer "10m" "break"
;;
"custom")
# Show input dialog for custom time
custom_time=$(rofi -dmenu -p "Enter time (e.g., 25m, 1h, 30s):" -l 0)
# Validate input and start timer
if [ ! -z "$custom_time" ] && validate_time "$custom_time"; then
start_timer "$custom_time" "custom"
else
${libnotify}/bin/notify-send "Invalid time format" "Please use format: 30s, 25m, or 1h"
exit 1
fi
;;
esac
'';
in
stdenv.mkDerivation {
pname = "work-timer";
version = "0.1.0";
dontUnpack = true;
buildInputs = [
timer
kitty
rofi
libnotify
speechd
];
installPhase = ''
mkdir -p $out/bin
ln -s ${launcher}/bin/launch-timer $out/bin/launch-timer
'';
meta = {
description = "A Work timer.";
license = lib.licenses.mit;
platforms = lib.platforms.linux;
mainProgram = "launch-timer";
};
}
+181
View File
@@ -0,0 +1,181 @@
{
writeShellScriptBin,
rofi,
libnotify,
coreutils,
gnugrep,
gnused,
jq,
}:
writeShellScriptBin "rofi-project-opener" ''
#!/usr/bin/env bash
# rofi-project-opener - Rofi-based project directory launcher
set -euo pipefail
# Core utilities
NOTIFY="${libnotify}/bin/notify-send"
ROFI="${rofi}/bin/rofi"
MKDIR="${coreutils}/bin/mkdir"
RM="${coreutils}/bin/rm"
SORT="${coreutils}/bin/sort"
CUT="${coreutils}/bin/cut"
DIRNAME="${coreutils}/bin/dirname"
BASENAME="${coreutils}/bin/basename"
GREP="${gnugrep}/bin/grep"
SED="${gnused}/bin/sed"
JQ="${jq}/bin/jq"
# Configuration files
CONFIG_DIR="''${XDG_CONFIG_HOME:-$HOME/.config}/rofi-project-opener"
CONFIG_FILE="$CONFIG_DIR/config"
PROJECTS_JSON="$CONFIG_DIR/projects.json"
if [[ -f "$CONFIG_FILE" ]]; then
# shellcheck disable=SC1090
source "$CONFIG_FILE"
fi
# Fallback to environment variables or defaults
TERMINAL="''${TERMINAL:-kitty}"
TERMINAL_CMD="''${TERMINAL_CMD:-}"
ROFI_PROMPT="''${ROFI_PROMPT:-Select project}"
ROFI_ARGS="''${ROFI_ARGS:--dmenu -i}"
# Check for projects.json
if [[ ! -f "$PROJECTS_JSON" ]]; then
echo "[rofi-project-opener] Error: No projects.json found at $PROJECTS_JSON" >&2
"$NOTIFY" -u critical -a "rofi-project-opener" "No projects.json configuration found"
exit 1
fi
PROJECTS_JSON_DATA="$(cat "$PROJECTS_JSON")"
# Temporary file for project list
PROJECTS_LIST="''${XDG_RUNTIME_DIR:-/tmp}/rofi-project-opener.$$"
# Cleanup on exit
cleanup() {
[[ -f "$PROJECTS_LIST" ]] && "$RM" -f "$PROJECTS_LIST"
}
trap cleanup EXIT
# Ensure runtime directory exists
"$MKDIR" -p "$("$DIRNAME" "$PROJECTS_LIST")"
# Show error notification
show_error() {
local message="$1"
echo "[rofi-project-opener] Error: $message" >&2
"$NOTIFY" -u critical -a "rofi-project-opener" "$message"
}
# Build list of projects from JSON config
# Format: display_name|full_path|args
build_project_list() {
> "$PROJECTS_LIST"
# Parse JSON and iterate over each base directory entry
local keys
keys=$(echo "$PROJECTS_JSON_DATA" | "$JQ" -r 'keys[]')
for key in $keys; do
local base_path base_args
base_path=$(echo "$PROJECTS_JSON_DATA" | "$JQ" -r --arg k "$key" '.[$k].path')
base_args=$(echo "$PROJECTS_JSON_DATA" | "$JQ" -r --arg k "$key" '.[$k].args // ""')
# Expand ~ to $HOME
base_path="''${base_path/#\~/$HOME}"
# Expand $HOME variable (allows both ~ and $HOME in config)
base_path="$(eval echo "$base_path")"
# Skip if directory doesn't exist
if [[ ! -d "$base_path" ]]; then
echo "[rofi-project-opener] Warning: Directory does not exist: $base_path" >&2
continue
fi
# Find 1st level subdirectories (non-hidden)
for project in "$base_path"/*/; do
if [[ -d "$project" ]]; then
# Get directory name without trailing slash
project_path="''${project%/}"
project_name="$("$BASENAME" "$project_path")"
# Skip hidden directories
if [[ "$project_name" == .* ]]; then
continue
fi
# Use key as display prefix (e.g., "dev/myproject")
echo "$key/$project_name|$project_path|$base_args" >> "$PROJECTS_LIST"
fi
done
done
# Check if we found any projects
[[ -s "$PROJECTS_LIST" ]]
}
# Build project list
if ! build_project_list; then
show_error "No projects found in configured directories"
exit 1
fi
# Deduplicate and sort
"$SORT" -t '|' -k1 -u "$PROJECTS_LIST" -o "$PROJECTS_LIST"
# Display in rofi and get selection
# shellcheck disable=SC2086
selection=$("$CUT" -d '|' -f1 "$PROJECTS_LIST" | "$ROFI" $ROFI_ARGS -p "$ROFI_PROMPT") || true
# Exit if cancelled
if [[ -z "$selection" ]]; then
exit 0
fi
# Get the full path and args from selection
selected_line=$("$GREP" "^$selection|" "$PROJECTS_LIST")
project_path=$(echo "$selected_line" | "$CUT" -d '|' -f2)
project_args=$(echo "$selected_line" | "$CUT" -d '|' -f3)
# Exit if path not found (shouldn't happen)
if [[ -z "$project_path" ]]; then
show_error "Could not find project path for: $selection"
exit 1
fi
# Verify directory still exists
if [[ ! -d "$project_path" ]]; then
show_error "Project directory no longer exists: $project_path"
exit 1
fi
# Build terminal command
# Placeholders: %s = project path, %a = project args
if [[ -n "$TERMINAL_CMD" ]]; then
# Substitute placeholders
final_cmd="$TERMINAL_CMD"
final_cmd="''${final_cmd//%s/$project_path}"
final_cmd="''${final_cmd//%a/$project_args}"
# Source /etc/profile (base PATH) and HM session vars (sessionPath) for NixOS
exec "$TERMINAL" --hold -e bash --login -c "
unset __HM_SESS_VARS_SOURCED
for f in ~/.nix-profile/etc/profile.d/hm-session-vars.sh /etc/profiles/per-user/\$USER/etc/profile.d/hm-session-vars.sh; do
[ -f \"\$f\" ] && . \"\$f\"
done
cd '$project_path' && exec $final_cmd
"
else
# Default: open terminal, cd to project, run opencode with args
# Source /etc/profile (base PATH) and HM session vars (sessionPath) for NixOS
exec "$TERMINAL" --hold -e bash --login -c "
unset __HM_SESS_VARS_SOURCED
for f in ~/.nix-profile/etc/profile.d/hm-session-vars.sh /etc/profiles/per-user/\$USER/etc/profile.d/hm-session-vars.sh; do
[ -f \"\$f\" ] && . \"\$f\"
done
cd '$project_path' && opencode $project_args
"
fi
''
+68
View File
@@ -0,0 +1,68 @@
{
lib,
buildGoModule,
fetchFromGitHub,
gitMinimal,
makeWrapper, # Add this
nix-update-script,
opencode,
td,
tmux,
versionCheckHook,
writableTmpDirAsHomeHook,
}:
buildGoModule (finalAttrs: {
pname = "sidecar";
version = "0.76.0";
src = fetchFromGitHub {
owner = "marcus";
repo = "sidecar";
tag = "v${finalAttrs.version}";
hash = "sha256-MJ2fXxYjCJzO8XoRAuvVC2CZMIUeFH3PKim8lsc4AD0=";
};
vendorHash = "sha256-PnA7vbDBIANmHTl6VfP8eTGewjT/A5CuEd+bfP6VQOA=";
subPackages = ["cmd/sidecar"];
ldflags = [
"-s"
"-w"
"-X main.Version=v${finalAttrs.version}" # Can combine these
];
nativeBuildInputs = [makeWrapper]; # Add this
nativeCheckInputs = [
gitMinimal
writableTmpDirAsHomeHook
];
nativeInstallCheckInputs = [
versionCheckHook
writableTmpDirAsHomeHook
];
versionCheckProgramArg = "--version";
doInstallCheck = true;
doCheck = false;
postInstall = ''
wrapProgram $out/bin/sidecar \
--prefix PATH : ${lib.makeBinPath [opencode td tmux]}
'';
passthru = {
updateScript = nix-update-script {};
};
meta = {
description = "Use sidecar next to CLI agents for diffs, file trees, conversation history, and task management with td";
homepage = "https://github.com/marcus/sidecar";
changelog = "https://github.com/marcus/sidecar/releases/tag/v${finalAttrs.version}";
license = lib.licenses.mit;
mainProgram = "sidecar";
platforms = lib.platforms.unix;
};
})
+98
View File
@@ -0,0 +1,98 @@
{
lib,
stdenv,
writeShellScriptBin,
whisper-cpp,
wtype,
libnotify,
pipewire,
procps,
busybox,
}: let
script = writeShellScriptBin "stt-ptt" ''
#!/usr/bin/env bash
# stt-ptt - Push to Talk Speech to Text
CACHE_DIR="''${XDG_CACHE_HOME:-$HOME/.cache}/stt-ptt"
MODEL_DIR="''${XDG_DATA_HOME:-$HOME/.local/share}/stt-ptt/models"
AUDIO="$CACHE_DIR/stt.wav"
# Configurable via environment
STT_MODEL="''${STT_MODEL:-$MODEL_DIR/ggml-large-v3-turbo.bin}"
STT_LANGUAGE="''${STT_LANGUAGE:-auto}"
STT_NOTIFY_TIMEOUT="''${STT_NOTIFY_TIMEOUT:-3000}"
NOTIFY="${libnotify}/bin/notify-send"
PW_RECORD="${pipewire}/bin/pw-record"
WHISPER="${whisper-cpp}/bin/whisper-cli"
WTYPE="${wtype}/bin/wtype"
PKILL="${procps}/bin/pkill"
MKDIR="${busybox}/bin/mkdir"
RM="${busybox}/bin/rm"
TR="${busybox}/bin/tr"
SED="${busybox}/bin/sed"
SLEEP="${busybox}/bin/sleep"
# Ensure cache directory exists
"$MKDIR" -p "$CACHE_DIR"
# Kill any existing pw-record for this audio file (prevents orphan nodes)
kill_existing() {
"$PKILL" -f "pw-record.*$AUDIO" 2>/dev/null
"$SLEEP" 0.1
}
case "''${1:-}" in
start)
kill_existing
"$RM" -f "$AUDIO"
"$NOTIFY" -t "$STT_NOTIFY_TIMEOUT" -a "stt-ptt" "Recording..."
"$PW_RECORD" --rate=16000 --channels=1 "$AUDIO" &
;;
stop)
kill_existing
if [[ -f "$AUDIO" ]]; then
if [[ ! -f "$STT_MODEL" ]]; then
"$NOTIFY" -t "$STT_NOTIFY_TIMEOUT" -a "stt-ptt" "Error: Model not found at $STT_MODEL"
"$RM" -f "$AUDIO"
exit 1
fi
text=$("$WHISPER" -m "$STT_MODEL" -f "$AUDIO" -l "$STT_LANGUAGE" -np -nt 2>/dev/null | "$TR" -d '\n' | "$SED" 's/^[[:space:]]*//;s/[[:space:]]*$//')
"$RM" -f "$AUDIO"
[[ -n "$text" ]] && "$WTYPE" -- "$text"
fi
;;
*)
echo "Usage: stt-ptt {start|stop}"
echo ""
echo "Environment variables:"
echo " STT_MODEL - Path to whisper model (default: \$XDG_DATA_HOME/stt-ptt/models/ggml-large-v3-turbo.bin)"
echo " STT_LANGUAGE - Language code or 'auto' for auto-detection (default: auto)"
echo " STT_NOTIFY_TIMEOUT - Notification timeout in ms (default: 3000)"
exit 1
;;
esac
'';
in
stdenv.mkDerivation {
pname = "stt-ptt";
version = "0.1.0";
dontUnpack = true;
# No buildInputs needed - all runtime deps are hardcoded with full nix store paths in the script
installPhase = ''
mkdir -p "$out/bin"
ln -s ${script}/bin/stt-ptt "$out/bin/stt-ptt"
'';
meta = with lib; {
description = "Push to Talk Speech to Text using Whisper";
homepage = "https://code.m3ta.dev/m3tam3re/nixpkgs";
license = licenses.mit;
platforms = platforms.linux;
mainProgram = "stt-ptt";
};
}
+47
View File
@@ -0,0 +1,47 @@
{
lib,
buildGoModule,
fetchFromGitHub,
gitMinimal,
nix-update-script,
versionCheckHook,
writableTmpDirAsHomeHook,
}:
buildGoModule (finalAttrs: {
pname = "td";
version = "0.41.0";
src = fetchFromGitHub {
owner = "marcus";
repo = "td";
tag = "v${finalAttrs.version}";
hash = "sha256-0mj+mCYcc8i2my0FVlQSpecEsFXB5AyvjEdvSSz2bJM=";
};
vendorHash = "sha256-8mOebFPbf7+hCpn9hUrE0IGu6deEPSujr+yHqrzYEec=";
ldflags = [
"-s"
"-w"
"-X"
"main.Version=v${finalAttrs.version}"
];
nativeCheckInputs = [gitMinimal writableTmpDirAsHomeHook];
nativeInstallCheckInputs = [versionCheckHook writableTmpDirAsHomeHook];
versionCheckProgramArg = "version";
doInstallCheck = true;
doCheck = false;
passthru.updateScript = nix-update-script {};
meta = with lib; {
description = "Minimalist CLI for tracking tasks across AI coding sessions";
homepage = "https://github.com/marcus/td";
license = licenses.mit;
mainProgram = "td";
platforms = platforms.unix;
};
})
+26
View File
@@ -0,0 +1,26 @@
{writeShellScriptBin}:
writeShellScriptBin "tuxedo-backlight" ''
# all keys
echo '0 150 255' | tee /sys/class/leds/rgb:kbd_backlight*/multi_intensity
# DEL key
echo '255 0 155' | tee /sys/class/leds/rgb:kbd_backlight_15/multi_intensity
# ESC key
echo '255 0 155' | tee /sys/class/leds/rgb:kbd_backlight/multi_intensity
# function and Fn keys
for i in {1..12} 102; do
echo '0 255 80' | tee /sys/class/leds/rgb:kbd_backlight_$i/multi_intensity
done
# complete numblock and keys above
for i in {16..19} {36..39} {56..59} {76..79} {96..99} {117..119}; do
echo '255 150 0' | tee /sys/class/leds/rgb:kbd_backlight_$i/multi_intensity
done
# arrow keys
for i in 95 {114..116}; do
echo '0 255 80' | tee /sys/class/leds/rgb:kbd_backlight_$i/multi_intensity
done
''
+42
View File
@@ -0,0 +1,42 @@
{
lib,
stdenv,
fetchFromGitea,
fish,
fd,
fzf,
zellij,
}:
with lib;
stdenv.mkDerivation {
pname = "zellij-ps";
version = "0.1.0";
src = fetchFromGitea {
domain = "code.m3ta.dev";
owner = "m3tam3re";
repo = "helper-scripts";
rev = "08a3217b83391c1110545c1ee3161eecd5dbe5e9";
sha256 = "1sc4i58mwcg3qsq0wwl5rvk08ykbxc497bq7mrxiirndsarskby7";
};
propagatedBuildInputs = [fish fd fzf zellij];
nativeBuildInputs = [];
installPhase = ''
mkdir -p $out/bin
substitute zellij-ps.fish $out/bin/zellij-ps \
--replace-fail 'fd --type' '${fd}/bin/fd --type' \
--replace-fail 'fzf --preview' '${fzf}/bin/fzf --preview' \
--replace-fail 'zellij --layout' '${zellij}/bin/zellij --layout' \
--replace-fail 'pgrep -c zellij' 'pgrep -c ${zellij}/bin/zellij'
chmod +x $out/bin/zellij-ps
'';
meta = {
description = "Zellij project switcher - quickly switch between project folders";
license = lib.licenses.mit;
platforms = platforms.unix;
mainProgram = "zellij-ps";
};
}
+36
View File
@@ -0,0 +1,36 @@
# Development shells for various programming environments
# Each shell can be accessed via: nix develop .#<shell-name>
# Or used in home-manager/system configs
{
pkgs,
inputs,
}: {
# Default shell for working on this repository
default = pkgs.mkShell {
name = "m3ta-nixpkgs-dev";
buildInputs = with pkgs; [
nil # Nix LSP
alejandra # Nix formatter
nix-tree # Explore dependency trees
statix # Nix linter
deadnix # Find dead Nix code
];
shellHook = ''
echo "🚀 m3ta-nixpkgs development environment"
echo "Available commands:"
echo " nix flake check - Check flake validity"
echo " nix flake show - Show flake outputs"
echo " nix build .#<pkg> - Build a package"
echo " nix fmt . - Format Nix files"
echo " statix check . - Lint Nix files"
echo " deadnix . - Find dead code"
'';
};
# Import all individual shell environments
python = import ./python.nix {inherit pkgs inputs;};
devops = import ./devops.nix {inherit pkgs inputs;};
opencode = import ./opencode.nix {inherit pkgs inputs;};
}
+147
View File
@@ -0,0 +1,147 @@
# DevOps development environment
# Usage: nix develop .#devops
{
pkgs,
inputs ? null,
}:
pkgs.mkShell {
name = "devops-dev";
buildInputs = with pkgs; [
# Container tools
docker
docker-compose
podman
buildah
skopeo
dive # Docker image explorer
# Kubernetes tools
kubectl
kubectx # Includes kubens
k9s # TUI for Kubernetes
kubernetes-helm
helmfile
kustomize
stern # Multi-pod log tailing
kubeseal # Sealed secrets
# Infrastructure as Code
terraform
opentofu # Open-source Terraform fork
terragrunt
terraform-docs
tflint
infracost # Cost estimates for Terraform
# Configuration management
ansible
ansible-lint
# CI/CD tools
github-cli
gitlab-runner
act # Run GitHub Actions locally
# Cloud CLIs
awscli2
google-cloud-sdk
azure-cli
doctl # DigitalOcean CLI
# Monitoring and observability
prometheus
grafana
# Note: promtool is included in prometheus package
# Service mesh
istioctl
linkerd
# Security and secrets
vault
sops
age # Encryption tool
trivy # Security scanner
# Scripting and automation
python3
jq
yq-go
jo # JSON output from shell
# Network tools
curl
wget
httpie
netcat
nmap
tcpdump
wireshark-cli
# System utilities
htop
btop
lsof
tmux
git
gnumake
# Linters and formatters
shellcheck
shfmt
yamllint
];
# Environment variables
DOCKER_BUILDKIT = "1";
COMPOSE_DOCKER_CLI_BUILD = "1";
shellHook = ''
echo "🚀 DevOps Development Environment"
echo ""
echo "Container tools:"
echo " docker / podman - Container runtime"
echo " docker-compose - Multi-container applications"
echo " dive - Explore Docker images"
echo " buildah / skopeo - Build and manage containers"
echo ""
echo "Kubernetes:"
echo " kubectl - Kubernetes CLI"
echo " k9s - Kubernetes TUI"
echo " helm - Package manager"
echo " kubectx / kubens - Switch contexts/namespaces (kubens included in kubectx)"
echo " stern <pod> - Multi-pod logs"
echo ""
echo "Infrastructure as Code:"
echo " terraform / opentofu - Infrastructure provisioning"
echo " terragrunt - Terraform wrapper"
echo " ansible - Configuration management"
echo " tflint - Terraform linter"
echo ""
echo "Cloud CLIs:"
echo " aws - AWS CLI"
echo " gcloud - Google Cloud CLI"
echo " az - Azure CLI"
echo " doctl - DigitalOcean CLI"
echo ""
echo "Security & Secrets:"
echo " vault - HashiCorp Vault"
echo " sops - Secrets management"
echo " trivy - Security scanner"
echo " kubeseal - Sealed secrets"
echo ""
echo "CI/CD:"
echo " gh - GitHub CLI"
echo " act - Run GitHub Actions locally"
echo " gitlab-runner - GitLab CI runner"
echo ""
echo "Utilities:"
echo " jq / yq - JSON/YAML processors"
echo " httpie / curl - HTTP clients"
echo " shellcheck - Shell script linter"
echo ""
echo "💡 Tip: Use 'kubectx' and 'kubens' to quickly switch contexts"
echo ""
'';
}
+155
View File
@@ -0,0 +1,155 @@
# OpenCode development environment with AI coding rules
# This shell demonstrates the mkOpencodeRules library provided by this repository
# Usage: nix develop .#opencode
#
# To enable OpenCode rules, add the agents input to your flake:
# agents = {
# url = "git+https://code.m3ta.dev/m3tam3re/AGENTS";
# flake = false;
# };
{
pkgs,
lib ? pkgs.lib,
inputs ? null,
agents ? null,
}: let
# Import the opencode-rules library
m3taLib = import ../lib {lib = pkgs.lib;};
# Import custom packages
customPackages = import ../pkgs {inherit pkgs inputs;};
# Create rules configuration only if agents input is provided
# This demonstrates how to use mkOpencodeRules in a real project
rulesConfig = lib.optionalAttrs (agents != null) {
rules = m3taLib.opencode-rules.mkOpencodeRules {
# Pass the AGENTS repository path
inherit agents;
# Languages relevant to this repository
languages = ["python" "typescript" "nix"];
# Frameworks used in this repo
frameworks = ["n8n"];
# Standard concerns for development
concerns = [
"coding-style"
"naming"
"documentation"
"testing"
"git-workflow"
"project-structure"
];
};
};
in
pkgs.mkShell {
name = "opencode-dev";
# Development tools
buildInputs = with pkgs;
[
# OpenCode AI coding agent (if inputs are available)
]
++ lib.optionals (inputs != null)
[inputs.opencode.packages.${pkgs.system}.opencode]
++ [
# Task management for AI coding sessions
customPackages.td
# Companion tool for CLI agents (diffs, file trees, task management)
customPackages.sidecar
# Code analysis tools
customPackages.code2prompt
# Nix development tools (for this repo)
nil
alejandra
statix
deadnix
];
# Shell hook that sets up OpenCode rules
shellHook = ''
echo "🤖 OpenCode Development Environment"
echo ""
echo "This environment demonstrates the mkOpencodeRules library"
echo "provided by the m3ta-nixpkgs repository."
echo ""
${
if (agents != null)
then ''
# Execute the OpenCode rules shellHook
${rulesConfig.rules.shellHook}
echo " OpenCode rules configured!"
''
else ''
echo " OpenCode rules not configured"
echo ""
echo "To enable OpenCode rules, add the agents input to your flake.nix:"
echo ""
echo " inputs = {"
echo " m3ta-nixpkgs.url = \"git+https://code.m3ta.dev/m3tam3re/nixpkgs\";"
echo " agents = {"
echo " url = \"git+https://code.m3ta.dev/m3tam3re/AGENTS\";"
echo " flake = false;"
echo " };"
echo " };"
echo ""
echo "Then pass agents to the shell:"
echo " opencode = import ./opencode.nix { inherit pkgs inputs agents; };"
''
}
echo ""
echo "Available tools:"
echo " opencode - AI coding agent"
echo " td usage --new-session - View current tasks"
echo " sidecar - Companion tool (diffs, file trees, tasks)"
echo " code2prompt - Convert code to prompts"
echo ""
echo "Nix development tools:"
echo " nix flake check - Check flake validity"
echo " nix fmt . - Format Nix files"
echo " statix check . - Lint Nix files"
echo " deadnix . - Find dead code"
echo ""
${
if (agents == null)
then ''
echo "💡 Using mkOpencodeRules in your project:"
echo ""
echo "Add to your flake.nix:"
echo " inputs = {"
echo " m3ta-nixpkgs.url = \"git+https://code.m3ta.dev/m3tam3re/nixpkgs\";"
echo " agents = {"
echo " url = \"git+https://code.m3ta.dev/m3tam3re/AGENTS\";"
echo " flake = false;"
echo " };"
echo " };"
echo ""
echo " outputs = {self, nixpkgs, m3ta-nixpkgs, agents, ...}:"
echo " let"
echo " system = \"x86_64-linux\";"
echo " pkgs = nixpkgs.legacyPackages.''${system};"
echo " m3taLib = m3ta-nixpkgs.lib.''${system};"
echo " rules = m3taLib.opencode-rules.mkOpencodeRules {"
echo " inherit agents;"
echo " languages = [\"python\" \"typescript\"];"
echo " frameworks = [\"n8n\"];"
echo " };"
echo " in {"
echo " devShells.''${system}.default = pkgs.mkShell {"
echo " shellHook = rules.shellHook;"
echo " };"
echo " };"
''
else ""
}
echo ""
'';
}
+85
View File
@@ -0,0 +1,85 @@
# Modern Python development environment with marimo and uv — Nushell version
# Usage: nix develop .#python (drops into Nushell)
{
pkgs,
inputs ? null,
}: let
# Use the latest Python available in nixpkgs
python = pkgs.python313;
in
pkgs.mkShell {
name = "python-marimo-dev";
buildInputs = with pkgs; [
# Python interpreter
python
# Tooling
black
pyrefly
# Modern package manager
uv
# Essential system dependencies for numpy and scientific packages
stdenv.cc.cc.lib
zlib
gfortran
openblas
lapack
# Nushell itself
nushell
];
# Environment variables for proper library linking
LD_LIBRARY_PATH = "${pkgs.lib.makeLibraryPath [
pkgs.stdenv.cc.cc.lib
pkgs.zlib
pkgs.gfortran.cc.lib
]}";
# Bash shellHook that sets up the environment and launches Nushell
shellHook = ''
echo "🐍 Python + Marimo Development Environment"
echo ""
echo "Python version: $(python --version)"
echo "uv version: $(uv --version)"
echo ""
# Create venv if it doesn't exist
if [ ! -d ".venv" ]; then
echo "Creating virtual environment..."
uv venv
fi
# Activate the virtual environment
source .venv/bin/activate
# Install marimo if not present
if ! python -c "import marimo" 2>/dev/null; then
echo "Installing marimo..."
uv pip install marimo
fi
# Install numpy if not present
if ! python -c "import numpy" 2>/dev/null; then
echo "Installing numpy..."
uv pip install numpy
fi
echo ""
echo " Environment ready!"
echo ""
echo "Quick start:"
echo " marimo edit - Start marimo notebook"
echo " uv pip install <package> - Install packages"
echo " python script.py - Run Python scripts"
echo ""
echo "💡 Popular packages: uv pip install pandas matplotlib scipy scikit-learn"
echo ""
# Launch Nushell
exec nu
'';
}
+144
View File
@@ -0,0 +1,144 @@
# Home Manager Module Template
# This is a template for creating new Home Manager modules in m3ta-nixpkgs
# Copy this template and modify it for your specific module
{
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.programs.myProgram; # Replace 'myProgram' with your program/module name
# Common locations: config.programs.*, config.services.*, config.m3ta.*
in {
# Define options that users can set in their Home Manager configuration
options.programs.myProgram = {
enable = mkEnableOption "my custom program"; # Replace with your program description
# Example: Package option
package = mkOption {
type = types.package;
default = pkgs.hello; # Replace with your package
defaultText = literalExpression "pkgs.hello";
description = "The package to use";
};
# Example: String option
configDir = mkOption {
type = types.str;
default = "${config.xdg.configHome}/myprogram";
defaultText = literalExpression ''"''${config.xdg.configHome}/myprogram"'';
description = "Directory to store configuration";
};
# Example: Boolean option
enableBashIntegration = mkOption {
type = types.bool;
default = true;
description = "Whether to enable Bash integration";
};
# Example: Attribute set for settings
settings = mkOption {
type = types.attrs;
default = {};
example = literalExpression ''
{
theme = "dark";
fontSize = 12;
}
'';
description = "Configuration settings written to config file";
};
# Example: Lines of text (for config files)
extraConfig = mkOption {
type = types.lines;
default = "";
example = ''
# Custom configuration
option = value
'';
description = "Extra configuration to append to the config file";
};
# Example: Environment variables
environmentVariables = mkOption {
type = types.attrsOf types.str;
default = {};
example = {MY_VAR = "value";};
description = "Environment variables to set";
};
};
# Define what happens when the module is enabled
config = mkIf cfg.enable {
# Add package to user profile
home.packages = [cfg.package];
# Set environment variables
home.sessionVariables = cfg.environmentVariables;
# Create configuration file
# Method 1: Using xdg.configFile
xdg.configFile."myprogram/config.conf" = {
text = ''
# Generated by Home Manager
${builtins.toJSON cfg.settings}
${cfg.extraConfig}
'';
};
# Method 2: Using home.file for non-XDG locations
# home.file.".myprogramrc".text = ''
# # Configuration here
# '';
# Example: Bash integration
programs.bash.initExtra = mkIf cfg.enableBashIntegration ''
# My program bash integration
eval "$(${cfg.package}/bin/myprogram init bash)"
'';
# Example: Zsh integration
programs.zsh.initExtra = mkIf cfg.enableBashIntegration ''
# My program zsh integration
eval "$(${cfg.package}/bin/myprogram init zsh)"
'';
# Example: Fish integration
# programs.fish.interactiveShellInit = mkIf cfg.enableFishIntegration ''
# ${cfg.package}/bin/myprogram init fish | source
# '';
# Example: Systemd user service
systemd.user.services.myprogram = {
Unit = {
Description = "My Program Service";
After = ["graphical-session.target"];
};
Service = {
Type = "simple";
ExecStart = "${cfg.package}/bin/myprogram daemon";
Restart = "on-failure";
RestartSec = 5;
};
Install = {
WantedBy = ["default.target"];
};
};
# Example: Create directories
# home.file."${cfg.configDir}/.keep".text = "";
# Example: Manage symlinks
# home.file."bin/myprogram".source = "${cfg.package}/bin/myprogram";
};
# Module metadata (optional)
meta = {
maintainers = with lib.maintainers; []; # Add your name if in nixpkgs
};
}
+136
View File
@@ -0,0 +1,136 @@
# NixOS Module Template
# This is a template for creating new NixOS modules in m3ta-nixpkgs
# Copy this template and modify it for your specific module
{
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.m3ta.myModule; # Replace 'myModule' with your module name
in {
# Define options that users can set in their configuration
options.m3ta.myModule = {
enable = mkEnableOption "my custom module"; # Replace with your module description
# Example: String option
package = mkOption {
type = types.package;
default = pkgs.hello; # Replace with your default package
defaultText = literalExpression "pkgs.hello";
description = "The package to use for this module";
};
# Example: String option
dataDir = mkOption {
type = types.path;
default = "/var/lib/mymodule";
description = "Directory where data will be stored";
};
# Example: Port number
port = mkOption {
type = types.port;
default = 8080;
description = "Port to listen on";
};
# Example: String option
user = mkOption {
type = types.str;
default = "mymodule";
description = "User account under which the service runs";
};
# Example: Group option
group = mkOption {
type = types.str;
default = "mymodule";
description = "Group under which the service runs";
};
# Example: Boolean option
openFirewall = mkOption {
type = types.bool;
default = false;
description = "Whether to open the firewall for the service port";
};
# Example: List of strings
extraArgs = mkOption {
type = types.listOf types.str;
default = [];
example = ["--verbose" "--debug"];
description = "Additional command-line arguments to pass";
};
# Example: Attribute set (key-value pairs)
settings = mkOption {
type = types.attrs;
default = {};
example = literalExpression ''
{
logLevel = "info";
timeout = 30;
}
'';
description = "Configuration settings as attribute set";
};
};
# Define what happens when the module is enabled
config = mkIf cfg.enable {
# Create a system user
users.users.${cfg.user} = {
isSystemUser = true;
group = cfg.group;
home = cfg.dataDir;
createHome = true;
description = "My module service user";
};
users.groups.${cfg.group} = {};
# Define a systemd service
systemd.services.mymodule = {
description = "My Custom Module Service";
wantedBy = ["multi-user.target"];
after = ["network.target"];
serviceConfig = {
Type = "simple";
User = cfg.user;
Group = cfg.group;
WorkingDirectory = cfg.dataDir;
ExecStart = "${cfg.package}/bin/myprogram ${concatStringsSep " " cfg.extraArgs}";
Restart = "on-failure";
RestartSec = 5;
# Security hardening
PrivateTmp = true;
NoNewPrivileges = true;
ProtectSystem = "strict";
ProtectHome = true;
ReadWritePaths = [cfg.dataDir];
};
};
# Open firewall if requested
networking.firewall = mkIf cfg.openFirewall {
allowedTCPPorts = [cfg.port];
};
# Add package to system packages (optional)
environment.systemPackages = [cfg.package];
# Example: Create configuration file
# environment.etc."mymodule/config.json".text = builtins.toJSON cfg.settings;
};
# Module metadata
meta = {
maintainers = with lib.maintainers; []; # Add your name if in nixpkgs
doc = ./default.md; # Optional: Link to documentation
};
}
+85
View File
@@ -0,0 +1,85 @@
# Package Template
# This is a template for creating new packages in m3ta-nixpkgs
# Copy this template and modify it for your specific package
{
lib,
stdenv,
fetchFromGitHub,
# Add build dependencies here
# pkg-config,
# cmake,
# rustPlatform,
# python3,
# nodejs,
# Add runtime dependencies here
# openssl,
# libxml2,
}:
stdenv.mkDerivation rec {
pname = "package-name"; # Replace with your package name
version = "0.1.0"; # Replace with actual version
# Source fetching - choose one method:
# Method 1: From GitHub
src = fetchFromGitHub {
owner = "owner-name";
repo = "repo-name";
rev = "v${version}"; # or use a specific commit hash
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
# To get the correct hash, first set it to lib.fakeHash, then run:
# nix build .#package-name
# The error message will show the correct hash
};
# Method 2: From URL
# src = fetchurl {
# url = "https://example.com/package-${version}.tar.gz";
# hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
# };
# Build-time dependencies (tools needed to build the package)
nativeBuildInputs = [
# pkg-config
# cmake
# makeWrapper
];
# Runtime dependencies (libraries needed at runtime)
buildInputs = [
# openssl
# libxml2
];
# Build phase (optional, only if you need custom build steps)
# buildPhase = ''
# make
# '';
# Install phase (optional, only if you need custom install steps)
# installPhase = ''
# mkdir -p $out/bin
# cp binary $out/bin/
# '';
# Post-install hook (optional, for wrapping binaries, etc.)
# postInstall = ''
# wrapProgram $out/bin/program \
# --prefix PATH : ${lib.makeBinPath [ dependency ]}
# '';
# Metadata - REQUIRED
meta = with lib; {
description = "A short description of the package";
longDescription = ''
A longer, more detailed description of what the package does.
This can span multiple lines.
'';
homepage = "https://github.com/owner/repo";
changelog = "https://github.com/owner/repo/releases/tag/v${version}";
license = licenses.mit; # Change to appropriate license
maintainers = with maintainers; []; # Add your name if you're in nixpkgs
platforms = platforms.linux; # or platforms.unix, platforms.all, etc.
mainProgram = "program-name"; # The main executable name
};
}