🇺🇸 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:
parent
80c87822c7
commit
796a8fce08
226
README.md
226
README.md
@ -1,89 +1,175 @@
|
||||
# nix-clawdis
|
||||
|
||||
Declarative Clawdis for macOS via Nix, designed to be **agent‑first**.
|
||||
> 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.
|
||||
|
||||
## Agent‑first 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.
|
||||
|
||||
### Human‑in‑the‑loop (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 Telegram’s 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.
|
||||
|
||||
### Agent‑only 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>` = space‑separated 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 non‑empty 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 re‑run 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 self‑test)
|
||||
You talk to Telegram, your Mac does things.
|
||||
|
||||
The agent’s 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
|
||||
|
||||
@ -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 batteries‑included, 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, user‑friendly configuration layer with strong defaults, clear guardrails, and an **agent‑first 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 batteries‑included, 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, user‑friendly configuration layer with strong defaults and an agent‑first 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 ad‑hoc 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) Non‑negotiables
|
||||
|
||||
- Nix‑first 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 (agenix‑style).
|
||||
- **Agent‑first docs**: no random snippets; a single prompt + deterministic steps.
|
||||
- Agent‑first 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 batteries‑included 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.
|
||||
- Telegram‑first configuration and defaults.
|
||||
- Provide a single **agent‑first onboarding flow** that is end‑to‑end declarative.
|
||||
- Provide a single agent‑first onboarding flow that is end‑to‑end declarative.
|
||||
- New user can get a working bot in 10 minutes without understanding Nix internals.
|
||||
|
||||
Non‑goals:
|
||||
@ -50,86 +50,89 @@ Non‑goals:
|
||||
## 3) System overview
|
||||
|
||||
`nix-clawdis` is a public repo that provides (macOS‑only 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 user‑level config and service wiring.
|
||||
- A nix‑darwin module for macOS users (optional, thin wrapper over HM).
|
||||
- A flake with devShell and a gateway app.
|
||||
- A flake with a batteries‑included default package.
|
||||
- Agent‑first 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 batteries‑included 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 agent‑first 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) Agent‑first onboarding flow (no snippets)
|
||||
## 6) Agent‑first onboarding flow (single source of truth)
|
||||
|
||||
The onboarding experience must be a **single prompt** that an agent can execute end‑to‑end, 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, agent‑friendly explanation of how to create and reference the secret file.
|
||||
|
||||
## 8) Verification and smoke test
|
||||
## 8) Backing tools (batteries‑included)
|
||||
|
||||
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 attach‑only mode to prevent it from spawning its own gateway.
|
||||
|
||||
## 10) Deliverables (docs)
|
||||
## 10) Prod vs dev split (planned)
|
||||
|
||||
We will rebuild docs to be **agent‑first**:
|
||||
- A single “Agent‑First Guide” (copy‑paste 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` batteries‑included 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 agent‑first guide.
|
||||
- Telegram‑first 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 copy‑paste 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 attach‑only 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 agenix‑style token file wiring.
|
||||
- A release tag is published and referenced in the agent‑first 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 agent‑first 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`.
|
||||
- Batteries‑included package output is wired in the flake.
|
||||
- README is the single onboarding source.
|
||||
|
||||
|
||||
@ -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 = {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
40
nix/packages/clawdis-app.nix
Normal file
40
nix/packages/clawdis-app.nix
Normal 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;
|
||||
};
|
||||
}
|
||||
19
nix/packages/clawdis-batteries.nix
Normal file
19
nix/packages/clawdis-batteries.nix
Normal 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
47
nix/tools/extended.nix
Normal 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;
|
||||
}
|
||||
@ -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>";
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
@ -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)
|
||||
Loading…
Reference in New Issue
Block a user