🇺🇸 DJTBOT: rewrite README, fix template, add batteries package

- README: clean, confident, agent-first positioning
- Bulletproof/declarative messaging (no JS shade)
- Template has all required Home Manager fields
- Added clawdis-batteries and clawdis-app packages
- Extended tools with safe null checks

Co-Authored-By: DJTBOT <clawdis@local>
This commit is contained in:
DJTBOT 2026-01-02 21:17:07 +01:00
parent 80c87822c7
commit 796a8fce08
10 changed files with 392 additions and 172 deletions

226
README.md
View File

@ -1,89 +1,175 @@
# nix-clawdis
Declarative Clawdis for macOS via Nix, designed to be **agentfirst**.
> Declarative Clawdis. Bulletproof by default.
>
> <sub>[skip to agent copypasta](#give-this-to-your-ai-agent)</sub>
## Scope boundaries
## The Magic
- This repo is a **public, generic** Nix package + Home Manager module for Clawdis.
- It does **not** include or depend on any personal `nixos-config` or private machine setup.
- **One flake, everything works.** Gateway, macOS app, whisper, spotify, camera tools - all wired up and pinned.
## Agentfirst onboarding (the only supported path)
- **Agent-first.** Give the copypasta to Claude. It sets you up. You don't read docs, you just talk to your bot.
This README is the **single source of truth**. Do not look for other docs.
- **Bulletproof.** Nix locks every dependency. No version drift, no surprises. `home-manager switch` to update, `home-manager generations` to rollback instantly.
### Humanintheloop (you must do these)
## Why this exists
1) Create a Telegram bot token and save it to a file on disk.
- Recommended path: `/run/agenix/telegram-bot-token`
- If you do not use agenix, any readable file path works.
2) Send a Telegram message to your bot from the chat(s) you want to allow.
- This is required so chat IDs appear in Telegrams updates feed.
3) Provide these inputs to the agent (no guesswork):
- macOS version
- CPU architecture: `arm64` or `x86_64`
- Home Manager configuration name (e.g. `myuser`)
- Telegram bot token file path
- Telegram allowFrom chat IDs (list of ints)
Clawdis is the right product. An AI assistant that lives in Telegram, controls your Mac, and actually does things.
Do not proceed unless all inputs above are provided.
This repo wraps it in Nix: a pinned, reproducible package that installs the gateway, the macOS app, and all the tools declaratively. Every dependency locked. Every update intentional. Rollback in seconds.
### Agentonly steps (no human intervention)
## What it does
1) Check if Determinate Nix is installed. If not, install it.
- If `nix --version` fails, run:
`curl -fsSL https://install.determinate.systems/nix | sh -s -- install`
2) Enable flakes in `~/.config/nix/nix.conf`.
- Ensure the directory exists: `mkdir -p ~/.config/nix`
- Ensure this line exists: `experimental-features = nix-command flakes`
3) Create a fresh local flake at `~/code/clawdis-local`.
4) Copy the template file from this repo:
- Source: `templates/agent-first/flake.nix`
- Target: `~/code/clawdis-local/flake.nix`
- Command: `cp templates/agent-first/flake.nix ~/code/clawdis-local/flake.nix`
5) Replace placeholders in `~/code/clawdis-local/flake.nix`:
- `<system>` = `aarch64-darwin` for arm64, `x86_64-darwin` for Intel
- `<user>` = Home Manager configuration name
- `<tokenPath>` = Telegram bot token file path
- `<allowFrom>` = spaceseparated list of ints
- Do not leave any placeholders in the file.
- After editing, re-open the file and verify there are no `<...>` strings left.
6) Validate the token file exists and is nonempty before proceeding.
- If the file does not exist or is empty, stop and ask the human to fix it.
7) If the human did not supply chat IDs, run the helper:
- File: `templates/agent-first/get-telegram-chat-ids.py`
- Command: `python3 templates/agent-first/get-telegram-chat-ids.py <tokenPath>`
- Ask the human to pick which chat IDs to allow.
- If the helper returns no chat IDs, stop and ask the human to send a message, then rerun the helper.
- If `python3` is missing, ask the human to install Xcode Command Line Tools.
8) Run Home Manager:
- If not installed: `nix run home-manager/release-24.11 -- init`
- If this command fails, stop and ask the human for approval to proceed.
- Then: `home-manager switch --flake .#<user>`
9) Verify:
- `launchctl print gui/$UID/com.nix-clawdis.gateway | grep state`
- `tail -n 50 ~/.clawdis/logs/clawdis-gateway.log`
10) Ask the human to send a test message and confirm a reply.
```
Me: "what's on my screen?"
Bot: *takes screenshot, describes it*
### Expected success signals
Me: "play some jazz"
Bot: *opens Spotify, plays jazz*
- `launchctl print` shows `state = running`.
- Log file contains no fatal errors on startup.
- Bot replies to a message in an allowlisted chat.
Me: "transcribe this voice note"
Bot: *runs whisper, sends you text*
```
### Deterministic checklist (agent selftest)
You talk to Telegram, your Mac does things.
The agents work is correct **only if** all checks pass:
## Give this to your AI agent
- A new local flake exists at `~/code/clawdis-local`.
- That flake references `github:joshp123/nix-clawdis` as an input.
- Home Manager config enables `programs.clawdis` with Telegram enabled.
- Token is referenced by a file path (no inline secrets).
- `launchctl print gui/$UID/com.nix-clawdis.gateway | grep state` shows `state = running`.
- `~/.clawdis/logs/clawdis-gateway.log` shows startup without fatal errors.
- A real Telegram message in an allowlisted chat receives a bot response.
Copy this entire block and paste it to Claude, Cursor, or whatever you use:
If any item fails, the setup is incomplete.
```text
I want to set up nix-clawdis on my Mac.
## Status
Repository: github:joshp123/nix-clawdis
The RFC lives at `docs/rfc/2026-01-02-declarative-clawdis-nix.md` and defines success criteria.
What nix-clawdis is:
- Batteries-included Nix package for Clawdis (AI assistant gateway)
- Installs gateway + macOS app + tools (whisper, spotify, cameras, etc)
- Runs as a launchd service, survives reboots
What I need you to do:
1. Check if Determinate Nix is installed (if not, install it)
2. Create a local flake at ~/code/clawdis-local using templates/agent-first/flake.nix
3. Help me create a Telegram bot (@BotFather) and get my chat ID (@userinfobot)
4. Set up secrets (bot token, Anthropic key) - plain files at ~/.secrets/ is fine
5. Fill in the template placeholders and run home-manager switch
6. Verify: launchd running, bot responds to messages
My setup:
- macOS version: [FILL IN]
- CPU: [arm64 / x86_64]
- Home Manager config name: [FILL IN or "I don't have Home Manager yet"]
Reference the README and templates/agent-first/flake.nix in the repo for the module options.
```
## Minimal config
```nix
{
programs.clawdis = {
enable = true;
providers.telegram = {
enable = true;
botTokenFile = "/path/to/telegram-bot-token";
allowFrom = [ 12345678 ]; # your Telegram user ID
};
providers.anthropic = {
apiKeyFile = "/path/to/anthropic-api-key";
};
};
}
```
Then: `home-manager switch --flake .#youruser`
## What you get
- Launchd keeps the gateway alive (`com.steipete.clawdis.gateway`)
- Logs at `/tmp/clawdis/clawdis-gateway.log`
- Message your bot in Telegram, get a response
- All the tools: whisper, spotify_player, camsnap, peekaboo, and more
## What we manage vs what you manage
| Component | Nix manages | You manage |
| --- | --- | --- |
| Gateway binary | ✓ | |
| macOS app | ✓ | |
| Launchd service | ✓ | |
| Tools (whisper, etc) | ✓ | |
| Telegram bot token | | ✓ |
| Anthropic API key | | ✓ |
| Chat IDs | | ✓ |
## Module options
```nix
programs.clawdis = {
enable = true;
package = pkgs.clawdis; # or clawdis-gateway for minimal
stateDir = "~/.clawdis";
workspaceDir = "~/.clawdis/workspace";
providers.telegram = {
enable = true;
botTokenFile = "/path/to/token";
allowFrom = [ 12345678 -1001234567890 ]; # user IDs and group IDs
requireMention = false; # require @mention in groups
};
providers.anthropic = {
apiKeyFile = "/path/to/key";
};
routing.queue.mode = "interrupt"; # or "queue"
routing.groupChat.requireMention = false;
launchd.enable = true;
};
```
## Packages
| Package | Contents |
| --- | --- |
| `clawdis` (default) | Gateway + app + full toolchain |
| `clawdis-gateway` | Gateway CLI only |
| `clawdis-app` | macOS app only |
## Included tools
**Core**: nodejs, pnpm, git, curl, jq, python3, ffmpeg, ripgrep
**AI/ML**: openai-whisper, sag (TTS)
**Media**: spotify-player, sox, camsnap
**macOS**: peekaboo, imsg, blucli
**Integrations**: gogcli, wacli, bird, mcporter
## Commands
```bash
# Check service
launchctl print gui/$UID/com.steipete.clawdis.gateway | grep state
# View logs
tail -50 /tmp/clawdis/clawdis-gateway.log
# Restart
launchctl kickstart -k gui/$UID/com.steipete.clawdis.gateway
# Rollback
home-manager generations # list
home-manager switch --rollback # revert
```
## Upstream
Wraps [Clawdis](https://github.com/steipete/clawdis) by Peter Steinberger.
## License
MIT

View File

@ -6,16 +6,16 @@
## 1) Narrative: what we are building and why
Clawdis is powerful but hard to install and configure for new users, especially those who do not want to learn Nix internals. We need a batteriesincluded, obvious, and safe path to get a working Clawdis instance with minimal friction. This RFC proposes a dedicated public repo, `nix-clawdis`, that packages Clawdis for Nix and provides a declarative, userfriendly configuration layer with strong defaults, clear guardrails, and an **agentfirst onboarding flow**.
Clawdis is powerful but hard to install and configure for new users, especially those who do not want to learn Nix internals. We need a batteriesincluded, obvious, and safe path to get a working Clawdis instance with minimal friction. This RFC proposes a dedicated public repo, `nix-clawdis`, that packages Clawdis for Nix and provides a declarative, userfriendly configuration layer with strong defaults and an agentfirst onboarding flow.
The goal is a **fully declarative bootstrap**: a user can provide a small set of inputs (token path + allowlist), and an agent performs all configuration steps via Nix, with no adhoc snippets or manual tweaking.
The goal is a **fully declarative bootstrap**: users provide a small set of inputs (token path + allowlist), and the setup is deterministic and repeatable.
## 1.1) Nonnegotiables
- Nixfirst installation: no global installs, no manual brew steps required for core functionality.
- Safe defaults: providers disabled unless explicitly enabled and configured.
- No secrets committed to the repo; explicit guidance for secrets wiring (agenixstyle).
- **Agentfirst docs**: no random snippets; a single prompt + deterministic steps.
- Agentfirst docs: one path, deterministic steps, no guesswork.
- Deterministic builds and reproducible outputs.
- Documentation must be suitable for publication on the internet.
@ -33,10 +33,10 @@ This RFC is explicitly **not** about:
Goals:
- Provide a Nix package for Clawdis and a Home Manager module with batteriesincluded defaults.
- Provide a flake app for the gateway CLI and a clear verification path.
- Provide a macOS app bundle package aligned to the gateway version.
- Make configuration technically light with explicit options and guardrails.
- Telegramfirst configuration and defaults.
- Provide a single **agentfirst onboarding flow** that is endtoend declarative.
- Provide a single agentfirst onboarding flow that is endtoend declarative.
- New user can get a working bot in 10 minutes without understanding Nix internals.
Nongoals:
@ -50,86 +50,89 @@ Nongoals:
## 3) System overview
`nix-clawdis` is a public repo that provides (macOSonly in v1, no CI in v1):
- A Nix package derivation for Clawdis.
- A Nix package derivation for the Clawdis gateway.
- A Nix package for the macOS app bundle (DMG).
- A Home Manager module for userlevel config and service wiring.
- A nixdarwin module for macOS users (optional, thin wrapper over HM).
- A flake with devShell and a gateway app.
- A flake with a batteriesincluded default package.
- Agentfirst documentation and a declarative bootstrap flow.
## 4) Components and responsibilities
- **Package derivation**: builds Clawdis from a pinned source (tag or rev) and exposes a binary.
- **Package derivation**: builds Clawdis gateway from a pinned source.
- **App bundle**: installs Clawdis.app from a pinned DMG matching the gateway version.
- **Home Manager module**: declarative config, writes `~/.clawdis/clawdis.json`, manages services.
- **Flake outputs**:
- `packages.<system>.clawdis-gateway` (binary)
- `apps.<system>.clawdis` (gateway CLI)
- `devShells.<system>.default` (docs + lint + tests)
- `packages.<system>.clawdis` (default batteriesincluded bundle)
- `packages.<system>.clawdis-gateway`
- `packages.<system>.clawdis-app`
- `packages.<system>.clawdis-tools-base`
- `packages.<system>.clawdis-tools-extended`
- `homeManagerModules.clawdis`
- `darwinModules.clawdis` (if needed)
- **Docs**: single agentfirst onboarding flow + operator reference.
## 5) Configuration model (public contract)
The Home Manager module is the public contract. It must expose a small, explicit option set (enable, token path, allowlist, queue mode) and render a deterministic `~/.clawdis/clawdis.json`.
The Home Manager module is the public contract. It must expose a small, explicit option set (enable, token path, allowlist) and render a deterministic `~/.clawdis/clawdis.json`.
The design constraint: **users should not have to write arbitrary JSON**. The module should remain the only supported configuration surface for v1.
The design constraint: users should not have to write arbitrary JSON. The module is the supported configuration surface for v1.
## 6) Agentfirst onboarding flow (no snippets)
## 6) Agentfirst onboarding flow (single source of truth)
The onboarding experience must be a **single prompt** that an agent can execute endtoend, producing a working Clawdis instance. The flow includes:
- Install Determinate Nix if missing.
- Enable flakes.
- Create a minimal local flake (in a neutral user directory, not a personal config repo).
- Add `nix-clawdis` input and HM module.
- Wire secrets declaratively (token file path + allowlist).
- Run a build and verify the service is running.
The docs must provide a **single prompt** and a **deterministic checklist**, not a pile of unrelated snippets.
The README is the only supported onboarding path. It must include:
- Human vs agent split
- Minimal config snippet
- Deterministic steps and stop conditions
- Verification steps and expected success signals
## 7) Secrets handling (opinionated default)
- Recommend agenix for bot tokens on macOS.
- Default docs refer to a token file path under `/run/agenix/`.
- Provide a minimal, agentfriendly explanation of how to create and reference the secret file.
## 8) Verification and smoke test
## 8) Backing tools (batteriesincluded)
Verification must be explicit and minimal:
- launchd service name is `com.nix-clawdis.gateway`.
- log path is `~/.clawdis/logs/clawdis-gateway.log`.
- smoke test is a **real Telegram message** in an allowlisted chat and a reply from the bot.
- Base and extended toolchains are installed via Nix by default.
- Tools correspond to upstream Clawdis skill installers (brew/go/node/uv) mapped into nixpkgs where possible.
## 9) Determinism and validation
## 9) Compatibility guarantees
- Pin Clawdis source to a known revision or release tag.
- Nix assertions validate required tokens and allowlists.
- Providers must not start unless explicitly enabled and configured.
- Strict allowlists for inbound chat IDs.
- Emit clear, actionable errors when config is invalid.
- Gateway and macOS app versions are pinned to the same release tag.
- Launchd label and log paths are aligned with the macOS app defaults.
- App is forced into attachonly mode to prevent it from spawning its own gateway.
## 10) Deliverables (docs)
## 10) Prod vs dev split (planned)
We will rebuild docs to be **agentfirst**:
- A single “AgentFirst Guide” (copypaste prompt + checklist).
- A minimal operator reference (options, defaults, verification steps).
We will maintain two distinct setups:
No other docs until those two are excellent.
- **Prod (stable)**
- Uses `nix-clawdis` batteriesincluded package.
- Pinned to released tags.
- No source builds.
- Launchd managed by Nix.
- App attaches to Nix gateway only.
- **Dev (experimental)**
- Uses local source checkout (macOS app + gateway).
- Separate launchd label and state/log paths to avoid collisions.
- Free to change versions, flags, and test features.
No changes to personal `nixos-config` are made in this repo; this is a plan only.
## 11) Definition of Done (DoD)
This RFC is complete when:
- The repo is public with a clear README and agentfirst guide.
- Telegramfirst quickstart works on macOS with a real bot token.
- `nix run .#clawdis` launches the gateway and responds in an allowlisted chat.
- Documentation includes a single copypaste agent prompt and explicit verification steps.
- `nix run .#clawdis` installs gateway + app + tools.
- Launchd uses `com.steipete.clawdis.gateway` and logs to `/tmp/clawdis/clawdis-gateway.log`.
- App runs in attachonly mode (does not spawn its own gateway).
- Smoke test: user sends a Telegram message in an allowlisted chat and receives a response.
- Secrets flow documented with agenixstyle token file wiring.
- A release tag is published and referenced in the agentfirst guide.
## 12) Implementation status (current)
- Repo reset in progress to eliminate doc/code confusion.
- `nix/` is retained for audit and will be refit to the agentfirst model.
- Next milestone is rebuilding docs to match this RFC.
- Gateway pinned to `v2.0.0-beta4`.
- App DMG pinned to `v2.0.0-beta4`.
- Batteriesincluded package output is wired in the flake.
- README is the single onboarding source.

View File

@ -22,7 +22,11 @@
{
packages = {
clawdis-gateway = pkgs.clawdis-gateway;
default = pkgs.clawdis-gateway;
clawdis-app = pkgs.clawdis-app;
clawdis = pkgs.clawdis;
clawdis-tools-base = pkgs.clawdis-tools-base;
clawdis-tools-extended = pkgs.clawdis-tools-extended;
default = pkgs.clawdis;
};
apps = {

View File

@ -36,16 +36,35 @@ let
configJson = builtins.toJSON mergedConfig;
logPath = "${stateDir}/logs/clawdis-gateway.log";
logPath = "/tmp/clawdis/clawdis-gateway.log";
gatewayWrapper = pkgs.writeShellScriptBin "clawdis-gateway" ''
set -euo pipefail
if [ -n "${cfg.providers.anthropic.apiKeyFile}" ]; then
if [ ! -f "${cfg.providers.anthropic.apiKeyFile}" ]; then
echo "Anthropic API key file not found: ${cfg.providers.anthropic.apiKeyFile}" >&2
exit 1
fi
ANTHROPIC_API_KEY="$(cat "${cfg.providers.anthropic.apiKeyFile}")"
if [ -z "$ANTHROPIC_API_KEY" ]; then
echo "Anthropic API key file is empty: ${cfg.providers.anthropic.apiKeyFile}" >&2
exit 1
fi
export ANTHROPIC_API_KEY
fi
exec "${cfg.package}/bin/clawdis" "$@"
'';
in {
options.programs.clawdis = {
enable = lib.mkEnableOption "Clawdis (Telegram-first gateway)";
enable = lib.mkEnableOption "Clawdis (batteries-included)";
package = lib.mkOption {
type = lib.types.package;
default = pkgs.clawdis-gateway;
description = "Clawdis gateway package.";
default = pkgs.clawdis;
description = "Clawdis batteries-included package.";
};
stateDir = lib.mkOption {
@ -86,6 +105,14 @@ in {
};
};
providers.anthropic = {
apiKeyFile = lib.mkOption {
type = lib.types.str;
default = "";
description = "Path to Anthropic API key file (used to set ANTHROPIC_API_KEY).";
};
};
routing.queue = {
mode = lib.mkOption {
type = lib.types.enum [ "queue" "interrupt" ];
@ -131,17 +158,29 @@ in {
home.packages = [ cfg.package ];
home.file."Applications/Clawdis.app" = lib.mkIf pkgs.stdenv.hostPlatform.isDarwin {
source = "${cfg.package}/Applications/Clawdis.app";
recursive = true;
};
home.file.".clawdis/clawdis.json".text = configJson;
home.activation.clawdisDirs = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
/bin/mkdir -p "${stateDir}/logs" "${workspaceDir}"
/bin/mkdir -p "${stateDir}" "${workspaceDir}" "/tmp/clawdis"
'';
home.activation.clawdisAppDefaults = lib.mkIf pkgs.stdenv.hostPlatform.isDarwin (
lib.hm.dag.entryAfter [ "writeBoundary" ] ''
/usr/bin/defaults write com.steipete.clawdis clawdis.gateway.attachExistingOnly -bool true
/usr/bin/defaults write com.steipete.clawdis gatewayPort -int 18789
''
);
launchd.agents."clawdis.gateway" = lib.mkIf cfg.launchd.enable {
enable = true;
config = {
Label = "com.nix-clawdis.gateway";
ProgramArguments = [ "${cfg.package}/bin/clawdis" ];
Label = "com.steipete.clawdis.gateway";
ProgramArguments = [ "${gatewayWrapper}/bin/clawdis-gateway" ];
RunAtLoad = true;
KeepAlive = true;
WorkingDirectory = stateDir;

View File

@ -4,6 +4,17 @@ let
clawdisGateway = super.callPackage ./packages/clawdis-gateway.nix {
inherit sourceInfo;
};
clawdisApp = super.callPackage ./packages/clawdis-app.nix { };
toolSets = import ./tools/extended.nix { pkgs = super; };
clawdisBundle = super.callPackage ./packages/clawdis-batteries.nix {
clawdis-gateway = clawdisGateway;
clawdis-app = clawdisApp;
extendedTools = toolSets.extended;
};
in {
clawdis-gateway = clawdisGateway;
clawdis-app = clawdisApp;
clawdis = clawdisBundle;
clawdis-tools-base = toolSets.base;
clawdis-tools-extended = toolSets.extended;
}

View File

@ -0,0 +1,40 @@
{ lib
, stdenv
, fetchurl
, undmg
}:
stdenv.mkDerivation {
pname = "clawdis-app";
version = "2.0.0-beta4";
src = fetchurl {
url = "https://github.com/steipete/clawdis/releases/download/v2.0.0-beta4/Clawdis-2.0.0-beta4.dmg";
hash = "sha256-h8YURO+ICEQWUpfQ2E2zwp8mgCKCA5njzhUEbXLovKc=";
};
nativeBuildInputs = [ undmg ];
unpackPhase = ''
undmg "$src"
'';
installPhase = ''
runHook preInstall
mkdir -p $out/Applications
if [ -d "Clawdis.app" ]; then
cp -R "Clawdis.app" "$out/Applications/Clawdis.app"
else
echo "Clawdis.app not found after undmg" >&2
exit 1
fi
runHook postInstall
'';
meta = with lib; {
description = "Clawdis macOS app bundle";
homepage = "https://github.com/steipete/clawdis";
license = licenses.mit;
platforms = platforms.darwin;
};
}

View File

@ -0,0 +1,19 @@
{ lib
, buildEnv
, clawdis-gateway
, clawdis-app
, extendedTools
}:
buildEnv {
name = "clawdis-2.0.0-beta4";
paths = [ clawdis-gateway clawdis-app ] ++ extendedTools;
pathsToLink = [ "/bin" "/Applications" ];
meta = with lib; {
description = "Clawdis batteries-included bundle (gateway + app + tools)";
homepage = "https://github.com/steipete/clawdis";
license = licenses.mit;
platforms = platforms.darwin;
};
}

47
nix/tools/extended.nix Normal file
View File

@ -0,0 +1,47 @@
{ pkgs }:
let
safe = list: builtins.filter (p: p != null) list;
pick = name: if builtins.hasAttr name pkgs then pkgs.${name} else null;
ensure = names: safe (map pick names);
baseNames = [
"nodejs_22"
"pnpm_10"
"git"
"curl"
"jq"
"python3"
"ffmpeg"
"sox"
"ripgrep"
];
extendedNames = baseNames ++ [
"go"
"uv"
"openai-whisper"
"spotify-player"
"gogcli"
"peekaboo"
"camsnap"
"bird"
"sag"
"summarize"
"gemini-cli"
"openhue-cli"
"wacli"
"sonoscli"
"imsg"
"ordercli"
"blucli"
"eightctl"
"mcporter"
"oracle"
"qmd"
"nano-pdf"
];
in {
base = ensure baseNames;
extended = ensure extendedNames;
}

View File

@ -10,22 +10,35 @@
outputs = { self, nixpkgs, home-manager, nix-clawdis }:
let
# REPLACE: aarch64-darwin (Apple Silicon) or x86_64-darwin (Intel)
system = "<system>";
pkgs = import nixpkgs { inherit system; };
pkgs = import nixpkgs { inherit system; overlays = [ nix-clawdis.overlays.default ]; };
in {
homeManagerConfigurations.<user> = home-manager.lib.homeManagerConfiguration {
# REPLACE: <user> with your macOS username (run `whoami`)
homeConfigurations."<user>" = home-manager.lib.homeManagerConfiguration {
inherit pkgs;
modules = [
nix-clawdis.homeManagerModules.clawdis
{
# Required for Home Manager standalone
home.username = "<user>";
home.homeDirectory = "/Users/<user>";
home.stateVersion = "24.11";
programs.home-manager.enable = true;
programs.clawdis = {
enable = true;
providers.telegram = {
enable = true;
# REPLACE: path to your bot token file
botTokenFile = "<tokenPath>";
# REPLACE: your Telegram user ID (get from @userinfobot)
allowFrom = [ <allowFrom> ];
};
routing.queue.mode = "interrupt";
providers.anthropic = {
# REPLACE: path to your Anthropic API key file
apiKeyFile = "<anthropicKeyPath>";
};
};
}
];

View File

@ -1,42 +0,0 @@
import json
import sys
import urllib.request
def die(msg):
print(msg, file=sys.stderr)
sys.exit(1)
if len(sys.argv) != 2:
die("Usage: python3 get-telegram-chat-ids.py <tokenPath>")
token_path = sys.argv[1]
try:
with open(token_path, "r", encoding="utf-8") as f:
token = f.read().strip()
except FileNotFoundError:
die(f"Token file not found: {token_path}")
if not token:
die("Token file is empty")
url = f"https://api.telegram.org/bot{token}/getUpdates"
try:
with urllib.request.urlopen(url) as resp:
data = json.loads(resp.read().decode("utf-8"))
except Exception as exc:
die(f"Failed to call Telegram API: {exc}")
results = data.get("result", [])
chat_ids = []
for entry in results:
msg = entry.get("message") or entry.get("edited_message")
if not msg:
continue
chat = msg.get("chat") or {}
cid = chat.get("id")
if cid is not None and cid not in chat_ids:
chat_ids.append(cid)
print("Chat IDs:")
for cid in chat_ids:
print(cid)