Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e89b961b0b |
@@ -1,73 +0,0 @@
|
|||||||
# Dolt database (managed by Dolt, not git)
|
|
||||||
dolt/
|
|
||||||
embeddeddolt/
|
|
||||||
|
|
||||||
# Runtime files
|
|
||||||
bd.sock
|
|
||||||
bd.sock.startlock
|
|
||||||
sync-state.json
|
|
||||||
last-touched
|
|
||||||
.exclusive-lock
|
|
||||||
|
|
||||||
# Daemon runtime (lock, log, pid)
|
|
||||||
daemon.*
|
|
||||||
|
|
||||||
# Interactions log (runtime, not versioned)
|
|
||||||
interactions.jsonl
|
|
||||||
|
|
||||||
# Push state (runtime, per-machine)
|
|
||||||
push-state.json
|
|
||||||
|
|
||||||
# Lock files (various runtime locks)
|
|
||||||
*.lock
|
|
||||||
|
|
||||||
# Credential key (encryption key for federation peer auth — never commit)
|
|
||||||
.beads-credential-key
|
|
||||||
|
|
||||||
# Local version tracking (prevents upgrade notification spam after git ops)
|
|
||||||
.local_version
|
|
||||||
|
|
||||||
# Worktree redirect file (contains relative path to main repo's .beads/)
|
|
||||||
# Must not be committed as paths would be wrong in other clones
|
|
||||||
redirect
|
|
||||||
|
|
||||||
# Sync state (local-only, per-machine)
|
|
||||||
# These files are machine-specific and should not be shared across clones
|
|
||||||
.sync.lock
|
|
||||||
export-state/
|
|
||||||
export-state.json
|
|
||||||
|
|
||||||
# Ephemeral store (SQLite - wisps/molecules, intentionally not versioned)
|
|
||||||
ephemeral.sqlite3
|
|
||||||
ephemeral.sqlite3-journal
|
|
||||||
ephemeral.sqlite3-wal
|
|
||||||
ephemeral.sqlite3-shm
|
|
||||||
|
|
||||||
# Dolt server management (auto-started by bd)
|
|
||||||
dolt-server.pid
|
|
||||||
dolt-server.log
|
|
||||||
dolt-server.lock
|
|
||||||
dolt-server.port
|
|
||||||
dolt-server.activity
|
|
||||||
|
|
||||||
# Corrupt backup directories (created by bd doctor --fix recovery)
|
|
||||||
*.corrupt.backup/
|
|
||||||
|
|
||||||
# Backup data (auto-exported JSONL, local-only)
|
|
||||||
backup/
|
|
||||||
|
|
||||||
# Per-project environment file (Dolt connection config, GH#2520)
|
|
||||||
.env
|
|
||||||
|
|
||||||
# Legacy files (from pre-Dolt versions)
|
|
||||||
*.db
|
|
||||||
*.db?*
|
|
||||||
*.db-journal
|
|
||||||
*.db-wal
|
|
||||||
*.db-shm
|
|
||||||
db.sqlite
|
|
||||||
bd.db
|
|
||||||
# NOTE: Do NOT add negation patterns here.
|
|
||||||
# They would override fork protection in .git/info/exclude.
|
|
||||||
# Config files (metadata.json, config.yaml) are tracked by git by default
|
|
||||||
# since no pattern above ignores them.
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
# Beads - AI-Native Issue Tracking
|
|
||||||
|
|
||||||
Welcome to Beads! This repository uses **Beads** for issue tracking - a modern, AI-native tool designed to live directly in your codebase alongside your code.
|
|
||||||
|
|
||||||
## What is Beads?
|
|
||||||
|
|
||||||
Beads is issue tracking that lives in your repo, making it perfect for AI coding agents and developers who want their issues close to their code. No web UI required - everything works through the CLI and integrates seamlessly with git.
|
|
||||||
|
|
||||||
**Learn more:** [github.com/steveyegge/beads](https://github.com/steveyegge/beads)
|
|
||||||
|
|
||||||
## Quick Start
|
|
||||||
|
|
||||||
### Essential Commands
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Create new issues
|
|
||||||
bd create "Add user authentication"
|
|
||||||
|
|
||||||
# View all issues
|
|
||||||
bd list
|
|
||||||
|
|
||||||
# View issue details
|
|
||||||
bd show <issue-id>
|
|
||||||
|
|
||||||
# Update issue status
|
|
||||||
bd update <issue-id> --claim
|
|
||||||
bd update <issue-id> --status done
|
|
||||||
|
|
||||||
# Sync with Dolt remote
|
|
||||||
bd dolt push
|
|
||||||
```
|
|
||||||
|
|
||||||
### Working with Issues
|
|
||||||
|
|
||||||
Issues in Beads are:
|
|
||||||
- **Git-native**: Stored in Dolt database with version control and branching
|
|
||||||
- **AI-friendly**: CLI-first design works perfectly with AI coding agents
|
|
||||||
- **Branch-aware**: Issues can follow your branch workflow
|
|
||||||
- **Always in sync**: Auto-syncs with your commits
|
|
||||||
|
|
||||||
## Why Beads?
|
|
||||||
|
|
||||||
✨ **AI-Native Design**
|
|
||||||
- Built specifically for AI-assisted development workflows
|
|
||||||
- CLI-first interface works seamlessly with AI coding agents
|
|
||||||
- No context switching to web UIs
|
|
||||||
|
|
||||||
🚀 **Developer Focused**
|
|
||||||
- Issues live in your repo, right next to your code
|
|
||||||
- Works offline, syncs when you push
|
|
||||||
- Fast, lightweight, and stays out of your way
|
|
||||||
|
|
||||||
🔧 **Git Integration**
|
|
||||||
- Automatic sync with git commits
|
|
||||||
- Branch-aware issue tracking
|
|
||||||
- Dolt-native three-way merge resolution
|
|
||||||
|
|
||||||
## Get Started with Beads
|
|
||||||
|
|
||||||
Try Beads in your own projects:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Install Beads
|
|
||||||
curl -sSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash
|
|
||||||
|
|
||||||
# Initialize in your repo
|
|
||||||
bd init
|
|
||||||
|
|
||||||
# Create your first issue
|
|
||||||
bd create "Try out Beads"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Learn More
|
|
||||||
|
|
||||||
- **Documentation**: [github.com/steveyegge/beads/docs](https://github.com/steveyegge/beads/tree/main/docs)
|
|
||||||
- **Quick Start Guide**: Run `bd quickstart`
|
|
||||||
- **Examples**: [github.com/steveyegge/beads/examples](https://github.com/steveyegge/beads/tree/main/examples)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*Beads: Issue tracking that moves at the speed of thought* ⚡
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
# Beads Configuration File
|
|
||||||
# This file configures default behavior for all bd commands in this repository
|
|
||||||
# All settings can also be set via environment variables (BD_* prefix)
|
|
||||||
# or overridden with command-line flags
|
|
||||||
|
|
||||||
# Issue prefix for this repository (used by bd init)
|
|
||||||
# If not set, bd init will auto-detect from directory name
|
|
||||||
# Example: issue-prefix: "myproject" creates issues like "myproject-1", "myproject-2", etc.
|
|
||||||
# issue-prefix: ""
|
|
||||||
|
|
||||||
# Use no-db mode: JSONL-only, no Dolt database
|
|
||||||
# When true, bd will use .beads/issues.jsonl as the source of truth
|
|
||||||
# no-db: false
|
|
||||||
|
|
||||||
# Enable JSON output by default
|
|
||||||
# json: false
|
|
||||||
|
|
||||||
# Feedback title formatting for mutating commands (create/update/close/dep/edit)
|
|
||||||
# 0 = hide titles, N > 0 = truncate to N characters
|
|
||||||
# output:
|
|
||||||
# title-length: 255
|
|
||||||
|
|
||||||
# Default actor for audit trails (overridden by BEADS_ACTOR or --actor)
|
|
||||||
# actor: ""
|
|
||||||
|
|
||||||
# Export events (audit trail) to .beads/events.jsonl on each flush/sync
|
|
||||||
# When enabled, new events are appended incrementally using a high-water mark.
|
|
||||||
# Use 'bd export --events' to trigger manually regardless of this setting.
|
|
||||||
# events-export: false
|
|
||||||
|
|
||||||
# Multi-repo configuration (experimental - bd-307)
|
|
||||||
# Allows hydrating from multiple repositories and routing writes to the correct database
|
|
||||||
# repos:
|
|
||||||
# primary: "." # Primary repo (where this database lives)
|
|
||||||
# additional: # Additional repos to hydrate from (read-only)
|
|
||||||
# - ~/beads-planning # Personal planning repo
|
|
||||||
# - ~/work-planning # Work planning repo
|
|
||||||
|
|
||||||
# JSONL backup (periodic export for off-machine recovery)
|
|
||||||
# Auto-enabled when a git remote exists. Override explicitly:
|
|
||||||
# backup:
|
|
||||||
# enabled: false # Disable auto-backup entirely
|
|
||||||
# interval: 15m # Minimum time between auto-exports
|
|
||||||
# git-push: false # Disable git push (export locally only)
|
|
||||||
# git-repo: "" # Separate git repo for backups (default: project repo)
|
|
||||||
|
|
||||||
# Integration settings (access with 'bd config get/set')
|
|
||||||
# These are stored in the database, not in this file:
|
|
||||||
# - jira.url
|
|
||||||
# - jira.project
|
|
||||||
# - linear.url
|
|
||||||
# - linear.api-key
|
|
||||||
# - github.org
|
|
||||||
# - github.repo
|
|
||||||
|
|
||||||
sync.remote: "git+ssh://gitea@code.m3ta.dev/m3tam3re/nixpkgs.git"
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#!/usr/bin/env sh
|
|
||||||
# --- BEGIN BEADS INTEGRATION v1.0.2 ---
|
|
||||||
# This section is managed by beads. Do not remove these markers.
|
|
||||||
if command -v bd >/dev/null 2>&1; then
|
|
||||||
export BD_GIT_HOOK=1
|
|
||||||
_bd_timeout=${BEADS_HOOK_TIMEOUT:-300}
|
|
||||||
if command -v timeout >/dev/null 2>&1; then
|
|
||||||
timeout "$_bd_timeout" bd hooks run post-checkout "$@"
|
|
||||||
_bd_exit=$?
|
|
||||||
if [ $_bd_exit -eq 124 ]; then
|
|
||||||
echo >&2 "beads: hook 'post-checkout' timed out after ${_bd_timeout}s — continuing without beads"
|
|
||||||
_bd_exit=0
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
bd hooks run post-checkout "$@"
|
|
||||||
_bd_exit=$?
|
|
||||||
fi
|
|
||||||
if [ $_bd_exit -eq 3 ]; then
|
|
||||||
echo >&2 "beads: database not initialized — skipping hook 'post-checkout'"
|
|
||||||
_bd_exit=0
|
|
||||||
fi
|
|
||||||
if [ $_bd_exit -ne 0 ]; then exit $_bd_exit; fi
|
|
||||||
fi
|
|
||||||
# --- END BEADS INTEGRATION v1.0.2 ---
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#!/usr/bin/env sh
|
|
||||||
# --- BEGIN BEADS INTEGRATION v1.0.2 ---
|
|
||||||
# This section is managed by beads. Do not remove these markers.
|
|
||||||
if command -v bd >/dev/null 2>&1; then
|
|
||||||
export BD_GIT_HOOK=1
|
|
||||||
_bd_timeout=${BEADS_HOOK_TIMEOUT:-300}
|
|
||||||
if command -v timeout >/dev/null 2>&1; then
|
|
||||||
timeout "$_bd_timeout" bd hooks run post-merge "$@"
|
|
||||||
_bd_exit=$?
|
|
||||||
if [ $_bd_exit -eq 124 ]; then
|
|
||||||
echo >&2 "beads: hook 'post-merge' timed out after ${_bd_timeout}s — continuing without beads"
|
|
||||||
_bd_exit=0
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
bd hooks run post-merge "$@"
|
|
||||||
_bd_exit=$?
|
|
||||||
fi
|
|
||||||
if [ $_bd_exit -eq 3 ]; then
|
|
||||||
echo >&2 "beads: database not initialized — skipping hook 'post-merge'"
|
|
||||||
_bd_exit=0
|
|
||||||
fi
|
|
||||||
if [ $_bd_exit -ne 0 ]; then exit $_bd_exit; fi
|
|
||||||
fi
|
|
||||||
# --- END BEADS INTEGRATION v1.0.2 ---
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#!/usr/bin/env sh
|
|
||||||
# --- BEGIN BEADS INTEGRATION v1.0.2 ---
|
|
||||||
# This section is managed by beads. Do not remove these markers.
|
|
||||||
if command -v bd >/dev/null 2>&1; then
|
|
||||||
export BD_GIT_HOOK=1
|
|
||||||
_bd_timeout=${BEADS_HOOK_TIMEOUT:-300}
|
|
||||||
if command -v timeout >/dev/null 2>&1; then
|
|
||||||
timeout "$_bd_timeout" bd hooks run pre-commit "$@"
|
|
||||||
_bd_exit=$?
|
|
||||||
if [ $_bd_exit -eq 124 ]; then
|
|
||||||
echo >&2 "beads: hook 'pre-commit' timed out after ${_bd_timeout}s — continuing without beads"
|
|
||||||
_bd_exit=0
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
bd hooks run pre-commit "$@"
|
|
||||||
_bd_exit=$?
|
|
||||||
fi
|
|
||||||
if [ $_bd_exit -eq 3 ]; then
|
|
||||||
echo >&2 "beads: database not initialized — skipping hook 'pre-commit'"
|
|
||||||
_bd_exit=0
|
|
||||||
fi
|
|
||||||
if [ $_bd_exit -ne 0 ]; then exit $_bd_exit; fi
|
|
||||||
fi
|
|
||||||
# --- END BEADS INTEGRATION v1.0.2 ---
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#!/usr/bin/env sh
|
|
||||||
# --- BEGIN BEADS INTEGRATION v1.0.2 ---
|
|
||||||
# This section is managed by beads. Do not remove these markers.
|
|
||||||
if command -v bd >/dev/null 2>&1; then
|
|
||||||
export BD_GIT_HOOK=1
|
|
||||||
_bd_timeout=${BEADS_HOOK_TIMEOUT:-300}
|
|
||||||
if command -v timeout >/dev/null 2>&1; then
|
|
||||||
timeout "$_bd_timeout" bd hooks run pre-push "$@"
|
|
||||||
_bd_exit=$?
|
|
||||||
if [ $_bd_exit -eq 124 ]; then
|
|
||||||
echo >&2 "beads: hook 'pre-push' timed out after ${_bd_timeout}s — continuing without beads"
|
|
||||||
_bd_exit=0
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
bd hooks run pre-push "$@"
|
|
||||||
_bd_exit=$?
|
|
||||||
fi
|
|
||||||
if [ $_bd_exit -eq 3 ]; then
|
|
||||||
echo >&2 "beads: database not initialized — skipping hook 'pre-push'"
|
|
||||||
_bd_exit=0
|
|
||||||
fi
|
|
||||||
if [ $_bd_exit -ne 0 ]; then exit $_bd_exit; fi
|
|
||||||
fi
|
|
||||||
# --- END BEADS INTEGRATION v1.0.2 ---
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#!/usr/bin/env sh
|
|
||||||
# --- BEGIN BEADS INTEGRATION v1.0.2 ---
|
|
||||||
# This section is managed by beads. Do not remove these markers.
|
|
||||||
if command -v bd >/dev/null 2>&1; then
|
|
||||||
export BD_GIT_HOOK=1
|
|
||||||
_bd_timeout=${BEADS_HOOK_TIMEOUT:-300}
|
|
||||||
if command -v timeout >/dev/null 2>&1; then
|
|
||||||
timeout "$_bd_timeout" bd hooks run prepare-commit-msg "$@"
|
|
||||||
_bd_exit=$?
|
|
||||||
if [ $_bd_exit -eq 124 ]; then
|
|
||||||
echo >&2 "beads: hook 'prepare-commit-msg' timed out after ${_bd_timeout}s — continuing without beads"
|
|
||||||
_bd_exit=0
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
bd hooks run prepare-commit-msg "$@"
|
|
||||||
_bd_exit=$?
|
|
||||||
fi
|
|
||||||
if [ $_bd_exit -eq 3 ]; then
|
|
||||||
echo >&2 "beads: database not initialized — skipping hook 'prepare-commit-msg'"
|
|
||||||
_bd_exit=0
|
|
||||||
fi
|
|
||||||
if [ $_bd_exit -ne 0 ]; then exit $_bd_exit; fi
|
|
||||||
fi
|
|
||||||
# --- END BEADS INTEGRATION v1.0.2 ---
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
{"_type":"issue","id":"nixpkgs-rrw","title":"chore(downstream): migrate direct mkSkills callsites","description":"What to build\nMigrate known downstream configurations that directly call the old AGENTS skill composition API. Each migrated callsite should use the new m3ta-nixpkgs Agent Skills Library and preserve the current rendered skill behavior unless intentionally changed by the new validation rules.\n\nAcceptance criteria\n- Known direct callers of the old AGENTS skill composition API are identified.\n- Direct callers under the maintained configuration repositories are migrated to the new m3ta-nixpkgs agentSkills interface.\n- Any callsite that cannot be migrated immediately is captured as an explicit follow-up issue.\n- The migrated configuration evaluates or has a documented verification command.\n- No remaining maintained callsite depends on the removed AGENTS skill composition API.\n\nBlocked by\nIssues 7 and 11","status":"open","priority":2,"issue_type":"chore","owner":"p@m3ta.dev","created_at":"2026-05-25T09:05:32Z","created_by":"m3tam3re","updated_at":"2026-05-25T09:05:32Z","labels":["ready-for-agent"],"dependencies":[{"issue_id":"nixpkgs-rrw","depends_on_id":"nixpkgs-kfl","type":"blocks","created_at":"2026-05-25T11:05:50Z","created_by":"m3tam3re","metadata":"{}"},{"issue_id":"nixpkgs-rrw","depends_on_id":"nixpkgs-n5t","type":"blocks","created_at":"2026-05-25T11:05:50Z","created_by":"m3tam3re","metadata":"{}"}],"dependency_count":2,"dependent_count":0,"comment_count":0}
|
|
||||||
{"_type":"issue","id":"nixpkgs-n5t","title":"docs(agents): document AGENTS as skill data source","description":"What to build\nUpdate the AGENTS repository role and documentation so AGENTS is treated as a skill data source only. Remove the old AGENTS-provided skill composition API and document the migration path to the m3ta-nixpkgs Agent Skills Library.\n\nAcceptance criteria\n- AGENTS no longer exposes the old skill composition function.\n- AGENTS documentation explains that skill composition is provided by m3ta-nixpkgs.\n- The migration path points users to the new m3ta-nixpkgs agentSkills interface.\n- References that imply AGENTS is the canonical skill composition library are removed or rewritten.\n- Documentation validation or grep-based checks confirm the obsolete API is not advertised.\n\nBlocked by\nIssue 7","status":"open","priority":2,"issue_type":"feature","owner":"p@m3ta.dev","created_at":"2026-05-25T09:05:27Z","created_by":"m3tam3re","updated_at":"2026-05-25T09:05:27Z","labels":["ready-for-agent"],"dependencies":[{"issue_id":"nixpkgs-n5t","depends_on_id":"nixpkgs-kfl","type":"blocks","created_at":"2026-05-25T11:05:50Z","created_by":"m3tam3re","metadata":"{}"}],"dependency_count":1,"dependent_count":1,"comment_count":0}
|
|
||||||
{"_type":"issue","id":"nixpkgs-bg8","title":"feat(pi-skillset): apply active skillsets to Pi settings","description":"What to build\nComplete the pi-skillset CLI by allowing it to apply named skillsets, none, and all to Pi settings. The CLI should translate active selections into Pi-native skills patterns, preserve manual settings using the sidecar state file, and write settings and state atomically.\n\nAcceptance criteria\n- `use \u003csets...\u003e` activates all skills belonging to the named skillsets.\n- `use none` disables all catalog-managed skills.\n- `use all` activates all cataloged skills regardless of skillset membership.\n- Generated patterns use one disable-all glob for the managed skills root and exact include patterns for active skill roots.\n- Patterns are computed relative to the settings file directory in POSIX form.\n- Previously generated patterns are removed using state before new patterns are written.\n- Manual skill settings outside the generated pattern set are preserved.\n- Invalid settings JSON fails without overwriting the existing settings file.\n- Settings and state writes are atomic.\n- Successful writes tell the user to run /reload in an active Pi session.\n- Python unit tests cover named skillsets, none, all, manual preservation, state replacement, invalid JSON safety, relative paths, and reload messaging.\n\nBlocked by\nIssues 8 and 9","status":"open","priority":2,"issue_type":"feature","owner":"p@m3ta.dev","created_at":"2026-05-25T09:05:22Z","created_by":"m3tam3re","updated_at":"2026-05-25T09:05:22Z","labels":["ready-for-agent"],"dependencies":[{"issue_id":"nixpkgs-bg8","depends_on_id":"nixpkgs-e1z","type":"blocks","created_at":"2026-05-25T11:05:49Z","created_by":"m3tam3re","metadata":"{}"},{"issue_id":"nixpkgs-bg8","depends_on_id":"nixpkgs-wqh","type":"blocks","created_at":"2026-05-25T11:05:50Z","created_by":"m3tam3re","metadata":"{}"}],"dependency_count":2,"dependent_count":0,"comment_count":0}
|
|
||||||
{"_type":"issue","id":"nixpkgs-wqh","title":"feat(pi-skillset): add list and status commands","description":"What to build\nAdd the initial Python-based pi-skillset CLI focused on safe read-only inspection. The CLI should read the catalog, settings, and state using sensible defaults or explicit flags, then report available skillsets and current managed state.\n\nAcceptance criteria\n- The CLI provides a list command that shows skillset names and skill counts.\n- The CLI provides a verbose list mode that shows skills per skillset.\n- The CLI provides a status command that reports active managed skillsets and managed skill counts.\n- The status command indicates when manual skill settings are present without reimplementing Pi's full resource resolver.\n- The CLI supports flags for alternate settings, catalog, state, and skills root locations.\n- Python unit tests cover list, verbose list, status, defaults, and alternate path flags.\n\nBlocked by\nIssue 7","status":"open","priority":2,"issue_type":"feature","owner":"p@m3ta.dev","created_at":"2026-05-25T09:05:16Z","created_by":"m3tam3re","updated_at":"2026-05-25T09:05:16Z","labels":["ready-for-agent"],"dependencies":[{"issue_id":"nixpkgs-wqh","depends_on_id":"nixpkgs-kfl","type":"blocks","created_at":"2026-05-25T11:05:49Z","created_by":"m3tam3re","metadata":"{}"}],"dependency_count":1,"dependent_count":1,"comment_count":0}
|
|
||||||
{"_type":"issue","id":"nixpkgs-e1z","title":"feat(pi): add mutable settings and skillset state bootstrap","description":"What to build\nIntroduce mutable Pi settings behavior and skillset state bootstrapping so runtime skillset changes survive Home Manager rebuilds. The slice should initialize settings and state from Nix defaults when needed, preserve existing runtime state by default, and support an explicit reset path.\n\nAcceptance criteria\n- Pi settings can be managed in a mutable mode that creates or merges a real settings file instead of forcing an immutable replacement.\n- Runtime-owned fields used by skillset activation are preserved across rebuilds by default.\n- A skillset state file records generated patterns and active skillsets.\n- Default active skillsets are initialized when no state exists.\n- Existing state is preserved when it exists.\n- An explicit reset option restores the state to Nix defaults.\n- Activation behavior is covered by tests or reproducible smoke checks.\n\nBlocked by\nIssue 7","status":"open","priority":2,"issue_type":"feature","owner":"p@m3ta.dev","created_at":"2026-05-25T09:05:06Z","created_by":"m3tam3re","updated_at":"2026-05-25T09:05:06Z","labels":["ready-for-agent"],"dependencies":[{"issue_id":"nixpkgs-e1z","depends_on_id":"nixpkgs-kfl","type":"blocks","created_at":"2026-05-25T11:05:49Z","created_by":"m3tam3re","metadata":"{}"}],"dependency_count":1,"dependent_count":1,"comment_count":0}
|
|
||||||
{"_type":"issue","id":"nixpkgs-kfl","title":"feat(pi): deploy skills and catalog via Home Manager","description":"What to build\nWire the new Agent Skills Library into the Home Manager agent skill deployment path. Home Manager should use the m3ta-nixpkgs skill library as the canonical implementation, install the rendered skills directory for Pi and other tools, and publish the generated skill catalog for Pi runtime tooling.\n\nAcceptance criteria\n- Home Manager agent skill deployment no longer depends on AGENTS-provided skill composition logic.\n- The rendered skills directory is deployed to the shared agent skills location.\n- The generated catalog is deployed to the Pi skillsets location.\n- Existing external skill source options remain backwards-compatible while supporting new source options.\n- Home Manager evaluation tests or smoke tests prove a nested external skill fixture is deployed and cataloged.\n- Documentation or option descriptions identify m3ta-nixpkgs as the canonical skill composition provider.\n\nBlocked by\nIssues 5 and 6","status":"open","priority":2,"issue_type":"feature","owner":"p@m3ta.dev","created_at":"2026-05-25T09:04:55Z","created_by":"m3tam3re","updated_at":"2026-05-25T09:04:55Z","labels":["ready-for-agent"],"dependencies":[{"issue_id":"nixpkgs-kfl","depends_on_id":"nixpkgs-ir8","type":"blocks","created_at":"2026-05-25T11:05:49Z","created_by":"m3tam3re","metadata":"{}"},{"issue_id":"nixpkgs-kfl","depends_on_id":"nixpkgs-nas","type":"blocks","created_at":"2026-05-25T11:05:49Z","created_by":"m3tam3re","metadata":"{}"}],"dependency_count":2,"dependent_count":4,"comment_count":0}
|
|
||||||
{"_type":"issue","id":"nixpkgs-nas","title":"feat(agent-skills): resolve skillsets in catalog","description":"What to build\nAdd skillset modeling and resolution to the Agent Skills catalog. The slice should allow global skillsets, source-wide default skillsets, and per-skill source mappings, then emit resolved skillset membership for each catalog skill while preserving skillset definitions for debugging.\n\nAcceptance criteria\n- Global skillsets can include skills by name or relative path.\n- Global skillsets can include categories by relative path prefix.\n- Global skillsets can exclude individual skills and category prefixes.\n- Source-wide default skillsets add membership to installed skills from that source.\n- Per-skill source mappings add membership only for final installed skills.\n- Skillset membership is merged additively.\n- Empty categories fail fast in phase 1.\n- Unknown or ambiguous skillset references fail fast.\n- The catalog includes both resolved membership per skill and the source skillset definitions.\n- Tests cover direct skill membership, category membership, excludes, source defaults, per-skill mappings, additive merge behavior, and validation failures.\n\nBlocked by\nIssue 5","status":"open","priority":2,"issue_type":"feature","owner":"p@m3ta.dev","created_at":"2026-05-25T09:04:49Z","created_by":"m3tam3re","updated_at":"2026-05-25T09:04:49Z","labels":["ready-for-agent"],"dependencies":[{"issue_id":"nixpkgs-nas","depends_on_id":"nixpkgs-ir8","type":"blocks","created_at":"2026-05-25T11:05:49Z","created_by":"m3tam3re","metadata":"{}"}],"dependency_count":1,"dependent_count":1,"comment_count":0}
|
|
||||||
{"_type":"issue","id":"nixpkgs-ir8","title":"feat(agent-skills): emit catalog v1 with provenance","description":"What to build\nGenerate the first version of the Agent Skills catalog as a machine-readable artifact alongside the rendered skills directory. The catalog should use portable relative paths, include source provenance, and act as the contract consumed by later skillset and runtime tooling.\n\nAcceptance criteria\n- The skill bundle produces a catalog artifact with schema version 1.\n- Catalog skills include skill name and relative target path.\n- Catalog skills do not require absolute runtime paths.\n- Catalog source provenance includes source label, skills directory, and original relative skill path.\n- External source labels are supported, with a stable fallback when no explicit label is provided.\n- Catalog generation is covered by fixture or golden-output tests.\n\nBlocked by\nIssues 1 and 3","status":"open","priority":2,"issue_type":"feature","owner":"p@m3ta.dev","created_at":"2026-05-25T09:04:46Z","created_by":"m3tam3re","updated_at":"2026-05-25T09:04:46Z","labels":["ready-for-agent"],"dependencies":[{"issue_id":"nixpkgs-ir8","depends_on_id":"nixpkgs-3m0","type":"blocks","created_at":"2026-05-25T11:05:49Z","created_by":"m3tam3re","metadata":"{}"},{"issue_id":"nixpkgs-ir8","depends_on_id":"nixpkgs-5at","type":"blocks","created_at":"2026-05-25T11:05:49Z","created_by":"m3tam3re","metadata":"{}"}],"dependency_count":2,"dependent_count":2,"comment_count":0}
|
|
||||||
{"_type":"issue","id":"nixpkgs-vsp","title":"feat(agent-skills): validate custom and external collisions","description":"What to build\nMake the final skill bundle strict about conflicts across custom and external sources. The slice should discover custom skills recursively using the same rules as external sources and fail fast when the final catalog would contain duplicate skill names or duplicate target paths.\n\nAcceptance criteria\n- Custom skills are discovered recursively using the same terminal SKILL.md root rule as external skills.\n- Custom skills and external skills participate in the same final catalog validation.\n- Duplicate final skill names fail fast, including custom-versus-external duplicates.\n- Duplicate final target paths fail fast.\n- Positive tests verify custom and external skills can coexist.\n- Negative tests verify duplicate names and duplicate paths fail with clear diagnostics.\n\nBlocked by\nIssues 1 and 3","status":"open","priority":2,"issue_type":"feature","owner":"p@m3ta.dev","created_at":"2026-05-25T09:04:42Z","created_by":"m3tam3re","updated_at":"2026-05-25T09:04:42Z","labels":["ready-for-agent"],"dependencies":[{"issue_id":"nixpkgs-vsp","depends_on_id":"nixpkgs-3m0","type":"blocks","created_at":"2026-05-25T11:05:49Z","created_by":"m3tam3re","metadata":"{}"},{"issue_id":"nixpkgs-vsp","depends_on_id":"nixpkgs-5at","type":"blocks","created_at":"2026-05-25T11:05:48Z","created_by":"m3tam3re","metadata":"{}"}],"dependency_count":2,"dependent_count":0,"comment_count":0}
|
|
||||||
{"_type":"issue","id":"nixpkgs-3m0","title":"feat(agent-skills): add source layouts and category validation","description":"What to build\nAdd per-source layout control to the Agent Skills Library so skill sources can be rendered in preserved, flat, or category-prefixed form. The slice should produce verifiable output paths for all three layouts and strictly validate category configuration.\n\nAcceptance criteria\n- The preserve layout keeps each skill root's relative source path under the target skills root.\n- The flat layout renders each skill under its skill name.\n- The under layout renders each skill under a validated category prefix while preserving the source structure below that prefix.\n- The default layout is preserve.\n- Category values are validated as safe relative paths.\n- A category is required for under layout.\n- Supplying a category with preserve or flat layout fails fast.\n- Fixture tests verify all layouts and invalid category combinations.\n\nBlocked by\nIssue 1","status":"open","priority":2,"issue_type":"feature","owner":"p@m3ta.dev","created_at":"2026-05-25T09:04:28Z","created_by":"m3tam3re","updated_at":"2026-05-25T09:04:28Z","labels":["ready-for-agent"],"dependencies":[{"issue_id":"nixpkgs-3m0","depends_on_id":"nixpkgs-5at","type":"blocks","created_at":"2026-05-25T11:05:48Z","created_by":"m3tam3re","metadata":"{}"}],"dependency_count":1,"dependent_count":2,"comment_count":0}
|
|
||||||
{"_type":"issue","id":"nixpkgs-7vr","title":"feat(agent-skills): support select and exclude semantics","description":"What to build\nExtend the Agent Skills Library tracer so callers can include and exclude skills from each source predictably. The slice should support selecting skills by skill name or relative skill path, excluding skills by skill name or relative skill path, preserve the distinction between selecting all skills and selecting no skills, and fail fast when references are unknown or ambiguous.\n\nAcceptance criteria\n- selectSkills accepts both skill names and relative skill paths.\n- selectSkills set to null includes all discovered skills from a source.\n- selectSkills set to an empty list includes no skills from a source.\n- excludeSkills removes matching skills from a source and is validated against discovered source skills.\n- Unknown skill references fail with a clear error.\n- Ambiguous skill-name references fail with a clear error and require relative path disambiguation.\n- Fixture tests cover selection by name, selection by path, exclusion, unknown references, ambiguous references, null selection, and empty selection.\n\nBlocked by\nIssue 1","status":"open","priority":2,"issue_type":"feature","owner":"p@m3ta.dev","created_at":"2026-05-25T09:04:23Z","created_by":"m3tam3re","updated_at":"2026-05-25T09:04:23Z","labels":["ready-for-agent"],"dependencies":[{"issue_id":"nixpkgs-7vr","depends_on_id":"nixpkgs-5at","type":"blocks","created_at":"2026-05-25T11:05:48Z","created_by":"m3tam3re","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
|
|
||||||
{"_type":"issue","id":"nixpkgs-5at","title":"feat(agent-skills): add recursive skill bundle tracer","description":"What to build\nCreate the first end-to-end tracer for the new m3ta-nixpkgs Agent Skills Library. The slice should expose the new skill bundle interface, provide a convenience interface for callers that only need the rendered skills directory, discover skill directories recursively, treat a directory containing SKILL.md as a terminal skill root, ignore hidden directories and dependency directories, derive skill names from parent directory names, and prove the resulting skill tree can be built from nested fixture sources.\n\nAcceptance criteria\n- A public agent-skills library interface exists for building a skill bundle and for retrieving only the rendered skills directory.\n- Nested skill directories containing SKILL.md are discovered and rendered into the output skill tree.\n- Discovery stops below a discovered skill root and does not treat nested content inside a skill as another skill.\n- Hidden directories and dependency directories are ignored during discovery.\n- Skill names are derived from the direct parent directory of SKILL.md.\n- Nix fixture tests or build/eval tests verify the tracer behavior end-to-end.\n\nBlocked by\nNone - can start immediately","status":"open","priority":2,"issue_type":"feature","owner":"p@m3ta.dev","created_at":"2026-05-25T09:04:14Z","created_by":"m3tam3re","updated_at":"2026-05-25T09:04:14Z","labels":["ready-for-agent"],"dependency_count":0,"dependent_count":4,"comment_count":0}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"database": "dolt",
|
|
||||||
"backend": "dolt",
|
|
||||||
"dolt_mode": "embedded",
|
|
||||||
"dolt_database": "nixpkgs",
|
|
||||||
"project_id": "b57a167a-6526-4211-a6c1-51686e431912"
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
|
|
||||||
# Use bd merge for beads JSONL files
|
|
||||||
.beads/issues.jsonl merge=beads
|
|
||||||
@@ -1,526 +0,0 @@
|
|||||||
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
|
|
||||||
# Custom scripts (./update.sh) become store paths ending in .sh
|
|
||||||
# nix-update-script produces a list with nix-update binary path
|
|
||||||
result=$(nix eval --impure --raw --expr "
|
|
||||||
let
|
|
||||||
flake = builtins.getFlake (toString ./.);
|
|
||||||
pkg = flake.packages.\${builtins.currentSystem}.${pkg};
|
|
||||||
script = pkg.passthru.updateScript or null;
|
|
||||||
in
|
|
||||||
if script == null then \"none\"
|
|
||||||
else if builtins.isPath script then \"custom\"
|
|
||||||
else if builtins.isString script then
|
|
||||||
(if builtins.match \".*\\.sh$\" script != null then \"custom\" else \"other\")
|
|
||||||
else if builtins.isList script then
|
|
||||||
let first = builtins.head script;
|
|
||||||
in if builtins.isString first && builtins.match \".*/nix-update$\" first != null
|
|
||||||
then \"nix-update-script\"
|
|
||||||
else \"custom\"
|
|
||||||
else if builtins.isAttrs script && script ? command then \"custom\"
|
|
||||||
else \"other\"
|
|
||||||
" 2>/dev/null || echo "other")
|
|
||||||
[[ "$result" == "custom" ]]
|
|
||||||
}
|
|
||||||
|
|
||||||
# Run a custom update script directly
|
|
||||||
# Scripts must use nix-shell shebang for their own dependencies
|
|
||||||
run_custom_update_script() {
|
|
||||||
local pkg=$1
|
|
||||||
local before_hash=$(git rev-parse HEAD)
|
|
||||||
|
|
||||||
echo " 🔧 Detected custom update script for $pkg"
|
|
||||||
|
|
||||||
# Resolve the store path of the update script
|
|
||||||
local script_path
|
|
||||||
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 if builtins.isList script then builtins.head script
|
|
||||||
else script;
|
|
||||||
in toString cmd
|
|
||||||
" 2>/dev/null)
|
|
||||||
|
|
||||||
if [ -z "$script_path" ]; then
|
|
||||||
echo "❌ Could not resolve update script path for $pkg"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Set environment variables that nix-update would normally provide
|
|
||||||
export UPDATE_NIX_NAME=$(nix eval --raw .#${pkg}.name 2>/dev/null || echo "$pkg")
|
|
||||||
export UPDATE_NIX_PNAME=$(nix eval --raw .#${pkg}.pname 2>/dev/null || echo "$pkg")
|
|
||||||
export UPDATE_NIX_OLD_VERSION=$(nix eval --raw .#${pkg}.version 2>/dev/null || echo "unknown")
|
|
||||||
export UPDATE_NIX_ATTR_PATH="$pkg"
|
|
||||||
|
|
||||||
echo " Running: $script_path"
|
|
||||||
if bash "$script_path" 2>&1 | tee /tmp/update-${pkg}.log; then
|
|
||||||
if [ "$(check_commit "$before_hash")" = "true" ]; then
|
|
||||||
echo "✅ Updated $pkg (via custom script)"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
# Script succeeded but no commit — may already be up to date
|
|
||||||
if grep -q "already at latest\|nothing to do" /tmp/update-${pkg}.log; then
|
|
||||||
echo "✓ $pkg already up to date"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Clean up on failure
|
|
||||||
git checkout -- . 2>/dev/null || true
|
|
||||||
git clean -fd 2>/dev/null || true
|
|
||||||
|
|
||||||
if ! grep -q "already at latest\|nothing to do\|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
|
|
||||||
-52
@@ -1,52 +0,0 @@
|
|||||||
# 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/
|
|
||||||
.sidecar-agent
|
|
||||||
.sidecar-task
|
|
||||||
.sidecar-pr
|
|
||||||
.sidecar-start.sh
|
|
||||||
.sidecar-base
|
|
||||||
.td-root
|
|
||||||
.cache
|
|
||||||
.pi*
|
|
||||||
|
|
||||||
# Beads / Dolt files (added by bd init)
|
|
||||||
.dolt/
|
|
||||||
*.db
|
|
||||||
.beads-credential-key
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
# Agent Instructions
|
|
||||||
|
|
||||||
This project uses **bd** (beads) for issue tracking. Run `bd prime` for full workflow context.
|
|
||||||
|
|
||||||
## Quick Reference
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bd ready # Find available work
|
|
||||||
bd show <id> # View issue details
|
|
||||||
bd update <id> --claim # Claim work atomically
|
|
||||||
bd close <id> # Complete work
|
|
||||||
bd dolt push # Push beads data to remote
|
|
||||||
```
|
|
||||||
|
|
||||||
## Non-Interactive Shell Commands
|
|
||||||
|
|
||||||
**ALWAYS use non-interactive flags** with file operations to avoid hanging on confirmation prompts.
|
|
||||||
|
|
||||||
Shell commands like `cp`, `mv`, and `rm` may be aliased to include `-i` (interactive) mode on some systems, causing the agent to hang indefinitely waiting for y/n input.
|
|
||||||
|
|
||||||
**Use these forms instead:**
|
|
||||||
```bash
|
|
||||||
# Force overwrite without prompting
|
|
||||||
cp -f source dest # NOT: cp source dest
|
|
||||||
mv -f source dest # NOT: mv source dest
|
|
||||||
rm -f file # NOT: rm file
|
|
||||||
|
|
||||||
# For recursive operations
|
|
||||||
rm -rf directory # NOT: rm -r directory
|
|
||||||
cp -rf source dest # NOT: cp -r source dest
|
|
||||||
```
|
|
||||||
|
|
||||||
**Other commands that may prompt:**
|
|
||||||
- `scp` - use `-o BatchMode=yes` for non-interactive
|
|
||||||
- `ssh` - use `-o BatchMode=yes` to fail instead of prompting
|
|
||||||
- `apt-get` - use `-y` flag
|
|
||||||
- `brew` - use `HOMEBREW_NO_AUTO_UPDATE=1` env var
|
|
||||||
|
|
||||||
<!-- BEGIN BEADS INTEGRATION v:1 profile:minimal hash:ca08a54f -->
|
|
||||||
## Beads Issue Tracker
|
|
||||||
|
|
||||||
This project uses **bd (beads)** for issue tracking. Run `bd prime` to see full workflow context and commands.
|
|
||||||
|
|
||||||
### Quick Reference
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bd ready # Find available work
|
|
||||||
bd show <id> # View issue details
|
|
||||||
bd update <id> --claim # Claim work
|
|
||||||
bd close <id> # Complete work
|
|
||||||
```
|
|
||||||
|
|
||||||
### Rules
|
|
||||||
|
|
||||||
- Use `bd` for ALL task tracking — do NOT use TodoWrite, TaskCreate, or markdown TODO lists
|
|
||||||
- Run `bd prime` for detailed command reference and session close protocol
|
|
||||||
- Use `bd remember` for persistent knowledge — do NOT use MEMORY.md files
|
|
||||||
|
|
||||||
## Session Completion
|
|
||||||
|
|
||||||
**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds.
|
|
||||||
|
|
||||||
**MANDATORY WORKFLOW:**
|
|
||||||
|
|
||||||
1. **File issues for remaining work** - Create issues for anything that needs follow-up
|
|
||||||
2. **Run quality gates** (if code changed) - Tests, linters, builds
|
|
||||||
3. **Update issue status** - Close finished work, update in-progress items
|
|
||||||
4. **PUSH TO REMOTE** - This is MANDATORY:
|
|
||||||
```bash
|
|
||||||
git pull --rebase
|
|
||||||
bd dolt push
|
|
||||||
git push
|
|
||||||
git status # MUST show "up to date with origin"
|
|
||||||
```
|
|
||||||
5. **Clean up** - Clear stashes, prune remote branches
|
|
||||||
6. **Verify** - All changes committed AND pushed
|
|
||||||
7. **Hand off** - Provide context for next session
|
|
||||||
|
|
||||||
**CRITICAL RULES:**
|
|
||||||
- Work is NOT complete until `git push` succeeds
|
|
||||||
- NEVER stop before pushing - that leaves work stranded locally
|
|
||||||
- NEVER say "ready to push when you are" - YOU must push
|
|
||||||
- If push fails, resolve and retry until it succeeds
|
|
||||||
<!-- END BEADS INTEGRATION -->
|
|
||||||
-108
@@ -1,108 +0,0 @@
|
|||||||
# Changelog
|
|
||||||
|
|
||||||
All notable changes to this project will be documented in this file.
|
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/).
|
|
||||||
|
|
||||||
## [Unreleased]
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Remove duplicate opencode-rules.nix (backward-compat alias preserved)
|
|
||||||
- Tool-agnostic naming in coding-rules lib internals
|
|
||||||
- Remove redundant overlay entries for non-existent flake inputs
|
|
||||||
- Remove redundant 'additions' overlay (identical to 'default')
|
|
||||||
|
|
||||||
### Removed
|
|
||||||
- Dead overlay entries for non-existent flake inputs
|
|
||||||
- Legacy `mkOpencodeRules` alias and `lib.opencode-rules` backward-compat entry (use `mkCodingRules` / `lib.coding-rules`)
|
|
||||||
|
|
||||||
## [0.4.0] - 2026-04-15
|
|
||||||
|
|
||||||
### Added
|
|
||||||
- Pi-agent wrapper with systemd sandbox and per-host-user policy
|
|
||||||
- Containerized Pi agent
|
|
||||||
- `lib.agents.nix` with loadCanonical, renderers (OpenCode, Claude Code, Pi), and shellHook
|
|
||||||
- `lib.coding-rules` helper for per-project rule injection (renamed from opencode-rules)
|
|
||||||
- Home Manager modules for coding agents: `claude-code`, `opencode`, `pi`
|
|
||||||
- Agents rework with canonical TOML format and harness-agnostic renderers
|
|
||||||
- `vibetyper` and `eigent` packages
|
|
||||||
- `openspec` package
|
|
||||||
- `basecamp-cli` package
|
|
||||||
- `openshell` package (0.0.14 through 0.0.23)
|
|
||||||
- `openwork` package
|
|
||||||
- Opencode config moved into m3ta-nixpkgs
|
|
||||||
- Opencode dev shell with mkCodingRules demo
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- OpenCode flake input updated through v1.1.65 to v1.3.6
|
|
||||||
- Switched from local opencode package to upstream flake input
|
|
||||||
- Removed opencode-desktop (awaiting upstream fix), later re-enabled
|
|
||||||
- Nix eval warnings resolved
|
|
||||||
- Flake inputs updated throughout
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Pi settings sync
|
|
||||||
- Remove openwork sidecars in preFixup to prevent .opencode-wrapped conflict
|
|
||||||
- Remove sidecar binaries from openwork $out/bin to fix buildEnv conflict
|
|
||||||
- Vibetyper .desktop entry
|
|
||||||
- Opencode module formatting
|
|
||||||
- Formatting opencode module
|
|
||||||
|
|
||||||
## [0.3.0] - 2026-02-20
|
|
||||||
|
|
||||||
### Added
|
|
||||||
- `notesmd-cli` package with flake checks
|
|
||||||
- `sidecar` and `td` packages
|
|
||||||
- `opencode-desktop` package with Wayland support
|
|
||||||
- `mem0` package (1.0.2 through 1.0.9)
|
|
||||||
- `kestracli` / `kestractl` package (1.0.0 to 1.2.2)
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Nix-update CI workflow optimized with caching and parallel processing
|
|
||||||
- Restructured n8n version handling for nix-update compatibility
|
|
||||||
- Switched formatter from nixpkgs-fmt to alejandra
|
|
||||||
- Replace local opencode with upstream flake input v1.1.27
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- n8n build error
|
|
||||||
- n8n pnpm hash
|
|
||||||
- n8n update script
|
|
||||||
- Gitea runner opencode.url flake input
|
|
||||||
- nix-update workflow: YAML syntax, jobs indentation, PR body formatting
|
|
||||||
- Arithmetic increment failing with set -e in nix-update workflow
|
|
||||||
- Removed magic-nix-cache-action causing platform mapping error
|
|
||||||
- Opencode bun version requirement patched to match upstream lockfile
|
|
||||||
- Deprecated opencode update logic removed
|
|
||||||
- nix fmt without arg in workflow
|
|
||||||
- Extra Lua config renamed initLua
|
|
||||||
- Stt-ptt use pkill for better process management
|
|
||||||
|
|
||||||
## [0.2.0] - 2026-01-13
|
|
||||||
|
|
||||||
### Added
|
|
||||||
- Gitea Actions workflow for automated package updates with nix-update
|
|
||||||
- `n8n`, `beads`, and `opencode` packages
|
|
||||||
- `stt-ptt` package with auto-language detection
|
|
||||||
- `rofi-project-opener` for rofi-based project launching
|
|
||||||
- Hierarchical AGENTS.md knowledge base
|
|
||||||
- Dev shell structure with python and devops shells
|
|
||||||
- Port management modules (NixOS + Home Manager)
|
|
||||||
- Port helper library (`lib/ports.nix`)
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Beads updated through v0.49.1
|
|
||||||
- N8n updated through v2.8.1
|
|
||||||
- Opencode updated through v1.1.18
|
|
||||||
- Documentation expanded with comprehensive patterns and HM module docs
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Python env version fix for marimo
|
|
||||||
|
|
||||||
## [0.1.0] - 2025-10-04
|
|
||||||
|
|
||||||
### Added
|
|
||||||
- Initial flake setup with packages, overlays, modules, and shells
|
|
||||||
- NixOS and Home Manager module infrastructure
|
|
||||||
- `lib/` shared utilities
|
|
||||||
- `overlays/mods/` for package modifications
|
|
||||||
- `templates/` for new packages/modules
|
|
||||||
- `examples/` for usage documentation
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
This repository is being used as a Dolt remote.
|
||||||
|
|
||||||
|
ref=refs/dolt/data
|
||||||
|
|
||||||
|
head=43d141bca1faebdf2ed20deb3c147ca1b2946eea
|
||||||
|
|
||||||
|
timestamp=2026-07-04T07:30:30Z
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
# 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
|
|
||||||
|
|
||||||
See [📦 Packages](./docs/packages/) for the full index with descriptions.
|
|
||||||
|
|
||||||
Quick reference — build any package directly:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
nix build git+https://code.m3ta.dev/m3tam3re/nixpkgs#<package-name>
|
|
||||||
nix run git+https://code.m3ta.dev/m3tam3re/nixpkgs#<package-name>
|
|
||||||
```
|
|
||||||
|
|
||||||
Notable packages: `sidecar`, `td`, `code2prompt`, `mem0`, `n8n`, `zellij-ps`.
|
|
||||||
|
|
||||||
## 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)
|
|
||||||
@@ -1,473 +0,0 @@
|
|||||||
# 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`).
|
|
||||||
@@ -1,373 +0,0 @@
|
|||||||
# 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
|
|
||||||
```
|
|
||||||
@@ -1,316 +0,0 @@
|
|||||||
# 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
|
|
||||||
-143
@@ -1,143 +0,0 @@
|
|||||||
# 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
|
|
||||||
- [Adding Modules](./guides/adding-modules.md) - How to add new NixOS or Home Manager modules
|
|
||||||
- [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
|
|
||||||
|
|
||||||
- [Packages Index](./packages/) - All packages with descriptions
|
|
||||||
- [Adding Packages](../guides/adding-packages.md) - How to add new packages
|
|
||||||
- [Templates](../templates.md) - Boilerplate templates
|
|
||||||
|
|
||||||
### ⚙️ 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
|
|
||||||
- [Templates](../templates.md) - Boilerplate for packages and modules
|
|
||||||
|
|
||||||
## 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)
|
|
||||||
@@ -1,261 +0,0 @@
|
|||||||
# Adding Modules Guide
|
|
||||||
|
|
||||||
How to add new NixOS and Home Manager modules to m3ta-nixpkgs.
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
Modules extend your system or user configuration with reusable, declarative options. m3ta-nixpkgs uses the standard NixOS module system with a `m3ta.*` namespace.
|
|
||||||
|
|
||||||
## Quick Start
|
|
||||||
|
|
||||||
Use a template for quick setup:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# NixOS module
|
|
||||||
nix flake init -t .#nixos-module my-module
|
|
||||||
|
|
||||||
# Home Manager module
|
|
||||||
nix flake init -t .#home-manager-module my-module
|
|
||||||
```
|
|
||||||
|
|
||||||
This copies the template into `templates/` — move it to the appropriate location and customize.
|
|
||||||
|
|
||||||
## Adding a NixOS Module
|
|
||||||
|
|
||||||
### 1. Create the Module File
|
|
||||||
|
|
||||||
Create `modules/nixos/<my-module>.nix`:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
{config, lib, pkgs, ...}:
|
|
||||||
with lib; let
|
|
||||||
cfg = config.m3ta.myModule;
|
|
||||||
in {
|
|
||||||
options.m3ta.myModule = {
|
|
||||||
enable = mkEnableOption "my module description";
|
|
||||||
# Add custom options here
|
|
||||||
someOption = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "default-value";
|
|
||||||
description = "Description of this option";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
# System configuration goes here
|
|
||||||
environment.systemPackages = [pkgs.some-package];
|
|
||||||
|
|
||||||
# Or systemd services
|
|
||||||
systemd.services.my-service = {
|
|
||||||
enable = true;
|
|
||||||
description = "My service";
|
|
||||||
wantedBy = ["multi-user.target"];
|
|
||||||
serviceConfig = {
|
|
||||||
ExecStart = "${pkgs.some-package}/bin/some-daemon";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Register in the Aggregator
|
|
||||||
|
|
||||||
Add to `modules/nixos/default.nix`:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
./ports.nix
|
|
||||||
./mem0.nix
|
|
||||||
./<my-module>.nix # ← add your module
|
|
||||||
];
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Export from flake.nix
|
|
||||||
|
|
||||||
Add to the `nixosModules` output in `flake.nix` (optional, for direct import):
|
|
||||||
|
|
||||||
```nix
|
|
||||||
nixosModules = {
|
|
||||||
default = ./modules/nixos;
|
|
||||||
ports = ./modules/nixos/ports.nix;
|
|
||||||
mem0 = ./modules/nixos/mem0.nix;
|
|
||||||
my-module = ./modules/nixos/<my-module>.nix; # ← add this
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
## Adding a Home Manager Module
|
|
||||||
|
|
||||||
Home Manager modules are organized by category under `modules/home-manager/`.
|
|
||||||
|
|
||||||
### Categories
|
|
||||||
|
|
||||||
| Category | Purpose | Location |
|
|
||||||
|----------|---------|----------|
|
|
||||||
| `cli/` | Command-line tools and utilities | `modules/home-manager/cli/` |
|
|
||||||
| `coding/` | Development tools, editors, agents | `modules/home-manager/coding/` |
|
|
||||||
| Root | Cross-cutting concerns (e.g., ports) | `modules/home-manager/` |
|
|
||||||
|
|
||||||
### 1. Choose a Category
|
|
||||||
|
|
||||||
- **CLI tools** (zsh plugins, tmux config, etc.) → `cli/`
|
|
||||||
- **Development tools** (editor config, linters, etc.) → `coding/`
|
|
||||||
- **System-wide settings** (ports, environment) → root level
|
|
||||||
|
|
||||||
### 2. Create the Module File
|
|
||||||
|
|
||||||
Create `modules/home-manager/<category>/<my-module>.nix`:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
{config, lib, pkgs, ...}:
|
|
||||||
with lib; let
|
|
||||||
cfg = config.m3ta.myModule;
|
|
||||||
in {
|
|
||||||
options.m3ta.myModule = {
|
|
||||||
enable = mkEnableOption "my user module description";
|
|
||||||
someOption = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "value";
|
|
||||||
description = "An option for this module";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
home.packages = [pkgs.some-package];
|
|
||||||
|
|
||||||
# Or Home Manager-specific options
|
|
||||||
programs.zsh.enable = true;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Register in the Category Aggregator
|
|
||||||
|
|
||||||
For `cli/` modules, add to `modules/home-manager/cli/default.nix`:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
./rofi-project-opener.nix
|
|
||||||
./stt-ptt.nix
|
|
||||||
./zellij-ps.nix
|
|
||||||
./<my-module>.nix # ← add your module
|
|
||||||
];
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
For `coding/` modules, add to `modules/home-manager/coding/default.nix`:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
./editors.nix
|
|
||||||
./opencode.nix
|
|
||||||
./agents
|
|
||||||
./<my-module>.nix # ← add your module
|
|
||||||
];
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Export from flake.nix
|
|
||||||
|
|
||||||
Add to `homeManagerModules` in `flake.nix`:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
homeManagerModules = {
|
|
||||||
default = import ./modules/home-manager;
|
|
||||||
my-module = import ./modules/home-manager/<category>/<my-module>.nix; # ← add this
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
## Module Patterns
|
|
||||||
|
|
||||||
### Standard Enable Option
|
|
||||||
|
|
||||||
Always start with `mkEnableOption`:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
options.m3ta.myModule = {
|
|
||||||
enable = mkEnableOption "my module";
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
### Conditional Configuration
|
|
||||||
|
|
||||||
Use `mkIf` for conditional config:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
# Only applied when enabled
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
### Multiple Conditions
|
|
||||||
|
|
||||||
Use `mkMerge` when combining multiple conditional blocks:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
config = mkMerge [
|
|
||||||
(mkIf cfg.feature1.enable { ... })
|
|
||||||
(mkIf cfg.feature2.enable { ... })
|
|
||||||
];
|
|
||||||
```
|
|
||||||
|
|
||||||
### Nested Namespaces
|
|
||||||
|
|
||||||
For logically grouped options, use nested namespaces:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
options.m3ta.coding = {
|
|
||||||
myTool = {
|
|
||||||
enable = mkEnableOption "my coding tool";
|
|
||||||
# ...
|
|
||||||
};
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
Usage: `m3ta.coding.myTool.enable = true;`
|
|
||||||
|
|
||||||
### Shared Library Functions
|
|
||||||
|
|
||||||
For shared utilities (port helpers, etc.), import from `lib/`:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
let
|
|
||||||
portsLib = import ../../lib/ports.nix {inherit lib;};
|
|
||||||
portHelpers = portsLib.mkPortHelpers { /* ... */ };
|
|
||||||
in {
|
|
||||||
# use portHelpers
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Documentation
|
|
||||||
|
|
||||||
Add documentation for your module:
|
|
||||||
|
|
||||||
1. Create `docs/modules/nixos/<my-module>.md` (NixOS) or `docs/modules/home-manager/<category>/<my-module>.md` (HM)
|
|
||||||
2. Follow the existing format in `docs/modules/`
|
|
||||||
3. Add it to the appropriate overview page's "Available Modules" list
|
|
||||||
4. Link it from `docs/guides/using-modules.md`
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Validate the module loads correctly
|
|
||||||
nix flake check
|
|
||||||
|
|
||||||
# Test with a minimal configuration (NixOS)
|
|
||||||
nixos-rebuild dry-build -I nixpkgs=. --option experimental-features flakes
|
|
||||||
|
|
||||||
# Format before commit
|
|
||||||
nix fmt
|
|
||||||
```
|
|
||||||
|
|
||||||
## Related
|
|
||||||
|
|
||||||
- [Using Modules](./using-modules.md) - How to use existing modules
|
|
||||||
- [Port Management](./port-management.md) - Centralized port management
|
|
||||||
- [Development Workflow](./development-workflow.md) - Local development
|
|
||||||
- [Adding Packages](./adding-packages.md) - Adding packages (not modules)
|
|
||||||
- [Architecture](../ARCHITECTURE.md) - Repository structure
|
|
||||||
@@ -1,504 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,527 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,402 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,525 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,668 +0,0 @@
|
|||||||
# 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
|
|
||||||
├── opencode.nix # OpenCode non-agent config
|
|
||||||
└── agents/ # Per-tool agent deployment
|
|
||||||
├── default.nix
|
|
||||||
├── opencode.nix
|
|
||||||
├── claude-code.nix
|
|
||||||
└── pi.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)
|
|
||||||
|
|
||||||
### `coding.opencode`
|
|
||||||
|
|
||||||
OpenCode AI coding assistant (non-agent config: theme, formatter, plugins).
|
|
||||||
|
|
||||||
```nix
|
|
||||||
coding.opencode = {
|
|
||||||
enable = true;
|
|
||||||
ohMyOpencodeSettings = {
|
|
||||||
agents.sisyphus.model = "anthropic/claude-opus-4-5";
|
|
||||||
};
|
|
||||||
extraSettings = {
|
|
||||||
provider.anthropic.name = "Anthropic";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
### `coding.agents.opencode`
|
|
||||||
|
|
||||||
OpenCode agent deployment from canonical TOML definitions.
|
|
||||||
|
|
||||||
```nix
|
|
||||||
coding.agents.opencode = {
|
|
||||||
enable = true;
|
|
||||||
agentsInput = inputs.agents;
|
|
||||||
modelOverrides = {
|
|
||||||
chiron = "anthropic/claude-sonnet-4";
|
|
||||||
};
|
|
||||||
externalSkills = [
|
|
||||||
{ src = inputs.skills-anthropic; }
|
|
||||||
];
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
### `coding.agents.claude-code`
|
|
||||||
|
|
||||||
Claude Code agent deployment from canonical TOML definitions.
|
|
||||||
|
|
||||||
```nix
|
|
||||||
coding.agents.claude-code = {
|
|
||||||
enable = true;
|
|
||||||
agentsInput = inputs.agents;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
### `coding.agents.pi`
|
|
||||||
|
|
||||||
Pi agent deployment from canonical TOML definitions.
|
|
||||||
|
|
||||||
```nix
|
|
||||||
coding.agents.pi = {
|
|
||||||
enable = true;
|
|
||||||
agentsInput = inputs.agents;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
## 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
|
|
||||||
- [Adding Modules](./adding-modules.md) - How to add new NixOS or Home Manager modules
|
|
||||||
- [Templates](../templates.md) - Boilerplate for new packages and modules
|
|
||||||
- [Architecture](../ARCHITECTURE.md) - Understanding module structure
|
|
||||||
- [Contributing](../CONTRIBUTING.md) - Code style and guidelines
|
|
||||||
@@ -1,219 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,312 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,317 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,206 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,272 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,508 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,166 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,229 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
# Packages
|
|
||||||
|
|
||||||
Documentation for packages in m3ta-nixpkgs. Each package directory may contain a `README.md` with detailed documentation.
|
|
||||||
|
|
||||||
## Index
|
|
||||||
|
|
||||||
Packages are organized in `pkgs/<name>/`. Add a `README.md` inside a package directory to document it here.
|
|
||||||
|
|
||||||
### Local Packages
|
|
||||||
|
|
||||||
These packages are built from source in `pkgs/<name>/`:
|
|
||||||
|
|
||||||
| Package | Description | Type | Location |
|
|
||||||
|---------|-------------|------|----------|
|
|
||||||
| `sidecar` | Companion tool for CLI agents with diffs, file trees, and task management | Go | `pkgs/sidecar/` |
|
|
||||||
| `td` | Minimalist CLI for tracking tasks across AI coding sessions | Go | `pkgs/td/` |
|
|
||||||
| `code2prompt` | Convert code to prompts | Go | `pkgs/code2prompt/` |
|
|
||||||
| `eigent` | Eigenvalue tool | Python | `pkgs/eigent/` |
|
|
||||||
| `hyprpaper-random` | Random wallpaper setter for Hyprpaper | Shell | `pkgs/hyprpaper-random/` |
|
|
||||||
| `kestractl` | CLI for Kestra workflow orchestration | Go | `pkgs/kestractl/` |
|
|
||||||
| `launch-webapp` | Launch web applications | Shell | `pkgs/launch-webapp/` |
|
|
||||||
| `mem0` | AI memory assistant with vector storage | Python | `pkgs/mem0/` |
|
|
||||||
| `msty-studio` | Msty Studio application | Python | `pkgs/msty-studio/` |
|
|
||||||
| `openshell` | AI shell assistant | Go | `pkgs/openshell/` |
|
|
||||||
| `openwork` | Open-source Claude Cowork alternative powered by opencode | AppImage | `pkgs/openwork/` |
|
|
||||||
| `pomodoro-timer` | Pomodoro timer utility | Shell | `pkgs/pomodoro-timer/` |
|
|
||||||
| `rofi-project-opener` | Rofi-based project launcher | Shell | `pkgs/rofi-project-opener/` |
|
|
||||||
| `stt-ptt` | Push to Talk Speech to Text | Python | `pkgs/stt-ptt/` |
|
|
||||||
| `tuxedo-backlight` | Backlight control for Tuxedo laptops | C | `pkgs/tuxedo-backlight/` |
|
|
||||||
| `vibetyper` | Typing practice tool | Python | `pkgs/vibetyper/` |
|
|
||||||
| `zellij-ps` | Project switcher for Zellij | Rust | `pkgs/zellij-ps/` |
|
|
||||||
|
|
||||||
### Overlay Modifications
|
|
||||||
|
|
||||||
These entries override upstream nixpkgs packages via `overlays.modifications`. They are also included in `overlays.default`.
|
|
||||||
|
|
||||||
| Package | Source | Modification | Location |
|
|
||||||
|---------|--------|--------------|----------|
|
|
||||||
| `n8n` | `nixpkgs#n8n` | Pins a newer release and fetch hashes | `overlays/mods/n8n.nix` |
|
|
||||||
|
|
||||||
### Pass-Through Packages
|
|
||||||
|
|
||||||
These packages are imported directly from flake inputs with minor modifications:
|
|
||||||
|
|
||||||
| Package | Source | Modification | Location |
|
|
||||||
|---------|--------|-------------|----------|
|
|
||||||
| `opencode-desktop` | `inputs.opencode` | Tauri desktop wrapper + Wayland fix | `pkgs/opencode-desktop/` |
|
|
||||||
|
|
||||||
## Adding Package Documentation
|
|
||||||
|
|
||||||
To document a package in detail, add a `README.md` inside the package directory (e.g., `pkgs/sidecar/README.md`). This guide indexes all packages and provides a quick overview.
|
|
||||||
|
|
||||||
## Automated Updates
|
|
||||||
|
|
||||||
Packages are automatically updated weekly by the Gitea Actions `nix-update` workflow. See the main README for details.
|
|
||||||
|
|
||||||
## Related
|
|
||||||
|
|
||||||
- [Adding Packages](../guides/adding-packages.md) - How to add new packages
|
|
||||||
- [Architecture](../ARCHITECTURE.md) - Repository structure
|
|
||||||
- [Quick Start](../QUICKSTART.md) - Getting started
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
# beads (Removed)
|
|
||||||
|
|
||||||
> **Note**: The `beads` package has been removed from this repository.
|
|
||||||
|
|
||||||
## Why was it removed?
|
|
||||||
|
|
||||||
The beads package was removed as it is no longer actively used.
|
|
||||||
|
|
||||||
## What was beads?
|
|
||||||
|
|
||||||
Beads was a lightweight memory system for AI coding agents with graph-based issue tracking. It provided:
|
|
||||||
- Persistent memory across AI sessions
|
|
||||||
- Graph-based issue tracking with dependencies
|
|
||||||
- Discovered work tracking
|
|
||||||
- Git integration
|
|
||||||
|
|
||||||
If you need beads, you can still build it from source:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone https://github.com/steveyegge/beads
|
|
||||||
cd beads
|
|
||||||
go build ./cmd/bd
|
|
||||||
```
|
|
||||||
@@ -1,206 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,190 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
# kestractl
|
|
||||||
|
|
||||||
CLI for the Kestra workflow orchestration platform.
|
|
||||||
|
|
||||||
## Description
|
|
||||||
|
|
||||||
kestractl is the official command-line interface for [Kestra](https://kestra.io), an open-source workflow orchestration platform. It allows you to interact with Kestra instances to manage flows, trigger executions, inspect namespaces, and automate orchestration tasks from the terminal.
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- 🔄 **Flow Management**: Deploy, inspect, and delete flows
|
|
||||||
- ▶️ **Execution Control**: Trigger and monitor workflow executions
|
|
||||||
- 📁 **Namespace Operations**: Manage Kestra namespaces and their resources
|
|
||||||
- 📂 **Namespace Files**: Upload and manage files in namespace storage
|
|
||||||
- 🌐 **Multi-Environment**: Switch between dev, staging, and production contexts
|
|
||||||
- ⚡ **Pre-built Binary**: No compilation required — fetched directly from GitHub releases
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
### Via Overlay
|
|
||||||
|
|
||||||
```nix
|
|
||||||
{pkgs, ...}: {
|
|
||||||
environment.systemPackages = with pkgs; [
|
|
||||||
kestractl
|
|
||||||
];
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Direct Reference
|
|
||||||
|
|
||||||
```nix
|
|
||||||
{pkgs, ...}: {
|
|
||||||
environment.systemPackages = with pkgs; [
|
|
||||||
inputs.m3ta-nixpkgs.packages.${pkgs.system}.kestractl
|
|
||||||
];
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Run Directly
|
|
||||||
|
|
||||||
```bash
|
|
||||||
nix run git+https://code.m3ta.dev/m3tam3re/nixpkgs#kestractl
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Basic Commands
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Check version
|
|
||||||
kestractl version
|
|
||||||
|
|
||||||
# Show help
|
|
||||||
kestractl --help
|
|
||||||
|
|
||||||
# Connect to a Kestra instance
|
|
||||||
kestractl context set --api-url http://localhost:8080
|
|
||||||
|
|
||||||
# List flows in a namespace
|
|
||||||
kestractl flow list --namespace my.namespace
|
|
||||||
|
|
||||||
# Trigger a flow execution
|
|
||||||
kestractl execution create --namespace my.namespace --flow-id my-flow
|
|
||||||
|
|
||||||
# Monitor executions
|
|
||||||
kestractl execution list --namespace my.namespace
|
|
||||||
```
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
kestractl uses a context system to manage connections to Kestra instances:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Create a context for a local instance
|
|
||||||
kestractl context set local --api-url http://localhost:8080
|
|
||||||
|
|
||||||
# Create a context for a remote instance with auth
|
|
||||||
kestractl context set prod --api-url https://kestra.example.com --token <your-token>
|
|
||||||
|
|
||||||
# Switch active context
|
|
||||||
kestractl context use prod
|
|
||||||
```
|
|
||||||
|
|
||||||
## Build Information
|
|
||||||
|
|
||||||
- **Version**: 1.0.0
|
|
||||||
- **Language**: Go (pre-built binary)
|
|
||||||
- **License**: Apache 2.0
|
|
||||||
- **Source**: [GitHub](https://github.com/kestra-io/kestractl)
|
|
||||||
|
|
||||||
## Platform Support
|
|
||||||
|
|
||||||
- `x86_64-linux`
|
|
||||||
- `aarch64-linux`
|
|
||||||
|
|
||||||
## Package Structure
|
|
||||||
|
|
||||||
This package uses a `sources.json` + `update.sh` pattern for multi-platform binary fetching:
|
|
||||||
|
|
||||||
```
|
|
||||||
pkgs/kestractl/
|
|
||||||
├── default.nix — reads version + hashes from sources.json
|
|
||||||
├── sources.json — per-platform URLs and SRI hashes
|
|
||||||
└── update.sh — fetches latest GitHub release, updates sources.json
|
|
||||||
```
|
|
||||||
|
|
||||||
Updates are handled by `update.sh` (called by the Gitea Actions nix-update workflow), which fetches the latest release from GitHub, downloads each platform's tarball, computes SRI hashes, and rewrites `sources.json`.
|
|
||||||
|
|
||||||
## Related
|
|
||||||
|
|
||||||
- [Kestra Documentation](https://kestra.io/docs)
|
|
||||||
- [kestractl GitHub](https://github.com/kestra-io/kestractl)
|
|
||||||
- [Adding Packages](../guides/adding-packages.md) - How to add new packages
|
|
||||||
- [Quick Start](../QUICKSTART.md) - Getting started guide
|
|
||||||
@@ -1,180 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,268 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,172 +0,0 @@
|
|||||||
# msty-studio
|
|
||||||
|
|
||||||
Msty Studio enables advanced, privacy‑preserving 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
|
|
||||||
@@ -1,302 +0,0 @@
|
|||||||
# 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
|
|
||||||
|
|
||||||
This repository does not publish a standalone `n8n` package. Instead, it provides an overlay that overrides the upstream nixpkgs `n8n` package with a newer pinned release when needed.
|
|
||||||
|
|
||||||
### Via Overlay
|
|
||||||
|
|
||||||
```nix
|
|
||||||
{inputs, pkgs, ...}: {
|
|
||||||
nixpkgs.overlays = [
|
|
||||||
inputs.m3ta-nixpkgs.overlays.default
|
|
||||||
# Or, if you only want package overrides:
|
|
||||||
# inputs.m3ta-nixpkgs.overlays.modifications
|
|
||||||
];
|
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
|
||||||
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
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
# opencode (Deprecated)
|
|
||||||
|
|
||||||
> **Note**: The `opencode` package has been removed from this repository.
|
|
||||||
|
|
||||||
## Why was it removed?
|
|
||||||
|
|
||||||
OpenCode (CLI version) has been removed because there is now a well-maintained upstream repository for AI coding tools:
|
|
||||||
|
|
||||||
**[numtide/llm-agents.nix](https://github.com/numtide/llm-agents.nix)**
|
|
||||||
|
|
||||||
This repository provides Nix packages for various AI coding agents, including OpenCode and others, with active maintenance and updates.
|
|
||||||
|
|
||||||
## What should I use instead?
|
|
||||||
|
|
||||||
Use the [llm-agents.nix](https://github.com/numtide/llm-agents.nix) flake directly:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
{
|
|
||||||
inputs = {
|
|
||||||
llm-agents.url = "github:numtide/llm-agents.nix";
|
|
||||||
};
|
|
||||||
|
|
||||||
outputs = { inputs, ... }: {
|
|
||||||
# Access packages via inputs.llm-agents.packages.${system}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Or run directly:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
nix run github:numtide/llm-agents.nix#opencode
|
|
||||||
```
|
|
||||||
|
|
||||||
## What about opencode-desktop?
|
|
||||||
|
|
||||||
The `opencode-desktop` package remains available in this repository as it includes a Wayland support workaround for [upstream issue #11755](https://github.com/opencode-ai/opencode/issues/11755). Once this issue is resolved upstream, `opencode-desktop` may also be removed in favor of the llm-agents.nix repository.
|
|
||||||
@@ -1,220 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,245 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,202 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,130 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,248 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,204 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,245 +0,0 @@
|
|||||||
# 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"]
|
|
||||||
```
|
|
||||||
|
|
||||||
## 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]` |
|
|
||||||
|
|
||||||
|
|
||||||
## 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
|
|
||||||
@@ -1,498 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,162 +0,0 @@
|
|||||||
# Templates
|
|
||||||
|
|
||||||
Boilerplate templates for quickly adding new packages or modules to m3ta-nixpkgs.
|
|
||||||
|
|
||||||
## Available Templates
|
|
||||||
|
|
||||||
| Template | Command | Creates |
|
|
||||||
|---------|---------|---------|
|
|
||||||
| Package | `nix flake init -t .#package` | `templates/package/` |
|
|
||||||
| NixOS Module | `nix flake init -t .#nixos-module` | `templates/nixos-module/` |
|
|
||||||
| Home Manager Module | `nix flake init -t .#home-manager-module` | `templates/home-manager-module/` |
|
|
||||||
|
|
||||||
## Using Templates
|
|
||||||
|
|
||||||
### 1. List Available Templates
|
|
||||||
|
|
||||||
```bash
|
|
||||||
nix flake show --templates .
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Initialize from a Template
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Package
|
|
||||||
nix flake init -t .#package
|
|
||||||
|
|
||||||
# NixOS Module
|
|
||||||
nix flake init -t .#nixos-module
|
|
||||||
|
|
||||||
# Home Manager Module
|
|
||||||
nix flake init -t .#home-manager-module
|
|
||||||
```
|
|
||||||
|
|
||||||
Note: `nix flake init` copies the template contents into the current directory. Use a subdirectory name:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mkdir new-package && cd new-package
|
|
||||||
nix flake init -t ..#package
|
|
||||||
```
|
|
||||||
|
|
||||||
## Package Template
|
|
||||||
|
|
||||||
Creates a complete package structure:
|
|
||||||
|
|
||||||
```
|
|
||||||
templates/package/
|
|
||||||
├── default.nix # Package definition with comments
|
|
||||||
```
|
|
||||||
|
|
||||||
### Fields to Fill In
|
|
||||||
|
|
||||||
| Field | Location | Notes |
|
|
||||||
|-------|----------|-------|
|
|
||||||
| `pname` | `default.nix` | Package name (kebab-case) |
|
|
||||||
| `version` | `default.nix` | Semantic version |
|
|
||||||
| `src` | `default.nix` | Fetcher (GitHub, URL, Git, etc.) |
|
|
||||||
| `hash` | `default.nix` | Use `lib.fakeHash`, build to get real hash |
|
|
||||||
| `meta.description` | `default.nix` | Short one-line description |
|
|
||||||
| `meta.homepage` | `default.nix` | Project URL |
|
|
||||||
| `meta.license` | `default.nix` | Use `lib.licenses.*` |
|
|
||||||
| `meta.platforms` | `default.nix` | Usually `platforms.linux` |
|
|
||||||
| `meta.mainProgram` | `default.nix` | Main binary name |
|
|
||||||
|
|
||||||
### Common Build Systems
|
|
||||||
|
|
||||||
```nix
|
|
||||||
# Rust (recommended)
|
|
||||||
rustPlatform.buildRustPackage rec { ... }
|
|
||||||
|
|
||||||
# Python
|
|
||||||
python3.pkgs.buildPythonPackage rec { ... }
|
|
||||||
|
|
||||||
# Node.js
|
|
||||||
pkg-config, nodejs, npm2nix, or pnpm + prisma
|
|
||||||
|
|
||||||
# Shell script
|
|
||||||
writeShellScriptBin "name" ''echo hello''
|
|
||||||
|
|
||||||
# Go
|
|
||||||
go mdbook build
|
|
||||||
|
|
||||||
# Generic C/Make
|
|
||||||
stdenv.mkDerivation { ... }
|
|
||||||
```
|
|
||||||
|
|
||||||
See [Adding Packages](./guides/adding-packages.md) for detailed instructions.
|
|
||||||
|
|
||||||
## NixOS Module Template
|
|
||||||
|
|
||||||
Creates a complete NixOS module:
|
|
||||||
|
|
||||||
```
|
|
||||||
templates/nixos-module/
|
|
||||||
├── default.nix # Module with options
|
|
||||||
└── README.md # Module documentation
|
|
||||||
```
|
|
||||||
|
|
||||||
### Fields to Fill In
|
|
||||||
|
|
||||||
| Field | Location | Notes |
|
|
||||||
|-------|----------|-------|
|
|
||||||
| Module name | `default.nix` | File name matches `m3ta.<name>` |
|
|
||||||
| Options | `default.nix` | Add under `options.m3ta.<name>` |
|
|
||||||
| Config | `default.nix` | Add under `config.m3ta.<name>` |
|
|
||||||
| Description | `README.md` | What the module does |
|
|
||||||
|
|
||||||
### After Creating
|
|
||||||
|
|
||||||
1. Add to `modules/nixos/default.nix` imports
|
|
||||||
2. Optionally export from `flake.nix` `nixosModules`
|
|
||||||
3. Add documentation to `docs/modules/nixos/`
|
|
||||||
4. Run `nix flake check`
|
|
||||||
|
|
||||||
## Home Manager Module Template
|
|
||||||
|
|
||||||
Creates a complete Home Manager module:
|
|
||||||
|
|
||||||
```
|
|
||||||
templates/home-manager-module/
|
|
||||||
├── default.nix # Module with options
|
|
||||||
└── README.md # Module documentation
|
|
||||||
```
|
|
||||||
|
|
||||||
### Fields to Fill In
|
|
||||||
|
|
||||||
| Field | Location | Notes |
|
|
||||||
|-------|----------|-------|
|
|
||||||
| Category | Directory | Choose `cli/` or `coding/` |
|
|
||||||
| Options | `default.nix` | Add under `options.m3ta.<name>` |
|
|
||||||
| Config | `default.nix` | Add under `config.m3ta.<name>` |
|
|
||||||
| Description | `README.md` | What the module does |
|
|
||||||
|
|
||||||
### After Creating
|
|
||||||
|
|
||||||
1. Add to the appropriate category aggregator (`cli/default.nix` or `coding/default.nix`)
|
|
||||||
2. Optionally export from `flake.nix` `homeManagerModules`
|
|
||||||
3. Add documentation to `docs/modules/home-manager/`
|
|
||||||
4. Run `nix flake check`
|
|
||||||
|
|
||||||
## Template Variables
|
|
||||||
|
|
||||||
Templates use Nix attribute references. After copying, search for these placeholders:
|
|
||||||
|
|
||||||
| Placeholder | Replace With |
|
|
||||||
|-------------|--------------|
|
|
||||||
| `package-name` | Your package name (kebab-case) |
|
|
||||||
| `owner-name` / `repo-name` | GitHub owner and repo |
|
|
||||||
| `0.1.0` | Initial version |
|
|
||||||
| `lib.fakeHash` | Real hash after first build |
|
|
||||||
| `lib.licenses.mit` | Appropriate license |
|
|
||||||
| `A short description` | One-line description |
|
|
||||||
|
|
||||||
## Automated Updates
|
|
||||||
|
|
||||||
Packages created from templates are automatically updated weekly by the Gitea Actions workflow. See the main README for details on the `nix-update` automation.
|
|
||||||
|
|
||||||
## Related
|
|
||||||
|
|
||||||
- [Adding Packages](./guides/adding-packages.md) - Detailed package guide
|
|
||||||
- [Adding Modules](./guides/adding-modules.md) - Detailed module guide
|
|
||||||
- [Development Workflow](./guides/development-workflow.md) - Local development
|
|
||||||
- [Architecture](./ARCHITECTURE.md) - Repository structure
|
|
||||||
@@ -1,193 +0,0 @@
|
|||||||
# 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;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,153 +0,0 @@
|
|||||||
# 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
-104
@@ -1,104 +0,0 @@
|
|||||||
{
|
|
||||||
"nodes": {
|
|
||||||
"agents": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1780133320,
|
|
||||||
"narHash": "sha256-8AiN9tV9PBb5xblJiPlhumBbKj61qLjzqXXFtkj3vvY=",
|
|
||||||
"ref": "refs/heads/master",
|
|
||||||
"rev": "920c00313ae242bd93275c30131b9ab1e52ee2fb",
|
|
||||||
"revCount": 88,
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://code.m3ta.dev/m3tam3re/AGENTS"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://code.m3ta.dev/m3tam3re/AGENTS"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"basecamp": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1774505501,
|
|
||||||
"narHash": "sha256-7UiRrDptj7yuEFwToOfdunUMz/i3jRLR7CmMoYQjq6k=",
|
|
||||||
"owner": "basecamp",
|
|
||||||
"repo": "basecamp-cli",
|
|
||||||
"rev": "f087e6ef84002503d0dbc75ea1c8c928a8928d9e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "basecamp",
|
|
||||||
"ref": "v0.7.2",
|
|
||||||
"repo": "basecamp-cli",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1782467914,
|
|
||||||
"narHash": "sha256-pGvFkM8N0xEkIIXDe5YYfbEAvHrk4IxBrjB/x8OomhE=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "e73de5be04e0eff4190a1432b946d469c794e7b4",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "nixos-unstable",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs-master": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1782540244,
|
|
||||||
"narHash": "sha256-3skOZJEfAUG7LSB/Ok2AQUiqeagYLSq+8wKjtS1hOyc=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "a65184fc373636356fcaf460dc09655a919c66ea",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "master",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"openspec": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1782291243,
|
|
||||||
"narHash": "sha256-0pVn5pDqlKpqSgzf4eG9TFCjkjzOtnmGTpbILso7GwI=",
|
|
||||||
"owner": "Fission-AI",
|
|
||||||
"repo": "OpenSpec",
|
|
||||||
"rev": "737518b36fe4b6fdb09c83eeaf8d873a428c92e6",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "Fission-AI",
|
|
||||||
"repo": "OpenSpec",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
|
||||||
"inputs": {
|
|
||||||
"agents": "agents",
|
|
||||||
"basecamp": "basecamp",
|
|
||||||
"nixpkgs": "nixpkgs",
|
|
||||||
"nixpkgs-master": "nixpkgs-master",
|
|
||||||
"openspec": "openspec"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": "root",
|
|
||||||
"version": 7
|
|
||||||
}
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
{
|
|
||||||
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";
|
|
||||||
|
|
||||||
basecamp = {
|
|
||||||
url = "github:basecamp/basecamp-cli/v0.7.2";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
};
|
|
||||||
|
|
||||||
# openspec - spec-driven development for AI coding assistants
|
|
||||||
openspec = {
|
|
||||||
url = "github:Fission-AI/OpenSpec";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
};
|
|
||||||
|
|
||||||
# Agent definitions and coding rules
|
|
||||||
agents = {
|
|
||||||
url = "git+https://code.m3ta.dev/m3tam3re/AGENTS";
|
|
||||||
flake = false;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
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 = import ./overlays {inherit inputs;};
|
|
||||||
|
|
||||||
# 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;
|
|
||||||
opencode = import ./modules/home-manager/coding/opencode.nix;
|
|
||||||
agents = import ./modules/home-manager/coding/agents;
|
|
||||||
zellij-ps = import ./modules/home-manager/zellij-ps.nix;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Library functions - helper utilities for your configuration
|
|
||||||
lib = forAllSystems (system: import ./lib {lib = nixpkgs.lib;});
|
|
||||||
|
|
||||||
# Development shells for various programming environments
|
|
||||||
# Usage: nix develop .#<shell-name>
|
|
||||||
# Available shells: default, python, devops, coding
|
|
||||||
devShells = forAllSystems (system: let
|
|
||||||
pkgs = pkgsFor system;
|
|
||||||
in
|
|
||||||
import ./shells {
|
|
||||||
inherit pkgs inputs;
|
|
||||||
agents = inputs.agents;
|
|
||||||
});
|
|
||||||
|
|
||||||
# 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
|
|
||||||
'';
|
|
||||||
n8n-overlay = import ./tests/n8n-overlay-test.nix {
|
|
||||||
inherit pkgs inputs self;
|
|
||||||
};
|
|
||||||
# Lib unit tests
|
|
||||||
lib-agents = import ./tests/lib/agents-test.nix {
|
|
||||||
inherit pkgs;
|
|
||||||
lib = pkgs.lib;
|
|
||||||
};
|
|
||||||
lib-coding-rules = import ./tests/lib/coding-rules-test.nix {
|
|
||||||
inherit pkgs;
|
|
||||||
lib = pkgs.lib;
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
# 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";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
-433
@@ -1,433 +0,0 @@
|
|||||||
# Harness-agnostic agent management utilities
|
|
||||||
#
|
|
||||||
# This module provides functions to load canonical agent definitions and
|
|
||||||
# render them for different AI coding tools (OpenCode, Claude Code, Pi).
|
|
||||||
#
|
|
||||||
# Usage in your configuration:
|
|
||||||
#
|
|
||||||
# let
|
|
||||||
# m3taLib = inputs.m3ta-nixpkgs.lib.${system};
|
|
||||||
# canonical = m3taLib.agents.loadCanonical { agentsInput = inputs.agents; };
|
|
||||||
#
|
|
||||||
# # Render for a specific tool
|
|
||||||
# rendered = m3taLib.agents.renderForOpencode {
|
|
||||||
# inherit pkgs canonical;
|
|
||||||
# modelOverrides = { chiron = "anthropic/claude-sonnet-4"; };
|
|
||||||
# };
|
|
||||||
# in { ... }
|
|
||||||
{lib}: let
|
|
||||||
# ── Shared helpers ─────────────────────────────────────────────
|
|
||||||
# Split a rule string on the LAST colon to get { pattern, action }.
|
|
||||||
# e.g. "rm -rf *:ask" → pattern="rm -rf *", action="ask"
|
|
||||||
# e.g. "/run/agenix/**:deny" → pattern="/run/agenix/**", action="deny"
|
|
||||||
parseRule = ruleStr: let
|
|
||||||
parts = lib.strings.splitString ":" ruleStr;
|
|
||||||
action = lib.last parts;
|
|
||||||
pattern = lib.concatStringsSep ":" (lib.init parts);
|
|
||||||
in {inherit pattern action;};
|
|
||||||
|
|
||||||
# ── Shared renderer primitives ──────────────────────────────────
|
|
||||||
# Render agent files from canonical definitions into a directory.
|
|
||||||
# Each agent gets a "<name>.md" file containing mkContent name agent.
|
|
||||||
#
|
|
||||||
# Args:
|
|
||||||
# pkgs — Nixpkgs package set with linkFarm
|
|
||||||
# canonical — Attribute set of agent definitions (keyed by slug)
|
|
||||||
# mkContent — Function: name: agent → string (file content)
|
|
||||||
# name — Derivation name (e.g. "opencode-agents")
|
|
||||||
#
|
|
||||||
# Returns:
|
|
||||||
# A store path containing all agent *.md files.
|
|
||||||
renderAgentFiles = pkgs: canonical: mkContent: name:
|
|
||||||
pkgs.linkFarm name (
|
|
||||||
lib.mapAttrsToList (n: a: {
|
|
||||||
name = "${n}.md";
|
|
||||||
path = pkgs.writeText "${n}.md" (mkContent n a);
|
|
||||||
})
|
|
||||||
canonical
|
|
||||||
);
|
|
||||||
|
|
||||||
agentsLib = {
|
|
||||||
# ── loadCanonical ─────────────────────────────────────────────
|
|
||||||
#
|
|
||||||
# Load canonical agent definitions from the AGENTS flake input.
|
|
||||||
# Returns the canonical attrset from lib.loadAgents (keyed by slug).
|
|
||||||
|
|
||||||
loadCanonical = {agentsInput}: agentsInput.lib.loadAgents;
|
|
||||||
|
|
||||||
# ── OpenCode renderer ─────────────────────────────────────────
|
|
||||||
#
|
|
||||||
# Produces a directory of agent *.md files suitable for
|
|
||||||
# ~/.config/opencode/agents/ (system-level)
|
|
||||||
# .opencode/agents/ (project-level)
|
|
||||||
#
|
|
||||||
# Each file has YAML frontmatter (description, mode, optional model,
|
|
||||||
# optional permission) followed by the agent's systemPrompt content.
|
|
||||||
# The filename (without .md) becomes the agent name in OpenCode.
|
|
||||||
|
|
||||||
renderForOpencode = {
|
|
||||||
pkgs,
|
|
||||||
canonical,
|
|
||||||
modelOverrides ? {},
|
|
||||||
}: let
|
|
||||||
# Render one permission section to YAML lines.
|
|
||||||
# intent-only → single line: " <tool>: <intent>"
|
|
||||||
# intent+rules → nested block
|
|
||||||
renderPermSection = tool: section:
|
|
||||||
if !(section ? rules) || section.rules == []
|
|
||||||
then [" ${tool}: ${section.intent}"]
|
|
||||||
else let
|
|
||||||
parsedRules = map parseRule section.rules;
|
|
||||||
wildcardLine = " \"*\": ${section.intent}";
|
|
||||||
ruleLines = map (r: " \"${r.pattern}\": ${r.action}") parsedRules;
|
|
||||||
in
|
|
||||||
[" ${tool}:"] ++ [wildcardLine] ++ ruleLines;
|
|
||||||
|
|
||||||
renderPermBlock = permissions:
|
|
||||||
if permissions == {} || permissions == null
|
|
||||||
then []
|
|
||||||
else
|
|
||||||
["permission:"]
|
|
||||||
++ lib.concatLists (
|
|
||||||
lib.mapAttrsToList renderPermSection permissions
|
|
||||||
);
|
|
||||||
|
|
||||||
mkFrontmatter = name: agent: let
|
|
||||||
descLine = "description: \"${agent.description}.\"";
|
|
||||||
modeLine = "mode: ${agent.mode}";
|
|
||||||
modelLine =
|
|
||||||
lib.optionalString
|
|
||||||
(modelOverrides ? ${name})
|
|
||||||
"model: ${modelOverrides.${name}}\n";
|
|
||||||
permBlock = renderPermBlock (agent.permissions or {});
|
|
||||||
permLines =
|
|
||||||
if permBlock == []
|
|
||||||
then ""
|
|
||||||
else lib.concatStringsSep "\n" permBlock + "\n";
|
|
||||||
in "---\n${descLine}\n${modeLine}\n${modelLine}${permLines}---\n";
|
|
||||||
|
|
||||||
mkAgentContent = name: agent:
|
|
||||||
(mkFrontmatter name agent) + agent.systemPrompt;
|
|
||||||
in
|
|
||||||
renderAgentFiles pkgs canonical mkAgentContent "opencode-agents";
|
|
||||||
|
|
||||||
# ── Claude Code renderer ──────────────────────────────────────
|
|
||||||
#
|
|
||||||
# Produces a directory containing:
|
|
||||||
# .claude/agents/<name>.md — one per agent with YAML frontmatter
|
|
||||||
# .claude/settings.json — permission rules in Claude Code DSL
|
|
||||||
#
|
|
||||||
# Claude Code requires:
|
|
||||||
# - name field: [a-z0-9-]+ (kebab-case)
|
|
||||||
# - description field: required
|
|
||||||
# - All agents are subagents (no primary/subagent distinction)
|
|
||||||
|
|
||||||
renderForClaudeCode = {
|
|
||||||
pkgs,
|
|
||||||
canonical,
|
|
||||||
modelOverrides ? {},
|
|
||||||
}: let
|
|
||||||
# Claude Code permission DSL format: "Tool(pattern)" or just "Tool"
|
|
||||||
# Canonical bash rules → "Bash(pattern)" entries
|
|
||||||
# Canonical edit rules → "Edit(pattern)" entries
|
|
||||||
renderPermAllow = permissions: let
|
|
||||||
bashRules =
|
|
||||||
if !(permissions ? bash)
|
|
||||||
then []
|
|
||||||
else if permissions.bash.intent == "allow"
|
|
||||||
then ["Bash"]
|
|
||||||
else
|
|
||||||
map
|
|
||||||
(r: let parsed = parseRule r; in "Bash(${parsed.pattern})")
|
|
||||||
(lib.filter (r: (parseRule r).action == "allow") (permissions.bash.rules or []));
|
|
||||||
editRules =
|
|
||||||
if !(permissions ? edit)
|
|
||||||
then []
|
|
||||||
else if permissions.edit.intent == "allow"
|
|
||||||
then ["Edit"]
|
|
||||||
else
|
|
||||||
map
|
|
||||||
(r: let parsed = parseRule r; in "Edit(${parsed.pattern})")
|
|
||||||
(lib.filter (r: (parseRule r).action == "allow") (permissions.edit.rules or []));
|
|
||||||
webRules =
|
|
||||||
lib.optional (permissions.webfetch.intent or "" == "allow") "WebFetch";
|
|
||||||
in
|
|
||||||
bashRules ++ editRules ++ webRules;
|
|
||||||
|
|
||||||
renderPermDeny = permissions: let
|
|
||||||
bashRules =
|
|
||||||
if !(permissions ? bash)
|
|
||||||
then []
|
|
||||||
else
|
|
||||||
map
|
|
||||||
(r: let parsed = parseRule r; in "Bash(${parsed.pattern})")
|
|
||||||
(lib.filter (r: (parseRule r).action == "deny") (permissions.bash.rules or []));
|
|
||||||
editRules =
|
|
||||||
if !(permissions ? edit)
|
|
||||||
then []
|
|
||||||
else
|
|
||||||
map
|
|
||||||
(r: let parsed = parseRule r; in "Edit(${parsed.pattern})")
|
|
||||||
(lib.filter (r: (parseRule r).action == "deny") (permissions.edit.rules or []));
|
|
||||||
in
|
|
||||||
bashRules ++ editRules;
|
|
||||||
|
|
||||||
# Build YAML frontmatter for one Claude Code agent .md file.
|
|
||||||
mkClaudeFrontmatter = name: agent: let
|
|
||||||
descLine = "description: \"${agent.description}\"";
|
|
||||||
modelLine =
|
|
||||||
lib.optionalString
|
|
||||||
(modelOverrides ? ${name})
|
|
||||||
"model: ${modelOverrides.${name}}\n";
|
|
||||||
skillsLine =
|
|
||||||
if (agent ? skills) && agent.skills != []
|
|
||||||
then "skills:\n" + lib.concatStringsSep "\n" (map (s: " - ${s}") agent.skills) + "\n"
|
|
||||||
else "";
|
|
||||||
in "---\n${descLine}\n${modelLine}${skillsLine}---\n";
|
|
||||||
|
|
||||||
mkClaudeAgentContent = name: agent:
|
|
||||||
(mkClaudeFrontmatter name agent) + agent.systemPrompt;
|
|
||||||
|
|
||||||
agentFiles = renderAgentFiles pkgs canonical mkClaudeAgentContent "claude-code-agent-files";
|
|
||||||
|
|
||||||
# Build settings.json with permission rules aggregated from all agents.
|
|
||||||
allAllows = lib.flatten (lib.mapAttrsToList (_: agent: renderPermAllow (agent.permissions or {})) canonical);
|
|
||||||
allDenies = lib.flatten (lib.mapAttrsToList (_: agent: renderPermDeny (agent.permissions or {})) canonical);
|
|
||||||
|
|
||||||
settingsJson = builtins.toJSON {
|
|
||||||
permissions = {
|
|
||||||
allow = lib.unique (lib.sort (a: b: a < b) allAllows);
|
|
||||||
deny = lib.unique (lib.sort (a: b: a < b) allDenies);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
settingsFile = pkgs.writeText "claude-settings.json" settingsJson;
|
|
||||||
in
|
|
||||||
pkgs.runCommand "claude-code-agents" {} ''
|
|
||||||
mkdir -p $out/.claude/agents
|
|
||||||
cp -r ${agentFiles}/* $out/.claude/agents/
|
|
||||||
cp ${settingsFile} $out/.claude/settings.json
|
|
||||||
'';
|
|
||||||
|
|
||||||
# ── Pi renderer ───────────────────────────────────────────────
|
|
||||||
#
|
|
||||||
# This renderer produces:
|
|
||||||
# AGENTS.md — concatenated agent descriptions + specialist listing
|
|
||||||
# SYSTEM.md — primary agent's system prompt (replaces Pi default)
|
|
||||||
# agents/{name}.md — one per agent for pi-subagents (YAML frontmatter + prompt)
|
|
||||||
#
|
|
||||||
# The agents/ files use pi-subagents frontmatter format:
|
|
||||||
# name, description, tools, extensions, model, thinking, skill,
|
|
||||||
# output, defaultReads, defaultProgress, interactive, maxSubagentDepth
|
|
||||||
|
|
||||||
renderForPi = {
|
|
||||||
pkgs,
|
|
||||||
canonical,
|
|
||||||
modelOverrides ? {},
|
|
||||||
primaryAgent ? null,
|
|
||||||
codingRules ? null,
|
|
||||||
}: let
|
|
||||||
# Import coding-rules lib for concatRulesMd when codingRules is provided
|
|
||||||
codingRulesLib = import ./coding-rules.nix {inherit lib;};
|
|
||||||
# Find the primary agent (there should be exactly one).
|
|
||||||
primaryAgents = lib.filterAttrs (_: a: a.mode == "primary") canonical;
|
|
||||||
primaryNames = lib.attrNames primaryAgents;
|
|
||||||
primaryName =
|
|
||||||
if primaryAgent != null
|
|
||||||
then primaryAgent
|
|
||||||
else if primaryNames == []
|
|
||||||
then throw "lib.agents.renderForPi: no primary agent found"
|
|
||||||
else builtins.head primaryNames;
|
|
||||||
primary = builtins.getAttr primaryName primaryAgents;
|
|
||||||
|
|
||||||
# Subagents for the specialist listing.
|
|
||||||
subagents = lib.filterAttrs (_: a: a.mode != "primary") canonical;
|
|
||||||
|
|
||||||
# ── Permission → Pi tool mapping ──────────────────────────────
|
|
||||||
#
|
|
||||||
# Pi built-in tools: read, bash, edit, write, grep, find, ls,
|
|
||||||
# mcp, subagent, web_search, fetch_content, etc.
|
|
||||||
# Canonical tools: bash, edit, webfetch, websearch, question, external_directory
|
|
||||||
#
|
|
||||||
# We map canonical permissions to Pi's tool list.
|
|
||||||
# intent=allow → include tool; intent=deny → exclude; intent=ask → include (Pi has no ask granularity)
|
|
||||||
# When specific allow rules exist, the tool is always included (Pi can't restrict by pattern).
|
|
||||||
|
|
||||||
piToolsForAgent = agent: let
|
|
||||||
perms = agent.permissions or {};
|
|
||||||
tools = [];
|
|
||||||
# Always available: read (no permission concept in Pi)
|
|
||||||
addIf = tool: section:
|
|
||||||
if section.intent == "allow" || section.intent == "ask"
|
|
||||||
then [tool]
|
|
||||||
else [];
|
|
||||||
# bash → bash
|
|
||||||
withBash = tools ++ (addIf "bash" (perms.bash or {intent = "ask";}));
|
|
||||||
# edit → edit
|
|
||||||
withEdit = withBash ++ (addIf "edit" (perms.edit or {intent = "deny";}));
|
|
||||||
# webfetch → fetch_content
|
|
||||||
withFetch = withEdit ++ (addIf "fetch_content" (perms.webfetch or {intent = "deny";}));
|
|
||||||
# websearch → web_search
|
|
||||||
withSearch = withFetch ++ (addIf "web_search" (perms.websearch or {intent = "deny";}));
|
|
||||||
in
|
|
||||||
lib.unique (withSearch ++ ["read" "grep" "find" "ls"]);
|
|
||||||
|
|
||||||
# ── Build YAML frontmatter for pi-subagents .md files ──────────
|
|
||||||
mkPiFrontmatter = name: agent: let
|
|
||||||
tools = piToolsForAgent agent;
|
|
||||||
descLine = "description: \"${agent.description}\"";
|
|
||||||
toolsLine = "tools: ${lib.concatStringsSep ", " tools}";
|
|
||||||
model =
|
|
||||||
if modelOverrides ? ${name}
|
|
||||||
then "model: ${modelOverrides.${name}}"
|
|
||||||
else "";
|
|
||||||
skillsLine =
|
|
||||||
if (agent ? skills) && agent.skills != []
|
|
||||||
then "skill: ${lib.concatStringsSep ", " agent.skills}"
|
|
||||||
else "";
|
|
||||||
in
|
|
||||||
"---\n"
|
|
||||||
+ "name: ${name}\n"
|
|
||||||
+ "${descLine}\n"
|
|
||||||
+ "${toolsLine}\n"
|
|
||||||
+ (lib.optionalString (model != "") "${model}\n")
|
|
||||||
+ (lib.optionalString (skillsLine != "") "${skillsLine}\n")
|
|
||||||
+ "---\n";
|
|
||||||
|
|
||||||
mkPiAgentContent = name: agent:
|
|
||||||
(mkPiFrontmatter name agent) + agent.systemPrompt;
|
|
||||||
|
|
||||||
piAgentFiles = renderAgentFiles pkgs canonical mkPiAgentContent "pi-agent-files";
|
|
||||||
|
|
||||||
# ── Build AGENTS.md content ───────────────────────────────────
|
|
||||||
primaryDn = primary.display_name or primaryName;
|
|
||||||
specialistEntries = let
|
|
||||||
mkEntry = name: agent: let
|
|
||||||
dn = agent.display_name or name;
|
|
||||||
in
|
|
||||||
"- **" + dn + "**: " + agent.description;
|
|
||||||
in
|
|
||||||
lib.mapAttrsToList mkEntry subagents;
|
|
||||||
# ── Coding rules section (optional) ────────────────────────
|
|
||||||
# When codingRules is provided, append selected rules to AGENTS.md.
|
|
||||||
# codingRules attrset: { agents, languages, concerns, frameworks }
|
|
||||||
codingRulesSection =
|
|
||||||
if codingRules != null
|
|
||||||
then let
|
|
||||||
section = codingRulesLib.mkRulesMdSection codingRules;
|
|
||||||
in
|
|
||||||
if section != ""
|
|
||||||
then "\n" + section
|
|
||||||
else ""
|
|
||||||
else "";
|
|
||||||
|
|
||||||
agentsMd =
|
|
||||||
"# Agent Instructions\n"
|
|
||||||
+ "\n"
|
|
||||||
+ "## "
|
|
||||||
+ primaryDn
|
|
||||||
+ "\n"
|
|
||||||
+ "\n"
|
|
||||||
+ primary.description
|
|
||||||
+ "\n"
|
|
||||||
+ "\n"
|
|
||||||
+ (
|
|
||||||
if subagents == {}
|
|
||||||
then ""
|
|
||||||
else "## Available Specialists\n\n" + lib.concatStringsSep "\n" specialistEntries + "\n"
|
|
||||||
)
|
|
||||||
+ codingRulesSection;
|
|
||||||
|
|
||||||
agentsMdFile = pkgs.writeText "AGENTS.md" agentsMd;
|
|
||||||
systemMdFile = pkgs.writeText "SYSTEM.md" primary.systemPrompt;
|
|
||||||
in
|
|
||||||
pkgs.runCommand "pi-agents" {} ''
|
|
||||||
mkdir -p $out/agents
|
|
||||||
cp ${agentsMdFile} $out/AGENTS.md
|
|
||||||
cp ${systemMdFile} $out/SYSTEM.md
|
|
||||||
cp -r ${piAgentFiles}/* $out/agents/
|
|
||||||
'';
|
|
||||||
|
|
||||||
# ── renderForTool dispatcher ──────────────────────────────────
|
|
||||||
#
|
|
||||||
# Dispatches to the correct renderer by tool name.
|
|
||||||
# tool: "opencode" | "claude-code" | "pi"
|
|
||||||
|
|
||||||
renderForTool = {
|
|
||||||
pkgs,
|
|
||||||
agentsInput,
|
|
||||||
tool,
|
|
||||||
modelOverrides ? {},
|
|
||||||
codingRules ? null,
|
|
||||||
}: let
|
|
||||||
canonical = agentsInput.lib.loadAgents;
|
|
||||||
in
|
|
||||||
if tool == "opencode"
|
|
||||||
then
|
|
||||||
agentsLib.renderForOpencode {
|
|
||||||
inherit pkgs canonical modelOverrides;
|
|
||||||
}
|
|
||||||
else if tool == "claude-code"
|
|
||||||
then
|
|
||||||
agentsLib.renderForClaudeCode {
|
|
||||||
inherit pkgs canonical modelOverrides;
|
|
||||||
}
|
|
||||||
else if tool == "pi"
|
|
||||||
then
|
|
||||||
agentsLib.renderForPi {
|
|
||||||
inherit pkgs canonical modelOverrides codingRules;
|
|
||||||
}
|
|
||||||
else throw "lib.agents.renderForTool: unknown tool '${tool}'. Must be opencode, claude-code, or pi.";
|
|
||||||
|
|
||||||
# ── shellHookForTool ──────────────────────────────────────────
|
|
||||||
#
|
|
||||||
# Generates a shellHook string for use in devShells that symlinks
|
|
||||||
# rendered agent files into the project directory.
|
|
||||||
#
|
|
||||||
# Usage:
|
|
||||||
# devShells.default = pkgs.mkShell {
|
|
||||||
# shellHook = m3taLib.agents.shellHookForTool {
|
|
||||||
# inherit pkgs;
|
|
||||||
# agentsInput = inputs.agents;
|
|
||||||
# tool = "opencode";
|
|
||||||
# modelOverrides = { chiron = "anthropic/claude-sonnet-4"; };
|
|
||||||
# };
|
|
||||||
# };
|
|
||||||
|
|
||||||
shellHookForTool = {
|
|
||||||
pkgs,
|
|
||||||
agentsInput,
|
|
||||||
tool,
|
|
||||||
modelOverrides ? {},
|
|
||||||
codingRules ? null,
|
|
||||||
}: let
|
|
||||||
rendered = agentsLib.renderForTool {
|
|
||||||
inherit pkgs agentsInput tool modelOverrides codingRules;
|
|
||||||
};
|
|
||||||
in
|
|
||||||
if tool == "opencode"
|
|
||||||
then ''
|
|
||||||
# Agent files for OpenCode
|
|
||||||
mkdir -p .opencode/agents
|
|
||||||
ln -sfn ${rendered}/* .opencode/agents/
|
|
||||||
''
|
|
||||||
else if tool == "claude-code"
|
|
||||||
then ''
|
|
||||||
# Agent files for Claude Code
|
|
||||||
mkdir -p .claude/agents
|
|
||||||
ln -sfn ${rendered}/.claude/agents/* .claude/agents/
|
|
||||||
ln -sfn ${rendered}/.claude/settings.json .claude/settings.json
|
|
||||||
''
|
|
||||||
else if tool == "pi"
|
|
||||||
then ''
|
|
||||||
# Agent files for Pi
|
|
||||||
ln -sfn ${rendered}/AGENTS.md AGENTS.md
|
|
||||||
mkdir -p .pi
|
|
||||||
ln -sfn ${rendered}/SYSTEM.md .pi/SYSTEM.md
|
|
||||||
mkdir -p .pi/agents
|
|
||||||
ln -sfn ${rendered}/agents/* .pi/agents/
|
|
||||||
''
|
|
||||||
else throw "lib.agents.shellHookForTool: unknown tool '${tool}'";
|
|
||||||
};
|
|
||||||
in
|
|
||||||
agentsLib
|
|
||||||
@@ -1,233 +0,0 @@
|
|||||||
# Coding 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.coding-rules.mkCodingRules {
|
|
||||||
# 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
|
|
||||||
# - A `coding-rules.json` file with a $schema reference and instructions list
|
|
||||||
# - (Optional) Appends coding rules to `AGENTS.md` for Pi agent discovery
|
|
||||||
#
|
|
||||||
# The instructions list contains paths relative to the project root, all prefixed
|
|
||||||
# with `.opencode-rules/`, making them portable across different project locations.
|
|
||||||
{lib}: let
|
|
||||||
# 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)
|
|
||||||
# forPi: Whether to also append rules to AGENTS.md for Pi agent (default: true)
|
|
||||||
# Pi discovers AGENTS.md files by walking parent dirs + cwd and concatenates them.
|
|
||||||
# When enabled, a delimited block is appended to (or created in) AGENTS.md.
|
|
||||||
#
|
|
||||||
# Returns:
|
|
||||||
# An attribute set containing:
|
|
||||||
# - shellHook: Bash code to create symlink and coding-rules.json
|
|
||||||
# - instructions: List of rule file paths (relative to project root)
|
|
||||||
#
|
|
||||||
# Example:
|
|
||||||
# mkCodingRules {
|
|
||||||
# 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"
|
|
||||||
# # ];
|
|
||||||
# # }
|
|
||||||
mkCodingRules = {
|
|
||||||
agents,
|
|
||||||
languages ? [],
|
|
||||||
concerns ? [
|
|
||||||
"coding-style"
|
|
||||||
"naming"
|
|
||||||
"documentation"
|
|
||||||
"testing"
|
|
||||||
"git-workflow"
|
|
||||||
"project-structure"
|
|
||||||
],
|
|
||||||
frameworks ? [],
|
|
||||||
extraInstructions ? [],
|
|
||||||
rulesDir ? ".opencode-rules",
|
|
||||||
forPi ? false,
|
|
||||||
}: let
|
|
||||||
# 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 coding rules
|
|
||||||
rulesConfig = {
|
|
||||||
"$schema" = "https://opencode.ai/config.json";
|
|
||||||
inherit instructions;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Pi rules content (concatenated markdown) — only computed when forPi is true
|
|
||||||
piRulesSection =
|
|
||||||
if forPi
|
|
||||||
then mkRulesMdSection {inherit agents languages concerns frameworks;}
|
|
||||||
else "";
|
|
||||||
|
|
||||||
# Bash snippet to append rules to AGENTS.md for Pi discovery.
|
|
||||||
# Uses HTML comment markers for idempotent updates:
|
|
||||||
# - Removes any existing CODING-RULES block
|
|
||||||
# - Appends the new block
|
|
||||||
# - Creates AGENTS.md if it doesn't exist
|
|
||||||
# Note: Uses plain if-then-else instead of lib.optionalString to avoid
|
|
||||||
# forcing the `lib` argument (which may come from import <nixpkgs/lib>)
|
|
||||||
# when forPi is false.
|
|
||||||
piShellHook =
|
|
||||||
if forPi && piRulesSection != ""
|
|
||||||
then ''
|
|
||||||
# Pi agent: append coding rules to AGENTS.md
|
|
||||||
if [ -f AGENTS.md ]; then
|
|
||||||
# Remove existing coding-rules block (if any)
|
|
||||||
sed -i '/<!-- CODING-RULES:START -->/,/<!-- CODING-RULES:END -->/d' AGENTS.md
|
|
||||||
# Append new coding-rules block
|
|
||||||
cat >> AGENTS.md <<'PIRULES_EOF'
|
|
||||||
${piRulesSection}
|
|
||||||
PIRULES_EOF
|
|
||||||
else
|
|
||||||
# Create AGENTS.md with just the coding rules
|
|
||||||
cat > AGENTS.md <<'PIRULES_EOF'
|
|
||||||
${piRulesSection}
|
|
||||||
PIRULES_EOF
|
|
||||||
fi
|
|
||||||
''
|
|
||||||
else "";
|
|
||||||
in {
|
|
||||||
inherit instructions;
|
|
||||||
|
|
||||||
# Shell hook to set up rules in the project
|
|
||||||
# Creates a symlink to the AGENTS rules directory and generates coding-rules.json
|
|
||||||
# Optionally appends rules to AGENTS.md for Pi agent discovery
|
|
||||||
shellHook = ''
|
|
||||||
# Create/update symlink to AGENTS rules directory
|
|
||||||
ln -sfn ${agents}/rules ${rulesDir}
|
|
||||||
|
|
||||||
# Generate coding-rules.json configuration file
|
|
||||||
cat > coding-rules.json <<'RULES_EOF'
|
|
||||||
${builtins.toJSON rulesConfig}
|
|
||||||
RULES_EOF
|
|
||||||
|
|
||||||
${piShellHook}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
# Concatenate selected rule files from the AGENTS repository into a single
|
|
||||||
# markdown string. Used by Pi (append to AGENTS.md) and could be used by
|
|
||||||
# other tools that don't support an instructions list.
|
|
||||||
#
|
|
||||||
# Args:
|
|
||||||
# agents: Path to the AGENTS repository (non-flake input)
|
|
||||||
# languages: Optional list of language-specific rules to include
|
|
||||||
# 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
|
|
||||||
#
|
|
||||||
# Returns: A single concatenated markdown string with all selected rules.
|
|
||||||
#
|
|
||||||
# Example:
|
|
||||||
# concatRulesMd {
|
|
||||||
# agents = inputs.agents;
|
|
||||||
# languages = [ "python" ];
|
|
||||||
# concerns = [ "coding-style" ];
|
|
||||||
# }
|
|
||||||
# # Returns: "\n# Coding Style\n\n...python rules...\n"
|
|
||||||
concatRulesMd = {
|
|
||||||
agents,
|
|
||||||
languages ? [],
|
|
||||||
concerns ? [
|
|
||||||
"coding-style"
|
|
||||||
"naming"
|
|
||||||
"documentation"
|
|
||||||
"testing"
|
|
||||||
"git-workflow"
|
|
||||||
"project-structure"
|
|
||||||
],
|
|
||||||
frameworks ? [],
|
|
||||||
}: let
|
|
||||||
rulePaths =
|
|
||||||
(map (c: {
|
|
||||||
kind = "concerns";
|
|
||||||
name = c;
|
|
||||||
})
|
|
||||||
concerns)
|
|
||||||
++ (map (l: {
|
|
||||||
kind = "languages";
|
|
||||||
name = l;
|
|
||||||
})
|
|
||||||
languages)
|
|
||||||
++ (map (f: {
|
|
||||||
kind = "frameworks";
|
|
||||||
name = f;
|
|
||||||
})
|
|
||||||
frameworks);
|
|
||||||
|
|
||||||
readRule = rule: builtins.readFile "${agents}/rules/${rule.kind}/${rule.name}.md";
|
|
||||||
ruleContents = map readRule rulePaths;
|
|
||||||
in
|
|
||||||
lib.concatStringsSep "\n\n" ruleContents;
|
|
||||||
|
|
||||||
# Build a coding rules section suitable for appending to AGENTS.md.
|
|
||||||
# Wraps concatRulesMd output with a header and HTML comment markers
|
|
||||||
# for idempotent updates in project-level shellHooks.
|
|
||||||
#
|
|
||||||
# Args: Same as concatRulesMd
|
|
||||||
#
|
|
||||||
# Returns: A markdown string with start/end markers and a header.
|
|
||||||
mkRulesMdSection = args: let
|
|
||||||
content = concatRulesMd args;
|
|
||||||
in
|
|
||||||
if builtins.stringLength content == 0
|
|
||||||
then ""
|
|
||||||
else ''
|
|
||||||
<!-- CODING-RULES:START -->
|
|
||||||
# Coding Rules
|
|
||||||
|
|
||||||
${content}
|
|
||||||
<!-- CODING-RULES:END -->
|
|
||||||
'';
|
|
||||||
in {
|
|
||||||
inherit mkCodingRules concatRulesMd mkRulesMdSection;
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# 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;};
|
|
||||||
|
|
||||||
# Coding rules injection utilities
|
|
||||||
coding-rules = import ./coding-rules.nix {inherit lib;};
|
|
||||||
|
|
||||||
# Agent configuration management utilities
|
|
||||||
agents = import ./agents.nix {inherit lib;};
|
|
||||||
}
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
# 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;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,235 +0,0 @@
|
|||||||
# 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
|
|
||||||
├── opencode.nix # OpenCode non-agent config (theme, plugins, formatter)
|
|
||||||
└── agents/ # Per-tool agent deployment (canonical TOML → rendered)
|
|
||||||
├── default.nix
|
|
||||||
├── opencode.nix # File-based agents + skills + context
|
|
||||||
├── claude-code.nix # Claude Code agents + settings.json
|
|
||||||
└── pi.nix # Pi AGENTS.md + SYSTEM.md
|
|
||||||
```
|
|
||||||
|
|
||||||
## 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` |
|
|
||||||
| Add agent renderer | `coding/agents/<tool>.nix`, import in `coding/agents/default.nix` |
|
|
||||||
|
|
||||||
## Option Namespaces
|
|
||||||
|
|
||||||
- `cli.*` - CLI tools (e.g., `cli.zellij-ps.enable`)
|
|
||||||
- `coding.editors.*` - Editor configs (e.g., `coding.editors.neovim.enable`)
|
|
||||||
- `coding.opencode.*` - OpenCode non-agent config (theme, plugins, formatter)
|
|
||||||
- `coding.agents.opencode.*` - OpenCode agent deployment (file-based agents)
|
|
||||||
- `coding.agents.claude-code.*` - Claude Code agent deployment
|
|
||||||
- `coding.agents.pi.*` - Pi agent deployment
|
|
||||||
- `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 |
|
|
||||||
|
|
||||||
## Agent Modules
|
|
||||||
|
|
||||||
Agent definitions are stored as canonical `agent.toml` + `system-prompt.md` in the
|
|
||||||
[AGENTS repo](https://code.m3ta.dev/m3tam3re/AGENTS). Renderers in `lib/agents.nix`
|
|
||||||
transform these into tool-specific configs. Each tool has its own HM sub-module
|
|
||||||
under `coding/agents/`.
|
|
||||||
|
|
||||||
### OpenCode (`coding.agents.opencode`)
|
|
||||||
|
|
||||||
Renders file-based agents to `~/.config/opencode/agents/*.md`:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
coding.agents.opencode = {
|
|
||||||
enable = true;
|
|
||||||
agentsInput = inputs.agents;
|
|
||||||
modelOverrides = {
|
|
||||||
chiron = "anthropic/claude-sonnet-4";
|
|
||||||
};
|
|
||||||
externalSkills = [
|
|
||||||
{ src = inputs.skills-anthropic; }
|
|
||||||
];
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
**Options:** `enable`, `agentsInput`, `modelOverrides`, `externalSkills`
|
|
||||||
|
|
||||||
### Claude Code (`coding.agents.claude-code`)
|
|
||||||
|
|
||||||
Renders agents to `~/.claude/agents/*.md` + `~/.claude/settings.json`:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
coding.agents.claude-code = {
|
|
||||||
enable = true;
|
|
||||||
agentsInput = inputs.agents;
|
|
||||||
modelOverrides = {};
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
**Options:** `enable`, `agentsInput`, `modelOverrides`
|
|
||||||
|
|
||||||
### Pi (`coding.agents.pi`)
|
|
||||||
|
|
||||||
Renders `AGENTS.md` + `SYSTEM.md` to `~/.pi/agent/`:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
coding.agents.pi = {
|
|
||||||
enable = true;
|
|
||||||
agentsInput = inputs.agents;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
**Options:** `enable`, `agentsInput`
|
|
||||||
|
|
||||||
### Project-level usage
|
|
||||||
|
|
||||||
For per-project agent setup via `flake.nix` + `direnv`:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
m3taLib.agents.shellHookForTool {
|
|
||||||
inherit pkgs;
|
|
||||||
agentsInput = inputs.agents;
|
|
||||||
tool = "opencode";
|
|
||||||
modelOverrides = { chiron = "anthropic/claude-sonnet-4"; };
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
## Migration Guide (OpenCode agents)
|
|
||||||
|
|
||||||
The agent system was migrated from embedded `agents.json` to file-based canonical
|
|
||||||
`agent.toml` definitions. Here is how to migrate your home-manager config.
|
|
||||||
|
|
||||||
### What changed
|
|
||||||
|
|
||||||
| Before | After |
|
|
||||||
|--------|-------|
|
|
||||||
| `coding.opencode.agentsInput` | `coding.agents.opencode.agentsInput` |
|
|
||||||
| `coding.opencode.externalSkills` | `coding.agents.opencode.externalSkills` |
|
|
||||||
| Agents embedded in `config.json` | File-based `~/.config/opencode/agents/*.md` |
|
|
||||||
| Model hardcoded in `agents.json` | Per-machine `modelOverrides` |
|
|
||||||
| `mkOpencodeRules` | `mkCodingRules` |
|
|
||||||
|
|
||||||
### Migration steps
|
|
||||||
|
|
||||||
**1. Update home-manager config:**
|
|
||||||
|
|
||||||
Move `agentsInput` and `externalSkills` from `coding.opencode` to `coding.agents.opencode`.
|
|
||||||
Add `modelOverrides` with the models previously hardcoded in agents.json:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
# BEFORE (legacy):
|
|
||||||
coding.opencode = {
|
|
||||||
enable = true;
|
|
||||||
agentsInput = inputs.agents;
|
|
||||||
externalSkills = [{ src = inputs.skills-anthropic; }];
|
|
||||||
ohMyOpencodeSettings = { ... };
|
|
||||||
};
|
|
||||||
|
|
||||||
# AFTER (new):
|
|
||||||
coding.opencode = {
|
|
||||||
enable = true;
|
|
||||||
ohMyOpencodeSettings = { ... };
|
|
||||||
};
|
|
||||||
|
|
||||||
coding.agents.opencode = {
|
|
||||||
enable = true;
|
|
||||||
agentsInput = inputs.agents;
|
|
||||||
externalSkills = [{ src = inputs.skills-anthropic; }];
|
|
||||||
modelOverrides = {
|
|
||||||
chiron = "zai-coding-plan/glm-5";
|
|
||||||
"chiron-forge" = "zai-coding-plan/glm-5";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
**2. Run `home-manager switch`:**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
home-manager switch --flake .
|
|
||||||
```
|
|
||||||
|
|
||||||
**3. Verify agents are deployed:**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ls ~/.config/opencode/agents/
|
|
||||||
# Should show: chiron.md chiron-forge.md hermes.md athena.md apollo.md calliope.md
|
|
||||||
```
|
|
||||||
|
|
||||||
**4. Remove legacy files from AGENTS repo** (after confirming everything works):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /home/m3tam3re/p/AI/AGENTS
|
|
||||||
rm agents/agents.json
|
|
||||||
rm prompts/chiron.txt prompts/chiron-forge.txt prompts/hermes.txt \
|
|
||||||
prompts/athena.txt prompts/apollo.txt prompts/calliope.txt
|
|
||||||
rmdir prompts/ # if empty
|
|
||||||
# Also remove lib.agentsJson from flake.nix
|
|
||||||
```
|
|
||||||
|
|
||||||
**5. Final cleanup:** After legacy files are removed from AGENTS repo,
|
|
||||||
remove `lib.agentsJson` from the AGENTS `flake.nix` (it's only needed for
|
|
||||||
backward compatibility during the transition).
|
|
||||||
|
|
||||||
### Key advantage of the new system
|
|
||||||
|
|
||||||
Prompt changes no longer require `home-manager switch`. Since agents are
|
|
||||||
deployed as file-based `~/.config/opencode/agents/*.md` (symlinks to Nix store),
|
|
||||||
you only need to edit the `system-prompt.md` in the AGENTS repo, commit, update
|
|
||||||
the flake lock, and run `home-manager switch`. Or for local development, edit
|
|
||||||
the file directly and restart the tool.
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
# CLI/Terminal-related Home Manager modules
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
./rofi-project-opener.nix
|
|
||||||
./stt-ptt.nix
|
|
||||||
./zellij-ps.nix
|
|
||||||
];
|
|
||||||
}
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
{
|
|
||||||
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}"
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,158 +0,0 @@
|
|||||||
{
|
|
||||||
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
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
{
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
imports = [
|
|
||||||
./shared/default.nix
|
|
||||||
];
|
|
||||||
|
|
||||||
options.coding.agents.claude-code = let
|
|
||||||
shared = import ./shared/shared-options.nix {inherit lib;};
|
|
||||||
mcpCfg = config.programs.mcp or null;
|
|
||||||
in
|
|
||||||
with lib; {
|
|
||||||
enable = mkEnableOption "Claude Code agent management via canonical agent.toml definitions";
|
|
||||||
|
|
||||||
agentsInput = shared.mkAgentsInputOption ''
|
|
||||||
The `agents` flake input (your personal AGENTS repo).
|
|
||||||
When set, agents are rendered from canonical agent.toml files
|
|
||||||
and symlinked to ~/.claude/agents/.
|
|
||||||
'';
|
|
||||||
|
|
||||||
modelOverrides = shared.mkModelOverridesOption;
|
|
||||||
|
|
||||||
externalSkills = shared.externalSkillsOption;
|
|
||||||
|
|
||||||
mcpServers = mkOption {
|
|
||||||
type = types.attrsOf types.anything;
|
|
||||||
default =
|
|
||||||
if mcpCfg != null
|
|
||||||
then mcpCfg.servers
|
|
||||||
else {};
|
|
||||||
defaultText = literalExpression "config.programs.mcp.servers";
|
|
||||||
description = ''
|
|
||||||
MCP server configurations for Claude Code.
|
|
||||||
Merged into ~/.claude/settings.json alongside permissions.
|
|
||||||
Automatically inherits from config.programs.mcp.servers.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = with lib; let
|
|
||||||
shared = import ./shared/shared-options.nix {inherit lib;};
|
|
||||||
cfg = config.coding.agents.claude-code;
|
|
||||||
agentsLib = (import ../../../../lib {inherit lib;}).agents;
|
|
||||||
in
|
|
||||||
mkIf cfg.enable (let
|
|
||||||
# Rendered agents + permissions (only if agentsInput is set)
|
|
||||||
rendered = mkIf (cfg.agentsInput != null) (
|
|
||||||
agentsLib.renderForClaudeCode {
|
|
||||||
inherit pkgs;
|
|
||||||
canonical = cfg.agentsInput.lib.loadAgents;
|
|
||||||
modelOverrides = cfg.modelOverrides;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
# Merge MCP servers into the rendered settings.json.
|
|
||||||
# The renderer produces { permissions: { allow, deny } }.
|
|
||||||
# We add mcpServers on top.
|
|
||||||
settingsJson =
|
|
||||||
if cfg.agentsInput != null
|
|
||||||
then let
|
|
||||||
renderedSettings = builtins.fromJSON (builtins.readFile "${rendered}/.claude/settings.json");
|
|
||||||
withMcp =
|
|
||||||
if cfg.mcpServers != {}
|
|
||||||
then renderedSettings // {mcpServers = cfg.mcpServers;}
|
|
||||||
else renderedSettings;
|
|
||||||
in
|
|
||||||
pkgs.writeText "claude-settings.json" (builtins.toJSON withMcp)
|
|
||||||
else if cfg.mcpServers != {}
|
|
||||||
then pkgs.writeText "claude-settings.json" (builtins.toJSON {mcpServers = cfg.mcpServers;})
|
|
||||||
else null;
|
|
||||||
in {
|
|
||||||
# Rendered agent files symlinked to ~/.claude/agents/
|
|
||||||
home.file.".claude/agents" = mkIf (cfg.agentsInput != null) {
|
|
||||||
source = "${rendered}/.claude/agents";
|
|
||||||
};
|
|
||||||
|
|
||||||
# Skills (merged from personal AGENTS repo + optional external skills)
|
|
||||||
home.file.".claude/skills" = mkIf (cfg.agentsInput != null) {
|
|
||||||
source = cfg.agentsInput.lib.mkSkills {
|
|
||||||
inherit pkgs;
|
|
||||||
customSkills = "${cfg.agentsInput}/skills";
|
|
||||||
externalSkills = shared.mapExternalSkills cfg.externalSkills;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# Rendered settings.json with permissions + MCP servers
|
|
||||||
home.file.".claude/settings.json" = mkIf (settingsJson != null) {
|
|
||||||
source = "${settingsJson}";
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
# Per-tool agent sub-modules
|
|
||||||
# Each module handles rendering canonical agent.toml definitions
|
|
||||||
# for a specific AI coding tool.
|
|
||||||
#
|
|
||||||
# Also provides the shared coding.agents.skills submodule that writes
|
|
||||||
# ~/.agents/skills — the central skills directory used by Pi, OpenCode, etc.
|
|
||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}: let
|
|
||||||
shared = import ./shared/shared-options.nix {inherit lib;};
|
|
||||||
cfg = config.coding.agents.skills;
|
|
||||||
mkIf = lib.mkIf;
|
|
||||||
in {
|
|
||||||
imports = [
|
|
||||||
./opencode.nix
|
|
||||||
./claude-code.nix
|
|
||||||
./pi.nix
|
|
||||||
];
|
|
||||||
|
|
||||||
options.coding.agents.skills = {
|
|
||||||
agentsInput = shared.mkAgentsInputOption ''
|
|
||||||
The `agents` flake input (your personal AGENTS repo).
|
|
||||||
When set, skills are symlinked to ~/.agents/skills.
|
|
||||||
'';
|
|
||||||
|
|
||||||
externalSkills = shared.externalSkillsOption;
|
|
||||||
};
|
|
||||||
|
|
||||||
config = mkIf (cfg.agentsInput != null) {
|
|
||||||
home.file.".agents/skills".source = cfg.agentsInput.lib.mkSkills {
|
|
||||||
inherit pkgs;
|
|
||||||
customSkills = "${cfg.agentsInput}/skills";
|
|
||||||
externalSkills = shared.mapExternalSkills cfg.externalSkills;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
imports = [
|
|
||||||
./shared/default.nix
|
|
||||||
];
|
|
||||||
|
|
||||||
options.coding.agents.opencode = let
|
|
||||||
shared = import ./shared/shared-options.nix {inherit lib;};
|
|
||||||
in
|
|
||||||
with lib; {
|
|
||||||
enable = mkEnableOption "OpenCode agent management via canonical agent.toml definitions";
|
|
||||||
|
|
||||||
agentsInput = shared.mkAgentsInputOption ''
|
|
||||||
The `agents` flake input (your personal AGENTS repo).
|
|
||||||
When set, agents are rendered from canonical agent.toml files
|
|
||||||
and symlinked to ~/.config/opencode/agents/.
|
|
||||||
'';
|
|
||||||
|
|
||||||
modelOverrides = shared.mkModelOverridesOption;
|
|
||||||
};
|
|
||||||
|
|
||||||
config = with lib; let
|
|
||||||
shared = import ./shared/shared-options.nix {inherit lib;};
|
|
||||||
cfg = config.coding.agents.opencode;
|
|
||||||
in
|
|
||||||
mkIf cfg.enable {
|
|
||||||
# Rendered agent files symlinked to ~/.config/opencode/agents/
|
|
||||||
xdg.configFile."opencode/agents" = let
|
|
||||||
agentsLib = (import ../../../../lib {inherit lib;}).agents;
|
|
||||||
in
|
|
||||||
mkIf (cfg.agentsInput != null) {
|
|
||||||
source = agentsLib.renderForOpencode {
|
|
||||||
inherit pkgs;
|
|
||||||
canonical = cfg.agentsInput.lib.loadAgents;
|
|
||||||
modelOverrides = cfg.modelOverrides;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# Static config dirs from AGENTS repo
|
|
||||||
xdg.configFile."opencode/context" = mkIf (cfg.agentsInput != null) {
|
|
||||||
source = "${cfg.agentsInput}/context";
|
|
||||||
};
|
|
||||||
xdg.configFile."opencode/commands" = mkIf (cfg.agentsInput != null) {
|
|
||||||
source = "${cfg.agentsInput}/commands";
|
|
||||||
};
|
|
||||||
xdg.configFile."opencode/prompts" = mkIf (cfg.agentsInput != null) {
|
|
||||||
source = "${cfg.agentsInput}/prompts";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,357 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
imports = [
|
|
||||||
./shared/default.nix
|
|
||||||
];
|
|
||||||
|
|
||||||
options.coding.agents.pi = let
|
|
||||||
shared = import ./shared/shared-options.nix {inherit lib;};
|
|
||||||
mcpCfg = config.programs.mcp or null;
|
|
||||||
in
|
|
||||||
with lib; {
|
|
||||||
enable = mkEnableOption "Pi agent management via canonical agent.toml definitions";
|
|
||||||
|
|
||||||
mcpServers = mkOption {
|
|
||||||
type = types.attrsOf types.anything;
|
|
||||||
default =
|
|
||||||
if mcpCfg != null
|
|
||||||
then mcpCfg.servers
|
|
||||||
else {};
|
|
||||||
defaultText = literalExpression "config.programs.mcp.servers";
|
|
||||||
description = ''
|
|
||||||
MCP server configurations for Pi (pi-mcp-adapter).
|
|
||||||
Written to ~/.pi/agent/mcp.json.
|
|
||||||
Automatically inherits from config.programs.mcp.servers.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
agentsInput = shared.mkAgentsInputOption ''
|
|
||||||
The `agents` flake input (your personal AGENTS repo).
|
|
||||||
When set, the primary agent's system prompt is rendered as SYSTEM.md,
|
|
||||||
all agents are listed in AGENTS.md, and subagent .md files are deployed.
|
|
||||||
'';
|
|
||||||
|
|
||||||
modelOverrides = shared.mkModelOverridesOption;
|
|
||||||
|
|
||||||
primaryAgent = mkOption {
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = null;
|
|
||||||
description = ''
|
|
||||||
Override which canonical agent is used as primary for SYSTEM.md.
|
|
||||||
When null, the first agent with mode="primary" is used.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
codingRules = mkOption {
|
|
||||||
type = types.nullOr (types.submodule {
|
|
||||||
options = {
|
|
||||||
languages = mkOption {
|
|
||||||
type = types.listOf types.str;
|
|
||||||
default = [];
|
|
||||||
description = ''
|
|
||||||
Language-specific coding rules to include
|
|
||||||
(e.g. [ "python" "typescript" "nix" ]).
|
|
||||||
Rule files are read from the AGENTS repo's rules/languages/ directory.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
concerns = mkOption {
|
|
||||||
type = types.listOf types.str;
|
|
||||||
default = [
|
|
||||||
"coding-style"
|
|
||||||
"naming"
|
|
||||||
"documentation"
|
|
||||||
"testing"
|
|
||||||
"git-workflow"
|
|
||||||
"project-structure"
|
|
||||||
];
|
|
||||||
description = ''
|
|
||||||
Concern rules to include from the AGENTS repo's rules/concerns/ directory.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
frameworks = mkOption {
|
|
||||||
type = types.listOf types.str;
|
|
||||||
default = [];
|
|
||||||
description = ''
|
|
||||||
Framework-specific coding rules to include
|
|
||||||
(e.g. [ "react" "fastapi" ]).
|
|
||||||
Rule files are read from the AGENTS repo's rules/frameworks/ directory.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
});
|
|
||||||
default = null;
|
|
||||||
description = ''
|
|
||||||
Coding rules to inject into ~/.pi/agent/AGENTS.md.
|
|
||||||
Rules are read from the AGENTS repository and appended as markdown sections.
|
|
||||||
Requires agentsInput to be set.
|
|
||||||
'';
|
|
||||||
example = literalExpression ''
|
|
||||||
{
|
|
||||||
languages = [ "python" "typescript" ];
|
|
||||||
concerns = [ "coding-style" "testing" ];
|
|
||||||
frameworks = [ "fastapi" ];
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
settings = mkOption {
|
|
||||||
type = types.submodule {
|
|
||||||
freeformType = types.attrsOf types.anything;
|
|
||||||
options = {
|
|
||||||
packages = mkOption {
|
|
||||||
type = types.listOf types.str;
|
|
||||||
default = [];
|
|
||||||
description = ''
|
|
||||||
Pi packages to install (npm:, git:, or local paths).
|
|
||||||
These are written to ~/.pi/agent/settings.json.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
defaultProvider = mkOption {
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = null;
|
|
||||||
description = "Default LLM provider (e.g. 'anthropic', 'openai', 'zai').";
|
|
||||||
};
|
|
||||||
|
|
||||||
defaultModel = mkOption {
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = null;
|
|
||||||
description = "Default model ID.";
|
|
||||||
};
|
|
||||||
|
|
||||||
defaultThinkingLevel = mkOption {
|
|
||||||
type = types.nullOr (types.enum ["off" "minimal" "low" "medium" "high" "xhigh"]);
|
|
||||||
default = null;
|
|
||||||
description = "Default extended thinking level.";
|
|
||||||
};
|
|
||||||
|
|
||||||
theme = mkOption {
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = null;
|
|
||||||
description = "Pi theme name.";
|
|
||||||
};
|
|
||||||
|
|
||||||
hideThinkingBlock = mkOption {
|
|
||||||
type = types.nullOr types.bool;
|
|
||||||
default = null;
|
|
||||||
description = "Hide thinking blocks in output.";
|
|
||||||
};
|
|
||||||
|
|
||||||
quietStartup = mkOption {
|
|
||||||
type = types.nullOr types.bool;
|
|
||||||
default = null;
|
|
||||||
description = "Hide startup header.";
|
|
||||||
};
|
|
||||||
|
|
||||||
compaction = mkOption {
|
|
||||||
type = types.nullOr (types.submodule {
|
|
||||||
options = {
|
|
||||||
enabled = mkOption {
|
|
||||||
type = types.nullOr types.bool;
|
|
||||||
default = null;
|
|
||||||
};
|
|
||||||
reserveTokens = mkOption {
|
|
||||||
type = types.nullOr types.int;
|
|
||||||
default = null;
|
|
||||||
};
|
|
||||||
keepRecentTokens = mkOption {
|
|
||||||
type = types.nullOr types.int;
|
|
||||||
default = null;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
});
|
|
||||||
default = null;
|
|
||||||
description = "Auto-compaction settings.";
|
|
||||||
};
|
|
||||||
|
|
||||||
enabledModels = mkOption {
|
|
||||||
type = types.nullOr (types.listOf types.str);
|
|
||||||
default = null;
|
|
||||||
description = "Model patterns for Ctrl+P cycling.";
|
|
||||||
};
|
|
||||||
|
|
||||||
sessionDir = mkOption {
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = null;
|
|
||||||
description = "Directory where session files are stored.";
|
|
||||||
};
|
|
||||||
|
|
||||||
extensions = mkOption {
|
|
||||||
type = types.listOf types.str;
|
|
||||||
default = [];
|
|
||||||
description = "Local extension file paths or directories.";
|
|
||||||
};
|
|
||||||
|
|
||||||
skills = mkOption {
|
|
||||||
type = types.listOf types.str;
|
|
||||||
default = [];
|
|
||||||
description = "Local skill file paths or directories.";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
default = {};
|
|
||||||
description = ''
|
|
||||||
Pi settings written to ~/.pi/agent/settings.json.
|
|
||||||
Only non-null values are included in the generated JSON.
|
|
||||||
See pi docs/settings.md for all options.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# ── Pi Guardrails ─────────────────────────────────────────────
|
|
||||||
guardrails = mkOption {
|
|
||||||
type = types.nullOr (types.submodule {
|
|
||||||
options = {
|
|
||||||
enable =
|
|
||||||
mkEnableOption
|
|
||||||
("Generate ~/.pi/agent/extensions/guardrails.json for pi-guardrails. "
|
|
||||||
+ "Adds @aliou/pi-guardrails to packages automatically.");
|
|
||||||
|
|
||||||
config = mkOption {
|
|
||||||
type = types.attrsOf types.anything;
|
|
||||||
default = {};
|
|
||||||
description = ''
|
|
||||||
Guardrails configuration written to ~/.pi/agent/extensions/guardrails.json.
|
|
||||||
See https://github.com/aliou/pi-guardrails for config schema.
|
|
||||||
|
|
||||||
IMPORTANT: Path access checks are lexical (not symlink-safe).
|
|
||||||
Local project .pi/extensions/guardrails.json can override same rule IDs
|
|
||||||
(memory > local > global > defaults). For immutable global policies,
|
|
||||||
consider a wrapper or upstream patch.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
});
|
|
||||||
default = null;
|
|
||||||
description = ''
|
|
||||||
Pi Guardrails security configuration.
|
|
||||||
Generates ~/.pi/agent/extensions/guardrails.json when enabled.
|
|
||||||
The @aliou/pi-guardrails package is added to settings.packages automatically.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = with lib; let
|
|
||||||
shared = import ./shared/shared-options.nix {inherit lib;};
|
|
||||||
cfg = config.coding.agents.pi;
|
|
||||||
in
|
|
||||||
mkIf cfg.enable (let
|
|
||||||
# Build settings.json by filtering out null values recursively
|
|
||||||
filterNulls = attrs:
|
|
||||||
lib.filterAttrs (_: v: v != null) (
|
|
||||||
builtins.mapAttrs (_: v:
|
|
||||||
if builtins.isAttrs v
|
|
||||||
then let
|
|
||||||
filtered = filterNulls v;
|
|
||||||
in
|
|
||||||
if filtered == {}
|
|
||||||
then null
|
|
||||||
else filtered
|
|
||||||
else v)
|
|
||||||
attrs
|
|
||||||
);
|
|
||||||
|
|
||||||
# Base settings (already filtered)
|
|
||||||
piSettings = filterNulls cfg.settings;
|
|
||||||
|
|
||||||
# Guardrails package to inject when guardrails is enabled
|
|
||||||
guardrailsPackage = "npm:@aliou/pi-guardrails@0.11.1";
|
|
||||||
|
|
||||||
# Guardrails config (only when guardrails is enabled)
|
|
||||||
guardrailsJson =
|
|
||||||
if (cfg.guardrails != null && cfg.guardrails.enable)
|
|
||||||
then builtins.toJSON cfg.guardrails.config
|
|
||||||
else null;
|
|
||||||
|
|
||||||
# Merge guardrails package into settings.packages when guardrails is enabled
|
|
||||||
piSettingsWithGuardrails = let
|
|
||||||
baseSettings = cfg.settings;
|
|
||||||
basePackages = baseSettings.packages or [];
|
|
||||||
hasGuardrailsPackage =
|
|
||||||
lib.any
|
|
||||||
(p:
|
|
||||||
lib.hasPrefix "npm:@aliou/pi-guardrails" p
|
|
||||||
|| (lib.hasPrefix "git:" p && lib.hasSuffix "/pi-guardrails" p))
|
|
||||||
basePackages;
|
|
||||||
packagesWithGuardrails =
|
|
||||||
if (cfg.guardrails != null && cfg.guardrails.enable && !hasGuardrailsPackage)
|
|
||||||
then basePackages ++ [guardrailsPackage]
|
|
||||||
else basePackages;
|
|
||||||
in
|
|
||||||
if packagesWithGuardrails != basePackages
|
|
||||||
then filterNulls (baseSettings // {packages = packagesWithGuardrails;})
|
|
||||||
else piSettings;
|
|
||||||
|
|
||||||
# Coding rules config for renderForPi (only when both agentsInput and codingRules are set)
|
|
||||||
piCodingRules =
|
|
||||||
if cfg.agentsInput != null && cfg.codingRules != null
|
|
||||||
then cfg.codingRules // {agents = cfg.agentsInput;}
|
|
||||||
else null;
|
|
||||||
|
|
||||||
# Rendered agents (only computed when agentsInput is set)
|
|
||||||
rendered =
|
|
||||||
if cfg.agentsInput != null
|
|
||||||
then
|
|
||||||
(import ../../../../lib {inherit lib;}).agents.renderForPi {
|
|
||||||
inherit pkgs;
|
|
||||||
canonical = cfg.agentsInput.lib.loadAgents;
|
|
||||||
modelOverrides = cfg.modelOverrides;
|
|
||||||
primaryAgent = cfg.primaryAgent;
|
|
||||||
codingRules = piCodingRules;
|
|
||||||
}
|
|
||||||
else null;
|
|
||||||
|
|
||||||
# Dynamic home.file entries for agent .md files
|
|
||||||
agentFiles =
|
|
||||||
if cfg.agentsInput != null
|
|
||||||
then let
|
|
||||||
agentNames = builtins.attrNames cfg.agentsInput.lib.loadAgents;
|
|
||||||
in
|
|
||||||
builtins.listToAttrs (
|
|
||||||
map (name: {
|
|
||||||
name = ".pi/agent/agents/${name}.md";
|
|
||||||
value = {source = "${rendered}/agents/${name}.md";};
|
|
||||||
})
|
|
||||||
agentNames
|
|
||||||
)
|
|
||||||
else {};
|
|
||||||
in {
|
|
||||||
home.file = mkMerge [
|
|
||||||
# ── MCP servers from programs.mcp → ~/.pi/agent/mcp.json ───────
|
|
||||||
(mkIf (cfg.mcpServers != {}) {
|
|
||||||
".pi/agent/mcp.json".text = builtins.toJSON {mcpServers = cfg.mcpServers;};
|
|
||||||
".pi/agent/mcp.json".force = true;
|
|
||||||
})
|
|
||||||
|
|
||||||
# ── ~/.pi/agent/settings.json ──────────────────────────────────
|
|
||||||
{
|
|
||||||
".pi/agent/settings.json".text = builtins.toJSON piSettingsWithGuardrails;
|
|
||||||
".pi/agent/settings.json".force = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
# ── pi-guardrails config ─────────────────────────────────────
|
|
||||||
(mkIf (guardrailsJson != null) {
|
|
||||||
".pi/agent/extensions/guardrails.json".text = guardrailsJson;
|
|
||||||
".pi/agent/extensions/guardrails.json".force = true;
|
|
||||||
})
|
|
||||||
|
|
||||||
# ── AGENTS.md — agent descriptions and specialist listing ──────
|
|
||||||
(mkIf (cfg.agentsInput != null) {
|
|
||||||
".pi/agent/AGENTS.md".source = "${rendered}/AGENTS.md";
|
|
||||||
})
|
|
||||||
|
|
||||||
# ── SYSTEM.md — primary agent's system prompt ──────────────────
|
|
||||||
(mkIf (cfg.agentsInput != null) {
|
|
||||||
".pi/agent/SYSTEM.md".source = "${rendered}/SYSTEM.md";
|
|
||||||
})
|
|
||||||
|
|
||||||
# ── Agents — pi-subagents .md files ────────────────────────────
|
|
||||||
agentFiles
|
|
||||||
];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
# Shared agent module exports
|
|
||||||
# Imports all shared modules for the coding.agents namespace.
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
./git-identity.nix
|
|
||||||
];
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
# Git identity module for agent commits.
|
|
||||||
# Sets GIT_AUTHOR_*, GIT_COMMITTER_*, and GIT_SSH_COMMAND environment variables.
|
|
||||||
{
|
|
||||||
pkgs,
|
|
||||||
lib,
|
|
||||||
config,
|
|
||||||
...
|
|
||||||
}: let
|
|
||||||
cfg = config.coding.agents.gitIdentity;
|
|
||||||
in {
|
|
||||||
options.coding.agents.gitIdentity = {
|
|
||||||
enable = lib.mkEnableOption ''
|
|
||||||
Agent Git identity for commits. When enabled, sets GIT_AUTHOR_* and
|
|
||||||
GIT_COMMITTER_* environment variables for consistent bot identity.
|
|
||||||
'';
|
|
||||||
|
|
||||||
name = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "m3ta-chiron";
|
|
||||||
description = "Git user name for agent commits.";
|
|
||||||
example = "m3ta-chiron";
|
|
||||||
};
|
|
||||||
|
|
||||||
email = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "m3ta-chiron@agentmail.to";
|
|
||||||
description = "Git email for agent commits.";
|
|
||||||
example = "m3ta-chiron@agentmail.to";
|
|
||||||
};
|
|
||||||
|
|
||||||
signingKey = lib.mkOption {
|
|
||||||
type = lib.types.nullOr lib.types.path;
|
|
||||||
default = null;
|
|
||||||
description = ''
|
|
||||||
Optional GPG signing key for verified commits.
|
|
||||||
Set to null to disable signing.
|
|
||||||
'';
|
|
||||||
example = "/home/user/.gnupg/sign_key.gpg";
|
|
||||||
};
|
|
||||||
|
|
||||||
sshKey = lib.mkOption {
|
|
||||||
type = lib.types.path;
|
|
||||||
description = ''
|
|
||||||
Path to SSH private key for git push authentication.
|
|
||||||
Use agenix-managed paths like /run/agenix/m3ta-chiron-ssh-key
|
|
||||||
for secure secret management.
|
|
||||||
'';
|
|
||||||
example = "/run/agenix/m3ta-chiron-ssh-key";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
home.sessionVariables = {
|
|
||||||
# Git author/committer identity
|
|
||||||
GIT_AUTHOR_NAME = cfg.name;
|
|
||||||
GIT_AUTHOR_EMAIL = cfg.email;
|
|
||||||
GIT_COMMITTER_NAME = cfg.name;
|
|
||||||
GIT_COMMITTER_EMAIL = cfg.email;
|
|
||||||
|
|
||||||
# SSH command for git push
|
|
||||||
GIT_SSH_COMMAND = "ssh -i ${cfg.sshKey} -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
# Shared option definitions for agent modules.
|
|
||||||
# Prevents copy-pasting the externalSkills submodule across opencode/claude-code/pi.
|
|
||||||
{lib}: let
|
|
||||||
inherit (lib) mkOption mkEnableOption types literalExpression;
|
|
||||||
in {
|
|
||||||
# Common agentsInput option used by all agent modules.
|
|
||||||
mkAgentsInputOption = description:
|
|
||||||
mkOption {
|
|
||||||
type = types.nullOr types.anything;
|
|
||||||
default = null;
|
|
||||||
inherit description;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Common modelOverrides option.
|
|
||||||
mkModelOverridesOption = mkOption {
|
|
||||||
type = types.attrsOf types.str;
|
|
||||||
default = {};
|
|
||||||
description = ''
|
|
||||||
Per-agent model overrides. Maps agent slug to model string.
|
|
||||||
Example: { chiron = "anthropic/claude-sonnet-4"; }
|
|
||||||
'';
|
|
||||||
example = literalExpression ''
|
|
||||||
{
|
|
||||||
chiron = "anthropic/claude-sonnet-4";
|
|
||||||
"chiron-forge" = "anthropic/claude-sonnet-4";
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# External skills submodule — used by opencode, claude-code, and pi modules.
|
|
||||||
externalSkillsOption = mkOption {
|
|
||||||
type = types.listOf (types.submodule {
|
|
||||||
options = {
|
|
||||||
src = mkOption {
|
|
||||||
type = types.anything;
|
|
||||||
description = "Flake input pointing to a skills repository root.";
|
|
||||||
};
|
|
||||||
skillsDir = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "skills";
|
|
||||||
description = ''
|
|
||||||
Subdirectory inside src that contains skill folders.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
selectSkills = mkOption {
|
|
||||||
type = types.nullOr (types.listOf types.str);
|
|
||||||
default = null;
|
|
||||||
description = ''
|
|
||||||
List of skill names to cherry-pick from this source.
|
|
||||||
null means include every skill found in skillsDir.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
});
|
|
||||||
default = [];
|
|
||||||
description = ''
|
|
||||||
External skill sources passed to mkSkills.
|
|
||||||
Each entry maps directly to an element of the externalSkills
|
|
||||||
list accepted by the AGENTS flake's lib.mkSkills.
|
|
||||||
'';
|
|
||||||
example = literalExpression ''
|
|
||||||
[
|
|
||||||
{ src = inputs.skills-anthropic; selectSkills = [ "claude-api" ]; }
|
|
||||||
{ src = inputs.basecamp; }
|
|
||||||
]
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# Helper to map externalSkills from module config to mkSkills format.
|
|
||||||
mapExternalSkills = cfgEntries:
|
|
||||||
map (
|
|
||||||
entry:
|
|
||||||
{inherit (entry) src skillsDir;}
|
|
||||||
// lib.optionalAttrs (entry.selectSkills != null) {inherit (entry) selectSkills;}
|
|
||||||
)
|
|
||||||
cfgEntries;
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
# Coding-related Home Manager modules
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
./editors.nix
|
|
||||||
./opencode.nix
|
|
||||||
./agents
|
|
||||||
];
|
|
||||||
}
|
|
||||||
@@ -1,240 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
options,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
with lib; let
|
|
||||||
cfg = config.coding.editors;
|
|
||||||
# home-manager 26.05+ renamed extraLuaConfig → initLua.
|
|
||||||
# On stable 25.11 initLua does not exist; fall back to extraLuaConfig.
|
|
||||||
hasInitLua = options.programs.neovim ? initLua;
|
|
||||||
lazyVimConfig = ''
|
|
||||||
-- 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")
|
|
||||||
'';
|
|
||||||
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 (mkMerge [
|
|
||||||
{
|
|
||||||
programs.neovim = {
|
|
||||||
enable = true;
|
|
||||||
defaultEditor = true;
|
|
||||||
viAlias = true;
|
|
||||||
vimAlias = true;
|
|
||||||
vimdiffAlias = true;
|
|
||||||
withNodeJs = true;
|
|
||||||
withPython3 = true;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
# Use initLua on HM 26.05+ (unstable), extraLuaConfig on HM ≤ 25.11 (stable)
|
|
||||||
(
|
|
||||||
if hasInitLua
|
|
||||||
then {programs.neovim.initLua = lazyVimConfig;}
|
|
||||||
else {programs.neovim.extraLuaConfig = lazyVimConfig;}
|
|
||||||
)
|
|
||||||
]))
|
|
||||||
# Zed editor configuration
|
|
||||||
(mkIf cfg.zed.enable {
|
|
||||||
programs.zed-editor = {
|
|
||||||
enable = true;
|
|
||||||
userSettings = {
|
|
||||||
# CLI Behavior
|
|
||||||
cli_default_open_behavior = "existing_window";
|
|
||||||
# UI and Theme
|
|
||||||
theme = "Dracula";
|
|
||||||
ui_font_size = 16;
|
|
||||||
buffer_font_size = 16;
|
|
||||||
buffer_font_family = "FiraCode Nerd Font";
|
|
||||||
# Agent UI
|
|
||||||
agent_ui_font_size = 24.0;
|
|
||||||
# Editor Behavior
|
|
||||||
vim_mode = true;
|
|
||||||
auto_update = false;
|
|
||||||
format_on_save = "on";
|
|
||||||
load_direnv = "shell_hook";
|
|
||||||
# AI Features
|
|
||||||
features = {
|
|
||||||
copilot = false;
|
|
||||||
inline_prediction_provider = "zed";
|
|
||||||
};
|
|
||||||
edit_predictions = {
|
|
||||||
mode = "subtle";
|
|
||||||
provider = "zed";
|
|
||||||
};
|
|
||||||
show_edit_predictions = true;
|
|
||||||
agent_servers = {
|
|
||||||
"pi-acp" = {
|
|
||||||
type = "registry";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
agent = {
|
|
||||||
dock = "right";
|
|
||||||
default_profile = "ask";
|
|
||||||
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";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
rust_analyzer = {
|
|
||||||
binary = {
|
|
||||||
path_lookup = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
pyrefly = {
|
|
||||||
binary = {
|
|
||||||
arguments = ["--lsp"];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
# Panel Layout
|
|
||||||
project_panel = {
|
|
||||||
dock = "left";
|
|
||||||
};
|
|
||||||
outline_panel = {
|
|
||||||
dock = "left";
|
|
||||||
};
|
|
||||||
collaboration_panel = {
|
|
||||||
dock = "left";
|
|
||||||
};
|
|
||||||
git_panel = {
|
|
||||||
dock = "left";
|
|
||||||
};
|
|
||||||
# Privacy
|
|
||||||
telemetry = {
|
|
||||||
metrics = false;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
})
|
|
||||||
# SSH Connections
|
|
||||||
(mkIf cfg.zed.enable {
|
|
||||||
programs.zed-editor.userSettings.ssh_connections = [
|
|
||||||
{
|
|
||||||
nickname = "m3-atlas";
|
|
||||||
host = "152.53.85.162";
|
|
||||||
args = ["-i" "~/.ssh/m3tam3re"];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
nickname = "self-host-playbook";
|
|
||||||
host = "95.217.189.186";
|
|
||||||
port = 2222;
|
|
||||||
args = ["-i" "~/.ssh/self-host-playbook"];
|
|
||||||
projects = [
|
|
||||||
{
|
|
||||||
paths = ["/etc/nixos/current-systemconfig"];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
nickname = "m3-daedalus";
|
|
||||||
host = "192.168.1.152";
|
|
||||||
port = 22;
|
|
||||||
args = ["-i" "~/.ssh/m3tam3re"];
|
|
||||||
projects = [
|
|
||||||
{
|
|
||||||
paths = ["/home/m3tam3re/home-config"];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
})
|
|
||||||
# Common packages (always installed if either editor is enabled)
|
|
||||||
(mkIf (cfg.neovim.enable || cfg.zed.enable) {
|
|
||||||
home.packages = with pkgs; [zig];
|
|
||||||
})
|
|
||||||
];
|
|
||||||
}
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
with lib; let
|
|
||||||
cfg = config.coding.opencode;
|
|
||||||
in {
|
|
||||||
options.coding.opencode = {
|
|
||||||
enable = mkEnableOption "opencode AI coding assistant";
|
|
||||||
|
|
||||||
ohMyOpencodeSettings = mkOption {
|
|
||||||
type = types.attrs;
|
|
||||||
default = {};
|
|
||||||
description = ''
|
|
||||||
Attributes merged (via recursiveUpdate) on top of the default
|
|
||||||
oh-my-opencode.json. Use this to set provider-specific model
|
|
||||||
assignments per machine.
|
|
||||||
'';
|
|
||||||
example = literalExpression ''
|
|
||||||
{
|
|
||||||
agents.sisyphus.model = "anthropic/claude-opus-4-5";
|
|
||||||
categories.ultrabrain.model = "anthropic/claude-opus-4-5";
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
extraSettings = mkOption {
|
|
||||||
type = types.attrs;
|
|
||||||
default = {};
|
|
||||||
description = ''
|
|
||||||
Extra opencode settings merged (via mkMerge) into
|
|
||||||
programs.opencode.settings. Use this to add provider
|
|
||||||
configuration that is specific to a machine or organisation.
|
|
||||||
'';
|
|
||||||
example = literalExpression ''
|
|
||||||
{
|
|
||||||
provider.anthropic = {
|
|
||||||
name = "Anthropic";
|
|
||||||
models."claude-opus-4-5" = { limit.context = 200000; };
|
|
||||||
};
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
extraPlugins = mkOption {
|
|
||||||
type = types.listOf types.str;
|
|
||||||
default = [];
|
|
||||||
description = ''
|
|
||||||
Additional opencode plugins to add to the plugin list.
|
|
||||||
Each entry is a path or package name passed to opencode's plugin array.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
programs.opencode = {
|
|
||||||
enable = true;
|
|
||||||
enableMcpIntegration = true;
|
|
||||||
settings = mkMerge [
|
|
||||||
{
|
|
||||||
theme = "opencode";
|
|
||||||
plugin = ["oh-my-openagent"] ++ cfg.extraPlugins;
|
|
||||||
formatter = {
|
|
||||||
alejandra = {
|
|
||||||
command = ["alejandra" "-q" "-"];
|
|
||||||
extensions = [".nix"];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
cfg.extraSettings
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
home.file.".config/opencode/oh-my-opencode.json".text = builtins.toJSON (
|
|
||||||
recursiveUpdate
|
|
||||||
{
|
|
||||||
"$schema" = "https://raw.githubusercontent.com/code-yeongyu/oh-my-opencode/master/assets/oh-my-opencode.schema.json";
|
|
||||||
google_auth = false;
|
|
||||||
disabled_mcps = ["context7" "websearch"];
|
|
||||||
}
|
|
||||||
cfg.ohMyOpencodeSettings
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
# Home Manager modules organized by category
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
./cli
|
|
||||||
./coding
|
|
||||||
./ports.nix
|
|
||||||
];
|
|
||||||
}
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
# 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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
# 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
|
|
||||||
# };
|
|
||||||
}
|
|
||||||
@@ -1,363 +0,0 @@
|
|||||||
# 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];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
# 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;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
{inputs, ...}: let
|
|
||||||
# Package modifications for upstream nixpkgs packages.
|
|
||||||
modifications = final: prev: {
|
|
||||||
n8n = import ./mods/n8n.nix {inherit prev;};
|
|
||||||
};
|
|
||||||
in {
|
|
||||||
# Default overlay: adds all custom packages and applies package modifications.
|
|
||||||
default = final: prev:
|
|
||||||
import ../pkgs {
|
|
||||||
pkgs = final;
|
|
||||||
inherit inputs;
|
|
||||||
}
|
|
||||||
// (modifications final prev);
|
|
||||||
|
|
||||||
inherit modifications;
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
{prev}:
|
|
||||||
prev.n8n.overrideAttrs (finalAttrs: previousAttrs: {
|
|
||||||
version = "2.29.4";
|
|
||||||
|
|
||||||
src = prev.fetchFromGitHub {
|
|
||||||
owner = "n8n-io";
|
|
||||||
repo = "n8n";
|
|
||||||
tag = "n8n@${finalAttrs.version}";
|
|
||||||
hash = "sha256-Vc10fXKn21PSlv6Sk+5zyi2efkKup1Vi+9+vyJd2I1k=";
|
|
||||||
};
|
|
||||||
|
|
||||||
pnpmDeps = prev.fetchPnpmDeps {
|
|
||||||
inherit (finalAttrs) pname version src;
|
|
||||||
pnpm = prev.pnpm_10;
|
|
||||||
fetcherVersion = 3;
|
|
||||||
hash = "sha256-2UFKP5bo06afaMPD+dIYQ7O0NiyZai4i8vkidi7HfxE=";
|
|
||||||
};
|
|
||||||
|
|
||||||
meta =
|
|
||||||
previousAttrs.meta
|
|
||||||
// {
|
|
||||||
changelog = "https://github.com/n8n-io/n8n/releases/tag/n8n@${finalAttrs.version}";
|
|
||||||
};
|
|
||||||
})
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
# 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)
|
|
||||||
@@ -1,130 +0,0 @@
|
|||||||
# crunch
|
|
||||||
|
|
||||||
Voice-notified reminders and AI crunch jobs via systemd transient timers. Schedules tasks that fire through `talk` (ElevenLabs TTS) — no NixOS rebuild needed, survives reboots.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Simple voice reminders
|
|
||||||
|
|
||||||
```bash
|
|
||||||
crunch at "14:30" "Müll rausbringen"
|
|
||||||
crunch at "2026-07-03 10:00" "Zahnarzttermin"
|
|
||||||
crunch in "30m" "Build checken"
|
|
||||||
crunch daily "09:00" "Daily standup"
|
|
||||||
crunch weekly "Mon 09:00" "Weekly review"
|
|
||||||
crunch weekly "Montag 09:00" "Weekly review" # German day names
|
|
||||||
```
|
|
||||||
|
|
||||||
### AI crunch jobs
|
|
||||||
|
|
||||||
Runs a prompt through `pi` or `opencode` in print mode, pipes result to `talk`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
crunch ai pi in "1h" "Fasse die neuesten Commits zusammen"
|
|
||||||
crunch ai opencode daily "08:00" "Review offene Issues und gib 3 Key-Points"
|
|
||||||
crunch ai pi weekly "Mon 09:00" "Generiere Weekly Summary aus git log"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Custom script jobs
|
|
||||||
|
|
||||||
Runs any shell script on schedule. Script stdout → `talk`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
crunch script daily "08:00" ~/scripts/basecamp-daily.sh
|
|
||||||
crunch script in "2h" ~/scripts/deploy-check.sh -- --verbose
|
|
||||||
crunch script weekly "Mon 09:00" ~/scripts/weekly-report.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
Example script:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
#!/usr/bin/env bash
|
|
||||||
# ~/scripts/basecamp-daily.sh
|
|
||||||
TODOS=$(basecamp todos --today 2>/dev/null) || exit 0
|
|
||||||
echo "$TODOS" | pi -p "Erstelle Summary als ~/reports/daily.md. Antworte mit Top 3."
|
|
||||||
```
|
|
||||||
|
|
||||||
### Management
|
|
||||||
|
|
||||||
```bash
|
|
||||||
crunch list # List active jobs
|
|
||||||
crunch cancel crunch-mll-rausbringen-12345 # Cancel a job
|
|
||||||
crunch purge # Remove fired one-shot jobs
|
|
||||||
```
|
|
||||||
|
|
||||||
## Command Reference
|
|
||||||
|
|
||||||
```
|
|
||||||
crunch at <time> <message> One-shot (14:30 or "2026-07-03 14:30")
|
|
||||||
crunch in <duration> <message> One-shot after delay (30m, 2h, 1h30m)
|
|
||||||
crunch daily <time> <message> Recurring daily
|
|
||||||
crunch weekly <day> <time> <message> Recurring weekly (Mon/Montag)
|
|
||||||
crunch ai <engine> <type> <time> <prompt> AI crunch (pi|opencode)
|
|
||||||
crunch script <type> <time> <script.sh> [args] Custom script → talk
|
|
||||||
crunch list List active jobs
|
|
||||||
crunch cancel <name> Cancel a job
|
|
||||||
crunch purge Remove fired one-shot jobs
|
|
||||||
```
|
|
||||||
|
|
||||||
## Day Names
|
|
||||||
|
|
||||||
Supports English and German:
|
|
||||||
|
|
||||||
| English | German | systemd |
|
|
||||||
|---|---|---|
|
|
||||||
| Mon, Monday | Mo, Montag | Mon |
|
|
||||||
| Tue, Tuesday | Di, Dienstag | Tue |
|
|
||||||
| Wed, Wednesday | Mi, Mittwoch | Wed |
|
|
||||||
| Thu, Thursday | Do, Donnerstag | Thu |
|
|
||||||
| Fri, Friday | Fr, Freitag | Fri |
|
|
||||||
| Sat, Saturday | Sa, Samstag | Sat |
|
|
||||||
| Sun, Sunday | So, Sonntag | Sun |
|
|
||||||
|
|
||||||
## Environment Variables
|
|
||||||
|
|
||||||
| Variable | Required | Default | Description |
|
|
||||||
|---|---|---|---|
|
|
||||||
| `ELEVENLABS_API_KEY` | ✅ | — | Required by `talk` |
|
|
||||||
| `VOICE_NOTIFY` | ❌ | `1` | `0` silences talk globally |
|
|
||||||
| `TALK` | ❌ | `talk` | Override path to talk binary |
|
|
||||||
|
|
||||||
## How It Works
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────────┐
|
|
||||||
│ systemd --user transient timer fires │
|
|
||||||
│ │
|
|
||||||
│ crunch _say "message" │
|
|
||||||
│ └─ talk "message" (TTS via ElevenLabs) │
|
|
||||||
│ │
|
|
||||||
│ crunch _ai pi "prompt" │
|
|
||||||
│ └─ pi -p "prompt" | talk (AI → TTS) │
|
|
||||||
│ │
|
|
||||||
│ crunch _script ~/script.sh │
|
|
||||||
│ └─ bash ~/script.sh | talk (pipe → TTS)│
|
|
||||||
└─────────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
Uses `systemd-run --user` to create transient `.timer` + `.service` units. No NixOS rebuild needed — jobs are created and managed at runtime.
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
- `talk` package installed and in PATH
|
|
||||||
- `pi` and/or `opencode` for AI crunch mode
|
|
||||||
- `loginctl enable-linger <username>` — **critical** for timers to fire when logged out
|
|
||||||
- `ELEVENLABS_API_KEY` in environment (or agenix secrets)
|
|
||||||
|
|
||||||
## NixOS Installation
|
|
||||||
|
|
||||||
```nix
|
|
||||||
# home-manager
|
|
||||||
home.packages = [ pkgs.m3ta.crunch pkgs.m3ta.talk ];
|
|
||||||
```
|
|
||||||
|
|
||||||
Verify lingering is enabled:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
loginctl show-user $(whoami) | grep Linger=yes
|
|
||||||
# If not:
|
|
||||||
sudo loginctl enable-linger $(whoami)
|
|
||||||
```
|
|
||||||
@@ -1,289 +0,0 @@
|
|||||||
{
|
|
||||||
lib,
|
|
||||||
stdenv,
|
|
||||||
writeShellScriptBin,
|
|
||||||
coreutils,
|
|
||||||
bash,
|
|
||||||
}: let
|
|
||||||
script = writeShellScriptBin "crunch" ''
|
|
||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════════
|
|
||||||
# crunch — Voice-notified reminders & AI crunch jobs
|
|
||||||
# via systemd transient timers.
|
|
||||||
#
|
|
||||||
# Requires: talk (ElevenLabs TTS) in PATH, ELEVENLABS_API_KEY env.
|
|
||||||
# Optional: pi, opencode for AI crunch mode.
|
|
||||||
# ═══════════════════════════════════════════════════════════════
|
|
||||||
|
|
||||||
TALK="''${TALK:-talk}"
|
|
||||||
SELF="$(readlink -f "''${BASH_SOURCE[0]:-$0}")"
|
|
||||||
|
|
||||||
# ── Helpers ───────────────────────────────────────────────────
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
cat <<'EOF'
|
|
||||||
crunch — voice-notified reminders and AI jobs via systemd timers
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
crunch at <time> <message> One-shot (14:30 or "2026-07-03 14:30")
|
|
||||||
crunch in <duration> <message> One-shot after delay (30m, 2h, 1h30m)
|
|
||||||
crunch daily <time> <message> Recurring daily at time
|
|
||||||
crunch weekly <day> <time> <message> Recurring weekly (Mon or Montag)
|
|
||||||
crunch ai <engine> <type> <time> <prompt> AI crunch (pi|opencode)
|
|
||||||
crunch script <type> <time> <script.sh> [args] Custom script → talk
|
|
||||||
crunch list List active jobs
|
|
||||||
crunch cancel <name> Cancel a job
|
|
||||||
crunch purge Remove fired one-shot jobs
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
crunch at "14:30" "Müll rausbringen"
|
|
||||||
crunch at "2026-07-03 10:00" "Zahnarzttermin"
|
|
||||||
crunch in "30m" "Build checken"
|
|
||||||
crunch daily "09:00" "Daily standup"
|
|
||||||
crunch weekly "Mon 09:00" "Weekly review"
|
|
||||||
crunch weekly "Montag 09:00" "Weekly review"
|
|
||||||
crunch ai pi in "1h" "Fasse neueste Commits zusammen"
|
|
||||||
crunch ai opencode daily "08:00" "Review offene Issues"
|
|
||||||
crunch script daily "08:00" ~/scripts/basecamp-daily.sh
|
|
||||||
crunch list
|
|
||||||
crunch cancel mll-rausbringen-12345
|
|
||||||
|
|
||||||
Environment:
|
|
||||||
VOICE_NOTIFY=0 Silence voice output (passed to talk)
|
|
||||||
ELEVENLABS_API_KEY Required by talk
|
|
||||||
TALK Override path to talk binary
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
# German → systemd day abbreviations
|
|
||||||
norm_day() {
|
|
||||||
local d="''${1,,}"
|
|
||||||
d="''${d%%.*}" # strip trailing dot (German abbreviation)
|
|
||||||
case "$d" in
|
|
||||||
mo|mon|monday|montag) echo "Mon" ;;
|
|
||||||
di|tue|tues|tuesday|dienstag) echo "Tue" ;;
|
|
||||||
mi|wed|weds|wednesday|mittwoch) echo "Wed" ;;
|
|
||||||
do|thu|thur|thurs|thursday|donnerstag) echo "Thu" ;;
|
|
||||||
fr|fri|friday|freitag) echo "Fri" ;;
|
|
||||||
sa|sat|saturday|samstag) echo "Sat" ;;
|
|
||||||
so|su|sun|sunday|sonntag) echo "Sun" ;;
|
|
||||||
*) echo "''${1^}" ;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
make_name() {
|
|
||||||
local msg="''${1:?No message}"
|
|
||||||
local slug
|
|
||||||
slug="''${msg,,}"
|
|
||||||
slug="''${slug//[^a-z0-9 ]/}"
|
|
||||||
slug="''${slug// /-}"
|
|
||||||
slug="''${slug:0:25}"
|
|
||||||
slug="''${slug%-}" # trim trailing dash
|
|
||||||
echo "crunch-''${slug:-job}-$RANDOM"
|
|
||||||
}
|
|
||||||
|
|
||||||
# schedule <type> <time_spec> <exec_cmd> <name>
|
|
||||||
schedule() {
|
|
||||||
local type="$1" time_spec="$2" exec_cmd="$3" name="$4"
|
|
||||||
local timer_flag=""
|
|
||||||
|
|
||||||
case "$type" in
|
|
||||||
at)
|
|
||||||
if [[ "$time_spec" == *' '* ]]; then
|
|
||||||
# "2026-07-03 14:30" → specific date
|
|
||||||
timer_flag="--on-calendar=''${time_spec}:00"
|
|
||||||
else
|
|
||||||
# "14:30" → next matching time
|
|
||||||
timer_flag="--on-calendar=*-*-* ''${time_spec}:00"
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
in)
|
|
||||||
timer_flag="--on-active=''${time_spec}"
|
|
||||||
;;
|
|
||||||
daily)
|
|
||||||
timer_flag="--on-calendar=*-*-* ''${time_spec}:00"
|
|
||||||
;;
|
|
||||||
weekly)
|
|
||||||
local day time_part
|
|
||||||
day="$(norm_day "''${time_spec%% *}")"
|
|
||||||
time_part="''${time_spec##* }"
|
|
||||||
timer_flag="--on-calendar=''${day} *-*-* ''${time_part}:00"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Unknown schedule type: $type" >&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
systemd-run --user \
|
|
||||||
--unit="''${name}" \
|
|
||||||
--description="crunch job" \
|
|
||||||
"''${timer_flag}" \
|
|
||||||
bash -lc "''${exec_cmd}" \
|
|
||||||
&& echo "✓ Scheduled: $name"
|
|
||||||
}
|
|
||||||
|
|
||||||
# ── Internal execution (called by systemd) ────────────────────
|
|
||||||
|
|
||||||
case "''${1:-}" in
|
|
||||||
_say)
|
|
||||||
shift
|
|
||||||
exec "$TALK" "$*"
|
|
||||||
;;
|
|
||||||
_ai)
|
|
||||||
engine="$2"; shift 2
|
|
||||||
case "$engine" in
|
|
||||||
pi|pi-agent)
|
|
||||||
pi -p "$*" | "$TALK"
|
|
||||||
;;
|
|
||||||
opencode|oc)
|
|
||||||
opencode run "$*" -q | "$TALK"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Unknown engine: $engine (use: pi, opencode)" >&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
exit $?
|
|
||||||
;;
|
|
||||||
_script)
|
|
||||||
script_path="$2"; shift 2
|
|
||||||
rc=0
|
|
||||||
output=$(bash "$script_path" "$@" 2>&1) || rc=$?
|
|
||||||
if [ -n "''${output:-}" ]; then
|
|
||||||
printf '%s' "$output" | "$TALK"
|
|
||||||
fi
|
|
||||||
exit "$rc"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# ── CLI ───────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
[ $# -lt 1 ] && { usage; exit 0; }
|
|
||||||
|
|
||||||
cmd="$1"; shift
|
|
||||||
|
|
||||||
case "$cmd" in
|
|
||||||
# ── Simple voice reminders ──
|
|
||||||
at)
|
|
||||||
[ $# -lt 2 ] && { echo "Usage: crunch at <time> <message>" >&2; exit 1; }
|
|
||||||
time_spec="$1"; shift
|
|
||||||
msg="$*"
|
|
||||||
name="$(make_name "$msg")"
|
|
||||||
schedule at "$time_spec" "$SELF _say $(printf '%q' "$msg")" "$name"
|
|
||||||
;;
|
|
||||||
|
|
||||||
in)
|
|
||||||
[ $# -lt 2 ] && { echo "Usage: crunch in <duration> <message>" >&2; exit 1; }
|
|
||||||
duration="$1"; shift
|
|
||||||
msg="$*"
|
|
||||||
name="$(make_name "$msg")"
|
|
||||||
schedule in "$duration" "$SELF _say $(printf '%q' "$msg")" "$name"
|
|
||||||
;;
|
|
||||||
|
|
||||||
daily)
|
|
||||||
[ $# -lt 2 ] && { echo "Usage: crunch daily <time> <message>" >&2; exit 1; }
|
|
||||||
time_spec="$1"; shift
|
|
||||||
msg="$*"
|
|
||||||
name="$(make_name "$msg")"
|
|
||||||
schedule daily "$time_spec" "$SELF _say $(printf '%q' "$msg")" "$name"
|
|
||||||
;;
|
|
||||||
|
|
||||||
weekly)
|
|
||||||
[ $# -lt 2 ] && { echo "Usage: crunch weekly <day> <time> <message>" >&2; exit 1; }
|
|
||||||
day_time="$1"; shift
|
|
||||||
msg="$*"
|
|
||||||
name="$(make_name "$msg")"
|
|
||||||
schedule weekly "$day_time" "$SELF _say $(printf '%q' "$msg")" "$name"
|
|
||||||
;;
|
|
||||||
|
|
||||||
# ── AI crunch jobs ──
|
|
||||||
ai)
|
|
||||||
[ $# -lt 4 ] && { echo "Usage: crunch ai <pi|opencode> <at|in|daily|weekly> <time> <prompt>" >&2; exit 1; }
|
|
||||||
engine="$1"; sub_type="$2"; time_spec="$3"; shift 3
|
|
||||||
prompt="$*"
|
|
||||||
name="$(make_name "$prompt")"
|
|
||||||
schedule "$sub_type" "$time_spec" \
|
|
||||||
"$SELF _ai $engine $(printf '%q' "$prompt")" "$name"
|
|
||||||
;;
|
|
||||||
|
|
||||||
# ── Custom script crunch jobs ──
|
|
||||||
script)
|
|
||||||
[ $# -lt 3 ] && { echo "Usage: crunch script <at|in|daily|weekly> <time> <script.sh> [args...]" >&2; exit 1; }
|
|
||||||
sub_type="$1"; time_spec="$2"; script_path="$3"; shift 3
|
|
||||||
script_path="$(readlink -f "$script_path")"
|
|
||||||
[ ! -f "$script_path" ] && { echo "Script not found: $script_path" >&2; exit 1; }
|
|
||||||
name="$(make_name "$(basename "$script_path" .sh)")"
|
|
||||||
exec_cmd="$SELF _script $(printf '%q' "$script_path")"
|
|
||||||
if [ $# -gt 0 ]; then
|
|
||||||
exec_cmd+=" $(printf '%q ' "$@")"
|
|
||||||
fi
|
|
||||||
schedule "$sub_type" "$time_spec" "$exec_cmd" "$name"
|
|
||||||
;;
|
|
||||||
|
|
||||||
# ── Management ──
|
|
||||||
list)
|
|
||||||
echo "Active crunch jobs:"
|
|
||||||
echo "───────────────────────────────────"
|
|
||||||
systemctl --user list-timers 'crunch-*' --no-pager 2>/dev/null \
|
|
||||||
| grep -E 'crunch-|^NEXT|^NEXT|^$' || echo " (none)"
|
|
||||||
;;
|
|
||||||
|
|
||||||
cancel)
|
|
||||||
[ $# -lt 1 ] && { echo "Usage: crunch cancel <name>" >&2; exit 1; }
|
|
||||||
name="$1"
|
|
||||||
# Accept with or without crunch- prefix
|
|
||||||
[[ "$name" != crunch-* ]] && name="crunch-$name"
|
|
||||||
systemctl --user stop "''${name}.timer" "''${name}.service" 2>/dev/null \
|
|
||||||
&& echo "✓ Cancelled: $name" \
|
|
||||||
|| echo "✗ Not found: $name"
|
|
||||||
;;
|
|
||||||
|
|
||||||
purge)
|
|
||||||
echo "Purging fired one-shot jobs..."
|
|
||||||
local purged=0
|
|
||||||
for unit in $(systemctl --user list-units 'crunch-*' --all --plain --no-legend --no-pager 2>/dev/null | awk '{print $1}'); do
|
|
||||||
if systemctl --user is-failed "$unit" &>/dev/null; then
|
|
||||||
systemctl --user stop "$unit" 2>/dev/null || true
|
|
||||||
systemctl --user reset-failed "$unit" 2>/dev/null || true
|
|
||||||
echo " Purged: $unit"
|
|
||||||
purged=$((purged + 1))
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
echo "✓ Purged $purged unit(s)"
|
|
||||||
;;
|
|
||||||
|
|
||||||
-h|--help|help)
|
|
||||||
usage
|
|
||||||
;;
|
|
||||||
|
|
||||||
*)
|
|
||||||
echo "Unknown command: $cmd" >&2
|
|
||||||
echo ""
|
|
||||||
usage
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
'';
|
|
||||||
in
|
|
||||||
stdenv.mkDerivation {
|
|
||||||
pname = "crunch";
|
|
||||||
version = "0.1.0";
|
|
||||||
|
|
||||||
dontUnpack = true;
|
|
||||||
|
|
||||||
installPhase = ''
|
|
||||||
mkdir -p "$out/bin"
|
|
||||||
ln -s ${script}/bin/crunch "$out/bin/crunch"
|
|
||||||
'';
|
|
||||||
|
|
||||||
meta = with lib; {
|
|
||||||
description = "Voice-notified reminders and AI crunch jobs via systemd transient timers";
|
|
||||||
homepage = "https://code.m3ta.dev/m3tam3re/nixpkgs";
|
|
||||||
license = licenses.mit;
|
|
||||||
platforms = platforms.linux;
|
|
||||||
mainProgram = "crunch";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
# m3ta-nixpkgs package registry
|
|
||||||
#
|
|
||||||
# Flake inputs used:
|
|
||||||
# inputs.basecamp → basecamp (pass-through)
|
|
||||||
# inputs.openspec → openspec (pass-through)
|
|
||||||
# inputs.opencode → opencode-desktop (build inputs + patches)
|
|
||||||
# inputs.agents → not used directly here (used by lib/)
|
|
||||||
{
|
|
||||||
pkgs,
|
|
||||||
inputs,
|
|
||||||
...
|
|
||||||
}: let
|
|
||||||
system = pkgs.stdenv.hostPlatform.system;
|
|
||||||
in {
|
|
||||||
# ── Local packages ────────────────────────────────────────────────
|
|
||||||
# Standard packages built from source in ./<name>/default.nix.
|
|
||||||
# No flake inputs required.
|
|
||||||
|
|
||||||
sidecar = pkgs.callPackage ./sidecar {};
|
|
||||||
td = pkgs.callPackage ./td {};
|
|
||||||
eigent = pkgs.callPackage ./eigent {};
|
|
||||||
hyprpaper-random = pkgs.callPackage ./hyprpaper-random {};
|
|
||||||
launch-webapp = pkgs.callPackage ./launch-webapp {};
|
|
||||||
mem0 = pkgs.callPackage ./mem0 {};
|
|
||||||
msty-studio = pkgs.callPackage ./msty-studio {};
|
|
||||||
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 {};
|
|
||||||
kestractl = pkgs.callPackage ./kestractl {};
|
|
||||||
openshell = pkgs.callPackage ./openshell {};
|
|
||||||
openwork = pkgs.callPackage ./openwork {};
|
|
||||||
zellij-ps = pkgs.callPackage ./zellij-ps {};
|
|
||||||
vibetyper = pkgs.callPackage ./vibetyper {};
|
|
||||||
talk = pkgs.callPackage ./talk {};
|
|
||||||
crunch = pkgs.callPackage ./crunch {};
|
|
||||||
|
|
||||||
# ── Pass-through packages ──────────────────────────────────────────
|
|
||||||
# Imported directly from flake inputs. No local modifications.
|
|
||||||
|
|
||||||
basecamp = inputs.basecamp.packages.${system}.default;
|
|
||||||
openspec = inputs.openspec.packages.${system}.default;
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
{
|
|
||||||
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";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
{
|
|
||||||
lib,
|
|
||||||
stdenv,
|
|
||||||
fetchurl,
|
|
||||||
autoPatchelfHook,
|
|
||||||
}: let
|
|
||||||
sources = lib.importJSON ./sources.json;
|
|
||||||
source = sources.sources.${stdenv.hostPlatform.system};
|
|
||||||
in
|
|
||||||
stdenv.mkDerivation {
|
|
||||||
pname = "kestractl";
|
|
||||||
version = sources.version;
|
|
||||||
|
|
||||||
src = fetchurl {
|
|
||||||
inherit (source) url hash;
|
|
||||||
};
|
|
||||||
|
|
||||||
nativeBuildInputs = [autoPatchelfHook];
|
|
||||||
|
|
||||||
unpackPhase = ''
|
|
||||||
tar -xzf $src
|
|
||||||
'';
|
|
||||||
|
|
||||||
installPhase = ''
|
|
||||||
install -Dm755 kestractl $out/bin/kestractl
|
|
||||||
'';
|
|
||||||
|
|
||||||
passthru.updateScript = ./update.sh;
|
|
||||||
|
|
||||||
meta = with lib; {
|
|
||||||
description = "CLI for the Kestra workflow orchestration platform";
|
|
||||||
homepage = "https://github.com/kestra-io/kestractl";
|
|
||||||
license = licenses.asl20;
|
|
||||||
platforms = attrNames sources.sources;
|
|
||||||
mainProgram = "kestractl";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"version": "1.15.0",
|
|
||||||
"sources": {
|
|
||||||
"aarch64-linux": {
|
|
||||||
"url": "https://github.com/kestra-io/kestractl/releases/download/1.15.0/kestractl_1.15.0_linux_arm64.tar.gz",
|
|
||||||
"hash": "sha256-iBkhetgGy/8Nljxb0yO8hjln8LYgTHTOPdNsee1W/U4="
|
|
||||||
},
|
|
||||||
"x86_64-linux": {
|
|
||||||
"url": "https://github.com/kestra-io/kestractl/releases/download/1.15.0/kestractl_1.15.0_linux_amd64.tar.gz",
|
|
||||||
"hash": "sha256-hvQsOIODwDPZEW4wyZhd5Sb70tQsfwU4ZrHrxYK3VKc="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
#!/usr/bin/env nix-shell
|
|
||||||
#!nix-shell --pure -i bash -p bash curl jq nix cacert git
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# Update kestractl sources.json with the latest release from GitHub.
|
|
||||||
# Usage: ./update.sh (or via nix-update --update-script)
|
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
||||||
SOURCES_FILE="$SCRIPT_DIR/sources.json"
|
|
||||||
|
|
||||||
# Map Nix system -> GitHub release asset name fragment
|
|
||||||
declare -A SYSTEMS=(
|
|
||||||
["x86_64-linux"]="linux_amd64"
|
|
||||||
["aarch64-linux"]="linux_arm64"
|
|
||||||
)
|
|
||||||
|
|
||||||
echo "Fetching latest kestractl release..."
|
|
||||||
LATEST=$(curl -fsSL "https://api.github.com/repos/kestra-io/kestractl/releases/latest")
|
|
||||||
VERSION=$(echo "$LATEST" | jq -r '.tag_name')
|
|
||||||
echo "Latest version: $VERSION"
|
|
||||||
|
|
||||||
CURRENT_VERSION=$(jq -r '.version' "$SOURCES_FILE")
|
|
||||||
if [[ "$VERSION" == "$CURRENT_VERSION" ]]; then
|
|
||||||
echo "Already at latest version $VERSION, nothing to do."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
NEW_SOURCES="{}"
|
|
||||||
|
|
||||||
for NIX_SYSTEM in "${!SYSTEMS[@]}"; do
|
|
||||||
ASSET_FRAG="${SYSTEMS[$NIX_SYSTEM]}"
|
|
||||||
URL="https://github.com/kestra-io/kestractl/releases/download/${VERSION}/kestractl_${VERSION}_${ASSET_FRAG}.tar.gz"
|
|
||||||
|
|
||||||
echo "Fetching hash for $NIX_SYSTEM ($URL)..."
|
|
||||||
HASH=$(nix-prefetch-url --type sha256 "$URL" 2>/dev/null)
|
|
||||||
SRI=$(nix hash to-sri --type sha256 "$HASH")
|
|
||||||
|
|
||||||
NEW_SOURCES=$(echo "$NEW_SOURCES" | jq \
|
|
||||||
--arg sys "$NIX_SYSTEM" \
|
|
||||||
--arg url "$URL" \
|
|
||||||
--arg hash "$SRI" \
|
|
||||||
'. + {($sys): {url: $url, hash: $hash}}')
|
|
||||||
done
|
|
||||||
|
|
||||||
jq -n \
|
|
||||||
--arg version "$VERSION" \
|
|
||||||
--argjson sources "$NEW_SOURCES" \
|
|
||||||
'{"version": $version, "sources": $sources}' \
|
|
||||||
> "$SOURCES_FILE"
|
|
||||||
|
|
||||||
echo "Updated $SOURCES_FILE to $VERSION"
|
|
||||||
|
|
||||||
# Commit when running in CI or via nix-update
|
|
||||||
if [[ -d "$SCRIPT_DIR/../../.git" ]] || git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
||||||
NIXPKGS_ROOT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null || true)
|
|
||||||
if [[ -n "$NIXPKGS_ROOT" && -n "$(git -C "$NIXPKGS_ROOT" status --porcelain "$SOURCES_FILE")" ]]; then
|
|
||||||
git -C "$NIXPKGS_ROOT" add "$SOURCES_FILE"
|
|
||||||
git -C "$NIXPKGS_ROOT" commit -m "kestractl: ${CURRENT_VERSION} -> ${VERSION}"
|
|
||||||
echo "Committed update to git"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
{
|
|
||||||
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";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
{
|
|
||||||
lib,
|
|
||||||
nix-update-script,
|
|
||||||
python3,
|
|
||||||
fetchFromGitHub,
|
|
||||||
}:
|
|
||||||
python3.pkgs.buildPythonPackage rec {
|
|
||||||
pname = "mem0ai";
|
|
||||||
version = "2.0.2";
|
|
||||||
pyproject = true;
|
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
|
||||||
owner = "mem0ai";
|
|
||||||
repo = "mem0";
|
|
||||||
rev = "v${version}";
|
|
||||||
hash = "sha256-SV/+v0WmR6iZyyhPIXtj0PcIpPlSclak0zuSsIGebUo=";
|
|
||||||
};
|
|
||||||
|
|
||||||
# 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;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,301 +0,0 @@
|
|||||||
#!/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)
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
{
|
|
||||||
appimageTools,
|
|
||||||
fetchurl,
|
|
||||||
lib,
|
|
||||||
nodejs,
|
|
||||||
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
|
|
||||||
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:${uv}/bin:${python3}/bin
|
|
||||||
'';
|
|
||||||
meta = {
|
|
||||||
description = "Msty Studio enables advanced, privacy‑preserving AI workflows entirely on your local machine.";
|
|
||||||
license = lib.licenses.unfree;
|
|
||||||
platforms = lib.platforms.linux;
|
|
||||||
mainProgram = "msty-studio";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
{
|
|
||||||
lib,
|
|
||||||
stdenv,
|
|
||||||
fetchurl,
|
|
||||||
}: let
|
|
||||||
sources = lib.importJSON ./sources.json;
|
|
||||||
source = sources.sources.${stdenv.hostPlatform.system};
|
|
||||||
in
|
|
||||||
stdenv.mkDerivation {
|
|
||||||
pname = "openshell";
|
|
||||||
version = lib.removePrefix "v" sources.version;
|
|
||||||
|
|
||||||
src = fetchurl {
|
|
||||||
inherit (source) url hash;
|
|
||||||
};
|
|
||||||
|
|
||||||
unpackPhase = ''
|
|
||||||
tar -xzf $src
|
|
||||||
'';
|
|
||||||
|
|
||||||
installPhase = ''
|
|
||||||
install -Dm755 openshell $out/bin/openshell
|
|
||||||
'';
|
|
||||||
|
|
||||||
passthru.updateScript = ./update.sh;
|
|
||||||
|
|
||||||
meta = with lib; {
|
|
||||||
description = "Safe, private runtime for autonomous AI agents";
|
|
||||||
homepage = "https://github.com/NVIDIA/OpenShell";
|
|
||||||
license = licenses.asl20;
|
|
||||||
platforms = attrNames sources.sources;
|
|
||||||
mainProgram = "openshell";
|
|
||||||
maintainers = [];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"version": "v0.0.62",
|
|
||||||
"sources": {
|
|
||||||
"aarch64-linux": {
|
|
||||||
"url": "https://github.com/NVIDIA/OpenShell/releases/download/v0.0.62/openshell-aarch64-unknown-linux-musl.tar.gz",
|
|
||||||
"hash": "sha256-10jJ4pJ0lxXYI9ns/icicELZzDft4nUprxoQ9/s/8jU="
|
|
||||||
},
|
|
||||||
"x86_64-linux": {
|
|
||||||
"url": "https://github.com/NVIDIA/OpenShell/releases/download/v0.0.62/openshell-x86_64-unknown-linux-musl.tar.gz",
|
|
||||||
"hash": "sha256-0E4RXPeNZJF9c3kW6B1xOA2y7nNPg0O+3dfXnugfDxY="
|
|
||||||
},
|
|
||||||
"aarch64-darwin": {
|
|
||||||
"url": "https://github.com/NVIDIA/OpenShell/releases/download/v0.0.62/openshell-aarch64-apple-darwin.tar.gz",
|
|
||||||
"hash": "sha256-BRkhA1EsFQApkt8Y8+XXgZK9tyBxZHz6m0Rn4td2XH8="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user