From 38c27eff1cb3acc1d89060870b1bab01e4743ada Mon Sep 17 00:00:00 2001
From: m3tm3re
Date: Mon, 6 Apr 2026 18:44:07 +0200
Subject: [PATCH] +basic hermes config
---
.beads/.gitignore | 39 ----
.beads/.sync.lock | 0
.beads/README.md | 81 --------
.beads/interactions.jsonl | 0
.beads/issues.jsonl | 2 -
.beads/metadata.json | 4 -
.beads/sync_base.jsonl | 2 -
flake.lock | 249 ++++++++++++++++++++---
flake.nix | 6 +-
home/common/default.nix | 2 +-
home/features/cli/default.nix | 10 -
home/features/coding/default.nix | 10 +-
home/features/desktop/default.nix | 4 +-
home/features/desktop/hyprland.nix | 2 +
home/m3tam3re/home.nix | 1 +
hosts/common/default.nix | 2 +-
hosts/common/ports.nix | 1 +
hosts/m3-ares/services/udev.nix | 3 +-
hosts/m3-atlas/secrets.nix | 1 +
hosts/m3-atlas/services/conduit.nix | 48 +++++
hosts/m3-atlas/services/default.nix | 2 +
hosts/m3-atlas/services/hermes-agent.nix | 191 +++++++++++++++++
hosts/m3-kratos/secrets.nix | 4 +
hosts/m3-kratos/services/udev.nix | 3 +-
overlays/default.nix | 8 +-
secrets.nix | 3 +
secrets/conduit-env.age | 23 +++
secrets/hermes-env.age | Bin 0 -> 1597 bytes
28 files changed, 526 insertions(+), 175 deletions(-)
delete mode 100644 .beads/.gitignore
delete mode 100644 .beads/.sync.lock
delete mode 100644 .beads/README.md
delete mode 100644 .beads/interactions.jsonl
delete mode 100644 .beads/issues.jsonl
delete mode 100644 .beads/metadata.json
delete mode 100644 .beads/sync_base.jsonl
create mode 100644 hosts/m3-atlas/services/conduit.nix
create mode 100644 hosts/m3-atlas/services/hermes-agent.nix
create mode 100644 secrets/conduit-env.age
create mode 100644 secrets/hermes-env.age
diff --git a/.beads/.gitignore b/.beads/.gitignore
deleted file mode 100644
index 4a7a77d..0000000
--- a/.beads/.gitignore
+++ /dev/null
@@ -1,39 +0,0 @@
-# SQLite databases
-*.db
-*.db?*
-*.db-journal
-*.db-wal
-*.db-shm
-
-# Daemon runtime files
-daemon.lock
-daemon.log
-daemon.pid
-bd.sock
-sync-state.json
-last-touched
-
-# Local version tracking (prevents upgrade notification spam after git ops)
-.local_version
-
-# Legacy database files
-db.sqlite
-bd.db
-
-# Worktree redirect file (contains relative path to main repo's .beads/)
-# Must not be committed as paths would be wrong in other clones
-redirect
-
-# Merge artifacts (temporary files from 3-way merge)
-beads.base.jsonl
-beads.base.meta.json
-beads.left.jsonl
-beads.left.meta.json
-beads.right.jsonl
-beads.right.meta.json
-
-# NOTE: Do NOT add negation patterns (e.g., !issues.jsonl) here.
-# They would override fork protection in .git/info/exclude, allowing
-# contributors to accidentally commit upstream issue databases.
-# The JSONL files (issues.jsonl, interactions.jsonl) and config files
-# are tracked by git by default since no pattern above ignores them.
diff --git a/.beads/.sync.lock b/.beads/.sync.lock
deleted file mode 100644
index e69de29..0000000
diff --git a/.beads/README.md b/.beads/README.md
deleted file mode 100644
index 50f281f..0000000
--- a/.beads/README.md
+++ /dev/null
@@ -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
-
-# Update issue status
-bd update --status in_progress
-bd update --status done
-
-# Sync with git remote
-bd sync
-```
-
-### Working with Issues
-
-Issues in Beads are:
-- **Git-native**: Stored in `.beads/issues.jsonl` and synced like code
-- **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
-- Intelligent JSONL 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* β‘
diff --git a/.beads/interactions.jsonl b/.beads/interactions.jsonl
deleted file mode 100644
index e69de29..0000000
diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl
deleted file mode 100644
index 48529f6..0000000
--- a/.beads/issues.jsonl
+++ /dev/null
@@ -1,2 +0,0 @@
-{"id":"nixos-config-gx2","title":"form","status":"tombstone","priority":2,"issue_type":"task","created_at":"2026-01-11T11:49:21.688289476+01:00","created_by":"m3tam3re","updated_at":"2026-01-11T11:51:36.426124223+01:00","deleted_at":"2026-01-11T11:51:36.426124223+01:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"}
-{"id":"nixos-config-n4l","title":"Create Gitea action for nix-update package updates","description":"Create a Gitea action to automatically update packages in this nixos-config repository using nix-update.\n\n**Context:**\n- Gitea instance is already running on m3-atlas at code.m3ta.dev (configured in hosts/m3-atlas/services/gitea.nix)\n- The repository is self-hosted on this Gitea instance\n- nix-update is already referenced in home/features/cli/default.nix\n- Currently no Gitea workflows exist (.gitea/ directory does not exist)\n\n**Goal:**\nAutomate package updates by creating a Gitea Actions workflow that:\n1. Runs nix-update periodically (e.g., weekly or on schedule)\n2. Updates package definitions in pkgs/ directory\n3. Creates pull requests with the updates\n4. Uses appropriate secrets/credentials for the Gitea instance\n\n**Requirements:**\n- Create .gitea/workflows/ directory structure\n- Define workflow file with nix-update command\n- Configure triggers (schedule, manual, or on repository events)\n- Set up proper permissions and secrets\n- Test the workflow execution\n\n**Current Repository State:**\n- pkgs/default.nix exists but is minimal (currently just a comment)\n- Multiple nixpkgs inputs are used (unstable, 25.11, locked, master)\n- Custom m3ta-nixpkgs overlay at code.m3ta.dev/m3tam3re/nixpkgs\n- Uses agenix for secrets management\n\n**Related Files:**\n- hosts/m3-atlas/services/gitea.nix (existing Gitea configuration)\n- hosts/common/ports.nix (port management)\n- home/features/cli/default.nix (nix-update reference)\n\n**Acceptance Criteria:**\n- [ ] Create .gitea/workflows directory\n- [ ] Implement nix-update workflow YAML\n- [ ] Configure appropriate triggers\n- [ ] Test workflow on the repository\n- [ ] Document setup and configuration","status":"closed","priority":2,"issue_type":"feature","owner":"p@m3ta.dev","created_at":"2026-01-13T20:39:49.838916335+01:00","created_by":"m3tm3re","updated_at":"2026-01-13T20:51:43.833041989+01:00","closed_at":"2026-01-13T20:51:43.833041989+01:00","close_reason":"Closed"}
diff --git a/.beads/metadata.json b/.beads/metadata.json
deleted file mode 100644
index c787975..0000000
--- a/.beads/metadata.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "database": "beads.db",
- "jsonl_export": "issues.jsonl"
-}
\ No newline at end of file
diff --git a/.beads/sync_base.jsonl b/.beads/sync_base.jsonl
deleted file mode 100644
index 48529f6..0000000
--- a/.beads/sync_base.jsonl
+++ /dev/null
@@ -1,2 +0,0 @@
-{"id":"nixos-config-gx2","title":"form","status":"tombstone","priority":2,"issue_type":"task","created_at":"2026-01-11T11:49:21.688289476+01:00","created_by":"m3tam3re","updated_at":"2026-01-11T11:51:36.426124223+01:00","deleted_at":"2026-01-11T11:51:36.426124223+01:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"}
-{"id":"nixos-config-n4l","title":"Create Gitea action for nix-update package updates","description":"Create a Gitea action to automatically update packages in this nixos-config repository using nix-update.\n\n**Context:**\n- Gitea instance is already running on m3-atlas at code.m3ta.dev (configured in hosts/m3-atlas/services/gitea.nix)\n- The repository is self-hosted on this Gitea instance\n- nix-update is already referenced in home/features/cli/default.nix\n- Currently no Gitea workflows exist (.gitea/ directory does not exist)\n\n**Goal:**\nAutomate package updates by creating a Gitea Actions workflow that:\n1. Runs nix-update periodically (e.g., weekly or on schedule)\n2. Updates package definitions in pkgs/ directory\n3. Creates pull requests with the updates\n4. Uses appropriate secrets/credentials for the Gitea instance\n\n**Requirements:**\n- Create .gitea/workflows/ directory structure\n- Define workflow file with nix-update command\n- Configure triggers (schedule, manual, or on repository events)\n- Set up proper permissions and secrets\n- Test the workflow execution\n\n**Current Repository State:**\n- pkgs/default.nix exists but is minimal (currently just a comment)\n- Multiple nixpkgs inputs are used (unstable, 25.11, locked, master)\n- Custom m3ta-nixpkgs overlay at code.m3ta.dev/m3tam3re/nixpkgs\n- Uses agenix for secrets management\n\n**Related Files:**\n- hosts/m3-atlas/services/gitea.nix (existing Gitea configuration)\n- hosts/common/ports.nix (port management)\n- home/features/cli/default.nix (nix-update reference)\n\n**Acceptance Criteria:**\n- [ ] Create .gitea/workflows directory\n- [ ] Implement nix-update workflow YAML\n- [ ] Configure appropriate triggers\n- [ ] Test workflow on the repository\n- [ ] Document setup and configuration","status":"closed","priority":2,"issue_type":"feature","owner":"p@m3ta.dev","created_at":"2026-01-13T20:39:49.838916335+01:00","created_by":"m3tm3re","updated_at":"2026-01-13T20:51:43.833041989+01:00","closed_at":"2026-01-13T20:51:43.833041989+01:00","close_reason":"Closed"}
diff --git a/flake.lock b/flake.lock
index 159a577..443207d 100644
--- a/flake.lock
+++ b/flake.lock
@@ -176,6 +176,27 @@
}
},
"flake-parts": {
+ "inputs": {
+ "nixpkgs-lib": [
+ "hermes-agent",
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1772408722,
+ "narHash": "sha256-rHuJtdcOjK7rAHpHphUb1iCvgkU3GpfvicLMwwnfMT0=",
+ "owner": "hercules-ci",
+ "repo": "flake-parts",
+ "rev": "f20dc5d9b8027381c474144ecabc9034d6a839a3",
+ "type": "github"
+ },
+ "original": {
+ "owner": "hercules-ci",
+ "repo": "flake-parts",
+ "type": "github"
+ }
+ },
+ "flake-parts_2": {
"inputs": {
"nixpkgs-lib": [
"llm-agents",
@@ -196,7 +217,7 @@
"type": "github"
}
},
- "flake-parts_2": {
+ "flake-parts_3": {
"inputs": {
"nixpkgs-lib": [
"nur",
@@ -235,6 +256,28 @@
"type": "github"
}
},
+ "hermes-agent": {
+ "inputs": {
+ "flake-parts": "flake-parts",
+ "nixpkgs": "nixpkgs_3",
+ "pyproject-build-systems": "pyproject-build-systems",
+ "pyproject-nix": "pyproject-nix_2",
+ "uv2nix": "uv2nix_2"
+ },
+ "locked": {
+ "lastModified": 1775454213,
+ "narHash": "sha256-jNv7ux+zH8PDFMlFh2yTBJyzx7GvPkwYPBPcKzn+rhg=",
+ "owner": "NousResearch",
+ "repo": "hermes-agent",
+ "rev": "9ca954a274171c648397fd9e747301edc5b66b03",
+ "type": "github"
+ },
+ "original": {
+ "owner": "NousResearch",
+ "repo": "hermes-agent",
+ "type": "github"
+ }
+ },
"home-manager": {
"inputs": {
"nixpkgs": [
@@ -323,7 +366,7 @@
"inputs": {
"flake-utils": "flake-utils",
"home-manager": "home-manager_3",
- "nixpkgs": "nixpkgs_3"
+ "nixpkgs": "nixpkgs_4"
},
"locked": {
"lastModified": 1774257081,
@@ -358,17 +401,17 @@
"inputs": {
"blueprint": "blueprint",
"bun2nix": "bun2nix",
- "flake-parts": "flake-parts",
- "nixpkgs": "nixpkgs_4",
+ "flake-parts": "flake-parts_2",
+ "nixpkgs": "nixpkgs_5",
"systems": "systems_3",
"treefmt-nix": "treefmt-nix"
},
"locked": {
- "lastModified": 1775212861,
- "narHash": "sha256-Sf1nWWEuGuhKPBO2U9ar+YLqkJFa7q06tAnPRUhTIMc=",
+ "lastModified": 1775446641,
+ "narHash": "sha256-xzRYQF3iTdnjLnRDqLcud6bsBBth7jHqWXcY2/I13bY=",
"owner": "numtide",
"repo": "llm-agents.nix",
- "rev": "86f8dd41031b1aa013cbcb8c16ecfcc71c2c0ea5",
+ "rev": "cf24ebe96828b5c38fb0dbbbeed89f8d5397915f",
"type": "github"
},
"original": {
@@ -380,14 +423,14 @@
"m3ta-nixpkgs": {
"inputs": {
"basecamp": "basecamp",
- "nixpkgs": "nixpkgs_5",
+ "nixpkgs": "nixpkgs_6",
"nixpkgs-master": "nixpkgs-master",
"opencode": "opencode",
"openspec": "openspec"
},
"locked": {
- "lastModified": 1775213101,
- "narHash": "sha256-4Yis838PgXUI3H9eTsOCdWLCmhQC4tLhAmLRYFFj9MU=",
+ "lastModified": 1775355384,
+ "narHash": "sha256-3XPJvNUjd5JXshjogwUy8T/N5ylHUd7tDBSxcAkEAcY=",
"path": "/home/m3tam3re/p/NIX/nixpkgs",
"type": "path"
},
@@ -433,7 +476,7 @@
"nixos-generators": {
"inputs": {
"nixlib": "nixlib",
- "nixpkgs": "nixpkgs_6"
+ "nixpkgs": "nixpkgs_7"
},
"locked": {
"lastModified": 1769813415,
@@ -593,6 +636,22 @@
}
},
"nixpkgs_3": {
+ "locked": {
+ "lastModified": 1751274312,
+ "narHash": "sha256-/bVBlRpECLVzjV19t5KMdMFWSwKLtb5RyXdjz3LJT+g=",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "50ab793786d9de88ee30ec4e4c24fb4236fc2674",
+ "type": "github"
+ },
+ "original": {
+ "owner": "NixOS",
+ "ref": "nixos-24.11",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "nixpkgs_4": {
"locked": {
"lastModified": 1750776420,
"narHash": "sha256-/CG+w0o0oJ5itVklOoLbdn2dGB0wbZVOoDm4np6w09A=",
@@ -608,13 +667,13 @@
"type": "github"
}
},
- "nixpkgs_4": {
+ "nixpkgs_5": {
"locked": {
- "lastModified": 1775095191,
- "narHash": "sha256-CsqRiYbgQyv01LS0NlC7shwzhDhjNDQSrhBX8VuD3nM=",
+ "lastModified": 1775126147,
+ "narHash": "sha256-J0dZU4atgcfo4QvM9D92uQ0Oe1eLTxBVXjJzdEMQpD0=",
"owner": "NixOS",
"repo": "nixpkgs",
- "rev": "106eb93cbb9d4e4726bf6bc367a3114f7ed6b32f",
+ "rev": "8d8c1fa5b412c223ffa47410867813290cdedfef",
"type": "github"
},
"original": {
@@ -624,7 +683,7 @@
"type": "github"
}
},
- "nixpkgs_5": {
+ "nixpkgs_6": {
"locked": {
"lastModified": 1774709303,
"narHash": "sha256-D3Q07BbIA2KnTcSXIqqu9P586uWxN74zNoCH3h2ESHg=",
@@ -640,7 +699,7 @@
"type": "github"
}
},
- "nixpkgs_6": {
+ "nixpkgs_7": {
"locked": {
"lastModified": 1736657626,
"narHash": "sha256-FWlPMUzp0lkQBdhKlPqtQdqmp+/C+1MBiEytaYfrCTY=",
@@ -656,7 +715,7 @@
"type": "github"
}
},
- "nixpkgs_7": {
+ "nixpkgs_8": {
"locked": {
"lastModified": 1774386573,
"narHash": "sha256-4hAV26quOxdC6iyG7kYaZcM3VOskcPUrdCQd/nx8obc=",
@@ -672,7 +731,7 @@
"type": "github"
}
},
- "nixpkgs_8": {
+ "nixpkgs_9": {
"locked": {
"lastModified": 1710272261,
"narHash": "sha256-g0bDwXFmTE7uGDOs9HcJsfLFhH7fOsASbAuOzDC+fhQ=",
@@ -690,7 +749,7 @@
},
"nur": {
"inputs": {
- "flake-parts": "flake-parts_2",
+ "flake-parts": "flake-parts_3",
"nixpkgs": [
"nixpkgs"
]
@@ -717,16 +776,16 @@
]
},
"locked": {
- "lastModified": 1774807340,
- "narHash": "sha256-OV76SWqiBguUupfbkJMBVrslJoTqSh4epNjEp/HE/cY=",
+ "lastModified": 1774996501,
+ "narHash": "sha256-1sEkQDdV/qU4/N9oHR4mptllcRWt503k6HZ8Yp4EooE=",
"owner": "anomalyco",
"repo": "opencode",
- "rev": "e7f94f9b9a3bd8742330e4a7ba8573ac21042c01",
+ "rev": "892bdebaacbed3fc76976431c7aa7b81ab639fb6",
"type": "github"
},
"original": {
"owner": "anomalyco",
- "ref": "v1.3.6",
+ "ref": "v1.3.12",
"repo": "opencode",
"type": "github"
}
@@ -752,18 +811,107 @@
"type": "github"
}
},
+ "pyproject-build-systems": {
+ "inputs": {
+ "nixpkgs": [
+ "hermes-agent",
+ "nixpkgs"
+ ],
+ "pyproject-nix": "pyproject-nix",
+ "uv2nix": "uv2nix"
+ },
+ "locked": {
+ "lastModified": 1772555609,
+ "narHash": "sha256-3BA3HnUvJSbHJAlJj6XSy0Jmu7RyP2gyB/0fL7XuEDo=",
+ "owner": "pyproject-nix",
+ "repo": "build-system-pkgs",
+ "rev": "c37f66a953535c394244888598947679af231863",
+ "type": "github"
+ },
+ "original": {
+ "owner": "pyproject-nix",
+ "repo": "build-system-pkgs",
+ "type": "github"
+ }
+ },
+ "pyproject-nix": {
+ "inputs": {
+ "nixpkgs": [
+ "hermes-agent",
+ "pyproject-build-systems",
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1769936401,
+ "narHash": "sha256-kwCOegKLZJM9v/e/7cqwg1p/YjjTAukKPqmxKnAZRgA=",
+ "owner": "nix-community",
+ "repo": "pyproject.nix",
+ "rev": "b0d513eeeebed6d45b4f2e874f9afba2021f7812",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nix-community",
+ "repo": "pyproject.nix",
+ "type": "github"
+ }
+ },
+ "pyproject-nix_2": {
+ "inputs": {
+ "nixpkgs": [
+ "hermes-agent",
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1772865871,
+ "narHash": "sha256-/ZTSg97aouL0SlPHaokA4r3iuH9QzHVuWPACD2CUCFY=",
+ "owner": "pyproject-nix",
+ "repo": "pyproject.nix",
+ "rev": "e537db02e72d553cea470976b9733581bcf5b3ed",
+ "type": "github"
+ },
+ "original": {
+ "owner": "pyproject-nix",
+ "repo": "pyproject.nix",
+ "type": "github"
+ }
+ },
+ "pyproject-nix_3": {
+ "inputs": {
+ "nixpkgs": [
+ "hermes-agent",
+ "uv2nix",
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1771518446,
+ "narHash": "sha256-nFJSfD89vWTu92KyuJWDoTQJuoDuddkJV3TlOl1cOic=",
+ "owner": "pyproject-nix",
+ "repo": "pyproject.nix",
+ "rev": "eb204c6b3335698dec6c7fc1da0ebc3c6df05937",
+ "type": "github"
+ },
+ "original": {
+ "owner": "pyproject-nix",
+ "repo": "pyproject.nix",
+ "type": "github"
+ }
+ },
"root": {
"inputs": {
"agenix": "agenix",
"agents": "agents",
"disko": "disko",
+ "hermes-agent": "hermes-agent",
"home-manager": "home-manager_2",
"hyprpanel": "hyprpanel",
"llm-agents": "llm-agents",
"m3ta-nixpkgs": "m3ta-nixpkgs",
"nix-colors": "nix-colors",
"nixos-generators": "nixos-generators",
- "nixpkgs": "nixpkgs_7",
+ "nixpkgs": "nixpkgs_8",
"nixpkgs-45570c2": "nixpkgs-45570c2",
"nixpkgs-9e58ed7": "nixpkgs-9e58ed7",
"nixpkgs-locked": "nixpkgs-locked",
@@ -780,7 +928,7 @@
"rose-pine-hyprcursor": {
"inputs": {
"hyprlang": "hyprlang",
- "nixpkgs": "nixpkgs_8",
+ "nixpkgs": "nixpkgs_9",
"utils": "utils"
},
"locked": {
@@ -974,6 +1122,55 @@
"repo": "flake-utils",
"type": "github"
}
+ },
+ "uv2nix": {
+ "inputs": {
+ "nixpkgs": [
+ "hermes-agent",
+ "pyproject-build-systems",
+ "nixpkgs"
+ ],
+ "pyproject-nix": [
+ "hermes-agent",
+ "pyproject-build-systems",
+ "pyproject-nix"
+ ]
+ },
+ "locked": {
+ "lastModified": 1770770348,
+ "narHash": "sha256-A2GzkmzdYvdgmMEu5yxW+xhossP+txrYb7RuzRaqhlg=",
+ "owner": "pyproject-nix",
+ "repo": "uv2nix",
+ "rev": "5d1b2cb4fe3158043fbafbbe2e46238abbc954b0",
+ "type": "github"
+ },
+ "original": {
+ "owner": "pyproject-nix",
+ "repo": "uv2nix",
+ "type": "github"
+ }
+ },
+ "uv2nix_2": {
+ "inputs": {
+ "nixpkgs": [
+ "hermes-agent",
+ "nixpkgs"
+ ],
+ "pyproject-nix": "pyproject-nix_3"
+ },
+ "locked": {
+ "lastModified": 1773039484,
+ "narHash": "sha256-+boo33KYkJDw9KItpeEXXv8+65f7hHv/earxpcyzQ0I=",
+ "owner": "pyproject-nix",
+ "repo": "uv2nix",
+ "rev": "b68be7cfeacbed9a3fa38a2b5adc0cfb81d9bb1f",
+ "type": "github"
+ },
+ "original": {
+ "owner": "pyproject-nix",
+ "repo": "uv2nix",
+ "type": "github"
+ }
}
},
"root": "root",
diff --git a/flake.nix b/flake.nix
index 1727c02..c4b6a96 100644
--- a/flake.nix
+++ b/flake.nix
@@ -65,6 +65,7 @@
url = "github:vercel-labs/skills";
flake = false;
};
+ hermes-agent.url = "github:NousResearch/hermes-agent";
};
outputs = {
@@ -86,10 +87,12 @@
"x86_64-darwin"
];
forAllSystems = nixpkgs.lib.genAttrs systems;
+ allOverlays = import ./overlays {inherit inputs outputs;};
in {
packages =
forAllSystems (system: import ./pkgs nixpkgs.legacyPackages.${system});
- overlays = import ./overlays {inherit inputs outputs;};
+ overlays = builtins.removeAttrs allOverlays ["mkLlmAgentsOverlay"];
+ lib.mkLlmAgentsOverlay = allOverlays.mkLlmAgentsOverlay;
homeManagerModules = import ./modules/home-manager;
nixosConfigurations = {
@@ -128,6 +131,7 @@
agenix.nixosModules.default
nur.modules.nixos.default
m3ta-nixpkgs.nixosModules.default
+ inputs.hermes-agent.nixosModules.default
];
};
m3-helios = nixpkgs.lib.nixosSystem {
diff --git a/home/common/default.nix b/home/common/default.nix
index d6fdf5a..a8be118 100644
--- a/home/common/default.nix
+++ b/home/common/default.nix
@@ -25,7 +25,7 @@
inputs.nur.overlays.default
inputs.m3ta-nixpkgs.overlays.default
inputs.m3ta-nixpkgs.overlays.modifications
- (outputs.overlays.mkLlmAgentsOverlay system)
+ (outputs.lib.mkLlmAgentsOverlay system)
# You can also add overlays exported from other flakes:
# neovim-nightly-overlay.overlays.default
diff --git a/home/features/cli/default.nix b/home/features/cli/default.nix
index 46c05ff..3ab556e 100644
--- a/home/features/cli/default.nix
+++ b/home/features/cli/default.nix
@@ -14,16 +14,6 @@
./television.nix
./zellij.nix
];
- cli.stt-ptt = {
- enable = true;
- whisperPackage =
- if videoDrivers == ["nvidia"]
- then pkgs.whisper-cpp.override {cudaSupport = true;}
- else if videoDrivers == ["amdgpu"]
- then pkgs.whisper-cpp-vulkan
- else pkgs.whisper-cpp;
- model = "ggml-large-v3-turbo";
- };
programs.carapace = {
enable = true;
diff --git a/home/features/coding/default.nix b/home/features/coding/default.nix
index ff39b71..74abdb8 100644
--- a/home/features/coding/default.nix
+++ b/home/features/coding/default.nix
@@ -27,6 +27,13 @@
command = "sh";
args = ["-c" "exec bunx context-mode@latest"];
};
+ Honcho = {
+ command = "sh";
+ args = [
+ "-c"
+ ''exec bunx mcp-remote@latest https://mcp.honcho.dev --header "Authorization:Bearer $(cat /run/agenix/honcho-key)" --header "X-Honcho-User-Name:m3tam3re"''
+ ];
+ };
};
};
@@ -37,6 +44,7 @@
bun
devpod
#devpod-desktop
+ claude-code
code2prompt
gnumake
cmake
@@ -58,8 +66,8 @@
vulkanSupport = videoDrivers == ["amdgpu"];
cudaSupport = videoDrivers == ["nvidia"];
})
+ openshell
openspec
- openwork
alejandra
sidecar
tailwindcss
diff --git a/home/features/desktop/default.nix b/home/features/desktop/default.nix
index 69bea17..15ad082 100644
--- a/home/features/desktop/default.nix
+++ b/home/features/desktop/default.nix
@@ -113,6 +113,8 @@
# brightnessctl
# clipman
distrobox
+ eigent
+ element-desktop
launch-webapp
# eww
# firefox-devedition
@@ -127,7 +129,7 @@
ksnip
msty-studio
nwg-look
- openwork
+ # opencode-desktop
# pamixer
# pavucontrol
# libsForQt5.qtstyleplugins
diff --git a/home/features/desktop/hyprland.nix b/home/features/desktop/hyprland.nix
index 938fe9a..090c809 100644
--- a/home/features/desktop/hyprland.nix
+++ b/home/features/desktop/hyprland.nix
@@ -21,6 +21,7 @@ in {
"while ! hyprpaper-random; do sleep 0.5; done"
"wl-paste --type text --watch cliphist store" # Stores only text data
"wl-paste --type image --watch cliphist store" # Stores only image data "wl-paste -p -t text --watch clipman store -P --histpath=\"~/.local/share/clipman-primary.json\""
+ "vibetyper"
];
env = [
@@ -31,6 +32,7 @@ in {
"XDG_CURRENT_DESKTOP,Hyprland"
"XDG_SESSION_TYPE,wayland"
"XDG_SESSION_DESKTOP,Hyprland"
+ "XKB_DEFAULT_LAYOUT,de"
"NIXOS_OZONE_WL,1"
];
diff --git a/home/m3tam3re/home.nix b/home/m3tam3re/home.nix
index 06a9a61..6681d2d 100644
--- a/home/m3tam3re/home.nix
+++ b/home/m3tam3re/home.nix
@@ -74,6 +74,7 @@
# /etc/profiles/per-user/m3tam3re/etc/profile.d/hm-session-vars.sh
#
home.sessionVariables = {
+ # EDITOR = "emacs";
};
# Let Home Manager install and manage itself.
diff --git a/hosts/common/default.nix b/hosts/common/default.nix
index c3d6cef..db34ab4 100644
--- a/hosts/common/default.nix
+++ b/hosts/common/default.nix
@@ -38,7 +38,7 @@
inputs.m3ta-nixpkgs.overlays.default
inputs.m3ta-nixpkgs.overlays.modifications
- (outputs.overlays.mkLlmAgentsOverlay system)
+ (outputs.lib.mkLlmAgentsOverlay system)
# You can also add overlays exported from other flakes:
# neovim-nightly-overlay.overlays.default
diff --git a/hosts/common/ports.nix b/hosts/common/ports.nix
index b8e0715..85ef345 100644
--- a/hosts/common/ports.nix
+++ b/hosts/common/ports.nix
@@ -38,6 +38,7 @@
kestra = 3018;
outline = 3019;
authentik = 3023;
+ conduit = 3024;
# Home automation
homarr = 7575;
diff --git a/hosts/m3-ares/services/udev.nix b/hosts/m3-ares/services/udev.nix
index 9deb200..43ebcbe 100644
--- a/hosts/m3-ares/services/udev.nix
+++ b/hosts/m3-ares/services/udev.nix
@@ -2,7 +2,8 @@
services.udev.extraRules = ''
SUBSYSTEM=="usb", MODE="0666"
SUBSYSTEM=="leds", KERNEL=="rgb:kbd_backlight*", ACTION=="add", RUN+="${pkgs.coreutils}/bin/chmod a+w /sys/class/leds/%k/multi_intensity"
- '';
+ KERNEL=="uinput", MODE="0660", GROUP="input", OPTIONS+="static_node=uinput"
+ KERNEL=="event*", SUBSYSTEM=="input", MODE="0660", GROUP="input" '';
environment.systemPackages = with pkgs; [
zsa-udev-rules
];
diff --git a/hosts/m3-atlas/secrets.nix b/hosts/m3-atlas/secrets.nix
index 330fa31..a4716bd 100644
--- a/hosts/m3-atlas/secrets.nix
+++ b/hosts/m3-atlas/secrets.nix
@@ -65,6 +65,7 @@
owner = "m3tam3re";
};
authentik-env = {file = ../../secrets/authentik-env.age;};
+ conduit-env = {file = ../../secrets/conduit-env.age;};
};
};
}
diff --git a/hosts/m3-atlas/services/conduit.nix b/hosts/m3-atlas/services/conduit.nix
new file mode 100644
index 0000000..024531f
--- /dev/null
+++ b/hosts/m3-atlas/services/conduit.nix
@@ -0,0 +1,48 @@
+{config, ...}: {
+ services.matrix-conduit = {
+ enable = true;
+ settings.global = {
+ server_name = "m3ta.dev";
+ address = "127.0.0.1";
+ port = config.m3ta.ports.get "conduit";
+ max_request_size = 20000000;
+ allow_registration = false;
+ allow_encryption = true;
+ allow_federation = true;
+ trusted_servers = ["matrix.org"];
+ database_backend = "rocksdb";
+ };
+ secretFile = config.age.secrets.conduit-env.path;
+ };
+
+ # Traefik configuration for Conduit
+ services.traefik.dynamicConfigOptions.http = {
+ services.conduit.loadBalancer.servers = [
+ {
+ url = "http://localhost:${toString (config.m3ta.ports.get "conduit")}/";
+ }
+ ];
+
+ routers.conduit = {
+ rule = "Host(`matrix.m3ta.dev`)";
+ tls = {
+ certResolver = "godaddy";
+ };
+ service = "conduit";
+ entrypoints = "websecure";
+ };
+
+ # Federation endpoint on base domain
+ routers.conduit-federation = {
+ rule = "Host(`m3ta.dev`) && PathPrefix(`/_matrix`)";
+ tls = {
+ certResolver = "godaddy";
+ };
+ service = "conduit";
+ entrypoints = "websecure";
+ };
+ };
+
+ # Open federation port
+ networking.firewall.allowedTCPPorts = [8448];
+}
diff --git a/hosts/m3-atlas/services/default.nix b/hosts/m3-atlas/services/default.nix
index 5a7b668..47e2623 100644
--- a/hosts/m3-atlas/services/default.nix
+++ b/hosts/m3-atlas/services/default.nix
@@ -1,8 +1,10 @@
{
imports = [
+ ./conduit.nix
./containers
./gitea.nix
./gitea-actions-runner.nix
+ ./hermes-agent.nix
./minio.nix
./mysql.nix
./netbird.nix
diff --git a/hosts/m3-atlas/services/hermes-agent.nix b/hosts/m3-atlas/services/hermes-agent.nix
new file mode 100644
index 0000000..8c72954
--- /dev/null
+++ b/hosts/m3-atlas/services/hermes-agent.nix
@@ -0,0 +1,191 @@
+{config, ...}: let
+ # Default ElevenLabs voice: Bella (German-capable female)
+ elevenlabsVoiceId = "hpp4J3VqNfWAUOO0d1Us";
+in {
+ services.hermes-agent = {
+ enable = true;
+ addToSystemPackages = true;
+
+ # Secrets via agenix
+ environmentFiles = [config.age.secrets."hermes-env".path];
+
+ # Non-secret environment variables
+ environment = {
+ #
+ };
+
+ # ββ Container mode (podman) ββββββββββββββββββββββββββββββββββββββββββ
+ container = {
+ enable = true;
+ backend = "podman";
+ };
+
+ settings = {
+ # ββ Model ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ model = {
+ default = "glm-5.1";
+ provider = "zai";
+ base_url = "https://api.z.ai/api/coding/paas/v4/";
+ };
+
+ credential_pool_strategies = {
+ zai = "fill_first";
+ };
+
+ toolsets = ["all"];
+
+ # ββ Agent ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ agent = {
+ max_turns = 90;
+ gateway_timeout = 1800;
+ tool_use_enforcement = "auto";
+ };
+
+ # ββ Terminal βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ terminal = {
+ backend = "local";
+ modal_mode = "auto";
+ cwd = ".";
+ timeout = 180;
+ persistent_shell = true;
+ };
+
+ # ββ Browser ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ browser = {
+ inactivity_timeout = 120;
+ command_timeout = 30;
+ cloud_provider = "local";
+ };
+
+ # ββ Checkpoints / Compression ββββββββββββββββββββββββββββββββββββββ
+ checkpoints = {
+ enabled = true;
+ max_snapshots = 50;
+ };
+
+ file_read_max_chars = 100000;
+
+ compression = {
+ enabled = true;
+ threshold = 0.5;
+ target_ratio = 0.2;
+ protect_last_n = 20;
+ };
+
+ # ββ Display ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ display = {
+ compact = false;
+ personality = "kawaii";
+ resume_display = "full";
+ busy_input_mode = "interrupt";
+ inline_diffs = true;
+ skin = "default";
+ tool_progress = "all";
+ };
+
+ # ββ TTS / STT / Voice ββββββββββββββββββββββββββββββββββββββββββββββ
+ tts = {
+ provider = "elevenlabs";
+ elevenlabs = {
+ voice_id = elevenlabsVoiceId;
+ model_id = "eleven_multilingual_v2";
+ };
+ };
+
+ stt = {
+ enabled = true;
+ provider = "local";
+ local = {model = "base";};
+ };
+
+ voice = {
+ record_key = "ctrl+b";
+ max_recording_seconds = 120;
+ silence_threshold = 200;
+ silence_duration = 3.0;
+ };
+
+ # ββ Memory βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ memory = {
+ memory_enabled = true;
+ user_profile_enabled = true;
+ memory_char_limit = 2200;
+ user_char_limit = 1375;
+ };
+
+ # ββ Delegation βββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ delegation = {
+ max_iterations = 50;
+ };
+
+ # ββ Discord ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ discord = {
+ require_mention = true;
+ auto_thread = true;
+ reactions = true;
+ };
+
+ # ββ Approvals / Security βββββββββββββββββββββββββββββββββββββββββββ
+ approvals = {
+ mode = "manual";
+ timeout = 60;
+ };
+
+ security = {
+ redact_secrets = true;
+ tirith_enabled = true;
+ tirith_fail_open = true;
+ };
+
+ # ββ Cron / Session βββββββββββββββββββββββββββββββββββββββββββββββββ
+ cron = {wrap_response = true;};
+
+ session_reset = {
+ mode = "both";
+ idle_minutes = 1440;
+ at_hour = 4;
+ };
+
+ # ββ Web ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ web = {backend = "exa";};
+
+ # ββ Platform Toolsets ββββββββββββββββββββββββββββββββββββββββββββββ
+ platform_toolsets = {
+ cli = [
+ "browser"
+ "clarify"
+ "code_execution"
+ "cronjob"
+ "delegation"
+ "file"
+ "image_gen"
+ "memory"
+ "session_search"
+ "skills"
+ "terminal"
+ "todo"
+ "tts"
+ "vision"
+ "web"
+ ];
+ telegram = [
+ "browser"
+ "clarify"
+ "code_execution"
+ "cronjob"
+ "delegation"
+ "file"
+ "image_gen"
+ "memory"
+ "session_search"
+ "skills"
+ "terminal"
+ "todo"
+ "tts"
+ "vision"
+ "web"
+ ];
+ };
+ };
+ };
+}
diff --git a/hosts/m3-kratos/secrets.nix b/hosts/m3-kratos/secrets.nix
index f08f7f1..6a9decc 100644
--- a/hosts/m3-kratos/secrets.nix
+++ b/hosts/m3-kratos/secrets.nix
@@ -46,6 +46,10 @@
file = ../../secrets/basecamp-client-secret.age;
owner = "m3tam3re";
};
+ hermes-env = {
+ file = ../../secrets/hermes-env.age;
+ owner = "m3tam3re";
+ };
};
};
}
diff --git a/hosts/m3-kratos/services/udev.nix b/hosts/m3-kratos/services/udev.nix
index 9b7af9b..378e8f6 100644
--- a/hosts/m3-kratos/services/udev.nix
+++ b/hosts/m3-kratos/services/udev.nix
@@ -1,7 +1,8 @@
{pkgs, ...}: {
services.udev.extraRules = ''
SUBSYSTEM=="usb", MODE="0666"
- '';
+ KERNEL=="uinput", MODE="0660", GROUP="input", OPTIONS+="static_node=uinput"
+ KERNEL=="event*", SUBSYSTEM=="input", MODE="0660", GROUP="input" '';
environment.systemPackages = with pkgs; [
zsa-udev-rules
];
diff --git a/overlays/default.nix b/overlays/default.nix
index 46d4d9d..3d30474 100644
--- a/overlays/default.nix
+++ b/overlays/default.nix
@@ -12,7 +12,7 @@
# brave = prev.brave.override {
# commandLineArgs = "--password-store=gnome-libsecret";
- # };
+ # };
# hyprpanel = inputs.hyprpanel.packages.${prev.system}.default.overrideAttrs (prev: {
# version = "latest"; # or whatever version you want
@@ -60,9 +60,9 @@
};
};
- # Flatten llm-agents packages into top-level pkgs namespace.
- # Takes system as parameter to avoid infinite recursion β overlays
- # can't safely access final/prev.system when spreading attributes.
+ # Factory: not a proper overlay itself β takes system to avoid the infinite
+ # recursion that occurs when accessing final/prev.system while the fixed-point
+ # is still being computed. Exposed via outputs.lib, not outputs.overlays.
mkLlmAgentsOverlay = system: _final: _prev:
inputs.llm-agents.packages.${system} or {};
}
diff --git a/secrets.nix b/secrets.nix
index 2a38f74..4398a1c 100644
--- a/secrets.nix
+++ b/secrets.nix
@@ -15,6 +15,7 @@ in {
"secrets/anytype-key.age".publicKeys = systems ++ users;
"secrets/anytype-key-ares.age".publicKeys = systems ++ users;
"secrets/authentik-env.age".publicKeys = systems ++ users;
+ "secrets/conduit-env.age".publicKeys = systems ++ users;
"secrets/baserow-env.age".publicKeys = systems ++ users;
"secrets/ghost-env.age".publicKeys = systems ++ users;
"secrets/littlelink-m3tam3re.age".publicKeys = systems ++ users;
@@ -46,4 +47,6 @@ in {
"secrets/wg-NO.age".publicKeys = systems ++ users;
"secrets/wg-US.age".publicKeys = systems ++ users;
"secrets/wg-BR.age".publicKeys = systems ++ users;
+ "secrets/honcho-key.age".publicKeys = systems ++ users;
+ "secrets/hermes-env.age".publicKeys = systems ++ users;
}
diff --git a/secrets/conduit-env.age b/secrets/conduit-env.age
new file mode 100644
index 0000000..0803125
--- /dev/null
+++ b/secrets/conduit-env.age
@@ -0,0 +1,23 @@
+age-encryption.org/v1
+-> ssh-ed25519 4NLKrw /UWZV80Rvp+855kQZK8nP3rxIpRrtUuSukJNfU/H8zY
+nyaiOkqivEjvYC18rSufNihi4Pw6gCj/t3ZnLDugL9o
+-> ssh-ed25519 5kwcsA GFRK3O5+kWqKofzvL3ZbUhcr9GOQtWl7vMJBf7rSdEs
+cBryXigHXXjLg9v+ipvqSabPf1ePISSlYdRI/c9kJhI
+-> ssh-ed25519 9d4YIQ VQQb1iDYPCNQPF7/c7yFl2QEwCmJuboO4M2u+0a8IlU
+XlHkoPwGtmJ0NEFIpEuSH6+UMWBIFBBTgMZ4vWFiPSM
+-> ssh-ed25519 3Bcr1w Lo3jvXVb5Exy4gcyjaBHwxeKUV+zh8dAkyEL2/foijA
+rPbbibC8tXps6gBw5W9LwSEf7/RSoCgtu87cWIr2kjw
+-> ssh-rsa DQlE7w
+tcpC86YXZrK9fX9/bvVrirrwJPMct8WNpY9VQRBgQmq7CZt1AyZcXE4jHeH9r/1K
+oitC2wMXW39ebZsThZyK/jK3ZUZQFY/ZhUQr3TVdb4tTbHibEaujpqheQsFOGv4I
+9nyN3vtnBpqAfjo2SIXop28m9yepWFthPRUWYSFR2heBQE9uaD+xC/kbRH1+Rcgv
+i/mxEQ/k7+A4AiCoEum6oCReEPvT56HeksOceYezZg+NTzjIcuJH2xeMg6Bjnfx1
+kJCOlKL50uaUiFca8mmElchvDSjPDrOvk4VI0RHGFkl7bfY+2E9srMn7in4beroe
+l6vjlKCD9bPaAj5e3jr4D3ro1oub36fw5VoNoYPK8U/QBF3TG3FiDdouVaIaoYml
+4iK57HUj/RpyvMaUI63rmcq5Yiy5yK6IgL3sYF9ptNdpo4ZYompOetrL4FcQ7EY9
+qXuXZTmJcoXMmPFXapI2zMzYfbLtJHTASVVat27U/Ojuf0WfOJm9PwWoeA/4Mx9C
+
+-> ssh-ed25519 CSMyhg 4uAftUVdcF8S9K7jypmRHi/PtYm9ThJuvZg3qsdPVyM
+8mNE6siFfEPAuUi/gYpqttwdobBDiLBqB6Z7XEvBxQE
+--- 21YTrldwMWS13hp+WNLNkFwViGo8kcgxtAFkmOL4FRE
+Ϊύr<Πo^τ(0wDO
!km;Fχϊb
NΥP΅5Όφέλ΅D$ ε'M½h‘asζ
5ηwδKρξξsCΪχηϊίΨΪΏKqAΉ2?<Ο CξC1 n&uδ]]SLΉ§ ;ΖοhpF§ΤξΩ'`λγΤEOAWΦψV~
\ No newline at end of file
diff --git a/secrets/hermes-env.age b/secrets/hermes-env.age
new file mode 100644
index 0000000000000000000000000000000000000000..f290facd3239247faf0fe8339da55226c6b37a2d
GIT binary patch
literal 1597
zcmYdHPt{G$OD?J`D9Oyv)5|YP*Do{V(zR14F3!+RO))YxHMCSP@$>O6Dpx2C4c7Nd
zbT!H=%MJ5#a*cBL^9(Pjbj;2R4-Ss-H7IuS^@_|(a`F#w4CJcJNG$P95A;nf*LHUI
ztFR0XEcG)jH1S9*Es6^D$SU!4G>i=M40JBbGeNh_G`l>x*ipeN*{jN|tk}TOufj9M
zEvmxM*gVtF#3(Gl!!_ABJ-Z|@B0tI?$R*e~*Ox1xIN!O%(V(Cx$+O%yBfr?!$J;d}
z*~P*lH`Ks4+`_!dIV8O##N9K*$rs%=%M_DH&p?HU9E-$orxf$dR10(c#0cLaQ_swj
zh-5?el;Fbj$V?{}A7?{f-_oii<3O&63}XXdPqSkGD6>LGZO`Ng{WKH9#H29)s6q*EAc=}l6I);|{
zrR%5qrdNcd`4uH*R_3~erWxfV>ib!Qhv<8!`=@7Q2IN-yI3*byyEsR11yly-m3RcZ
zc!n2-8Jef01r>+6Ir
z^*pwH?$#$}W^F$9eZJ!>Nv|@)=|UEpH@{%{t0WOv=3rK8EyTs~w&z2o;oPN@{xSb<
z>yX(0is^fFI#=+@o4Ir9C$EuW&3|#WT~*yeeajN-`^wZ~#gn5N|I#ljhb+=uSd_>Cnp+M%#9tD7f3#oY+)p>vm`1D?1n7
zcmW|l-?qPrGi6fSn${O>T|MQw;=(iBv&7fW-haNiqFH~+$(-FYuN4ZeR$ozdtTwDs
zAnVbl#>Zau#v+$h7Kp2_vFfu@NooGxbZ%Y@;~d3bMycD}ZR|Q!GCz76_uM@>_u$5?
z{`X8jtK&s}vbN7T`oH4k^jquJeem;LRk`2;bJW2