Rename clawdis to clawdbot everywhere
This commit is contained in:
parent
82ee44aea4
commit
97127c98fe
52
README.md
52
README.md
@ -64,7 +64,7 @@ What I need you to do:
|
||||
1. Check if Determinate Nix is installed (if not, install it)
|
||||
2. Create a local flake at ~/code/clawdbot-local using templates/agent-first/flake.nix
|
||||
3. Create a docs dir next to the config (e.g., ~/code/clawdbot-local/documents) with AGENTS.md, SOUL.md, TOOLS.md
|
||||
- If ~/.clawdis/workspace already has these files, adopt them into the documents dir first
|
||||
- If ~/.clawdbot/workspace already has these files, adopt them into the documents dir first
|
||||
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
|
||||
@ -85,7 +85,7 @@ Use this for the simplest setup. For richer config (per‑group overrides), use
|
||||
|
||||
```nix
|
||||
{
|
||||
programs.clawdis = {
|
||||
programs.clawdbot = {
|
||||
enable = true;
|
||||
providers.telegram = {
|
||||
enable = true;
|
||||
@ -109,20 +109,20 @@ Then: `home-manager switch --flake .#youruser`
|
||||
## Small but useful config (sensible defaults)
|
||||
|
||||
This is still single‑instance, but uses `instances.default` to unlock per‑group mention rules.
|
||||
If `instances` is set, you don’t need `programs.clawdis.enable`.
|
||||
If `instances` is set, you don’t need `programs.clawdbot.enable`.
|
||||
Group mention overrides below mirror upstream Clawdbot config.
|
||||
Secrets are shown using `/run/agenix/...` (from a repo with your agenix secrets), but any file path works.
|
||||
Docs are managed from `./documents` and symlinked into the workspace on each switch.
|
||||
|
||||
```nix
|
||||
{
|
||||
programs.clawdis = {
|
||||
programs.clawdbot = {
|
||||
documents = ./documents;
|
||||
instances.default = {
|
||||
enable = true;
|
||||
package = pkgs.clawdis; # batteries-included
|
||||
stateDir = "~/.clawdis";
|
||||
workspaceDir = "~/.clawdis/workspace";
|
||||
package = pkgs.clawdbot; # batteries-included
|
||||
stateDir = "~/.clawdbot";
|
||||
workspaceDir = "~/.clawdbot/workspace";
|
||||
|
||||
providers.telegram = {
|
||||
enable = true;
|
||||
@ -190,7 +190,7 @@ let
|
||||
prod = {
|
||||
enable = true;
|
||||
# Prod gateway pin (comes from nix-clawdbot input @ v0.1.0 above).
|
||||
package = inputs.nix-clawdbot.packages.${pkgs.system}.clawdis-gateway;
|
||||
package = inputs.nix-clawdbot.packages.${pkgs.system}.clawdbot-gateway;
|
||||
providers.telegram.enable = true;
|
||||
providers.telegram.botTokenFile = "/run/agenix/telegram-prod";
|
||||
providers.telegram.allowFrom = [ 12345678 ];
|
||||
@ -199,10 +199,10 @@ let
|
||||
};
|
||||
in {
|
||||
# Pinned macOS app (POC: no local app builds, uses nix-clawdbot @ v0.1.0 above).
|
||||
programs.clawdis.appPackage =
|
||||
inputs.nix-clawdbot.packages.${pkgs.system}.clawdis-app;
|
||||
programs.clawdis.documents = ./documents;
|
||||
programs.clawdis.instances = {
|
||||
programs.clawdbot.appPackage =
|
||||
inputs.nix-clawdbot.packages.${pkgs.system}.clawdbot-app;
|
||||
programs.clawdbot.documents = ./documents;
|
||||
programs.clawdbot.instances = {
|
||||
prod = prod;
|
||||
dev = prod // {
|
||||
# Dev uses the same pinned macOS app (from nix-clawdbot input),
|
||||
@ -247,7 +247,7 @@ your-plugin/
|
||||
|
||||
Example implementation: `examples/hello-world-plugin`.
|
||||
|
||||
**`flake.nix` (minimal `clawdisPlugin`):**
|
||||
**`flake.nix` (minimal `clawdbotPlugin`):**
|
||||
|
||||
```nix
|
||||
{
|
||||
@ -255,7 +255,7 @@ Example implementation: `examples/hello-world-plugin`.
|
||||
let
|
||||
pkgs = import nixpkgs { system = builtins.currentSystem; };
|
||||
in {
|
||||
clawdisPlugin = {
|
||||
clawdbotPlugin = {
|
||||
name = "hello-world";
|
||||
skills = [ ./skills/hello-world ];
|
||||
packages = [ pkgs.hello ]; # example CLI
|
||||
@ -289,14 +289,14 @@ per‑plugin `config`.
|
||||
Goal: Make this repo a nix‑clawdbot‑native plugin with the standard contract.
|
||||
|
||||
Contract to implement:
|
||||
1) Add clawdisPlugin output in flake.nix:
|
||||
1) Add clawdbotPlugin output in flake.nix:
|
||||
- name
|
||||
- skills (paths to SKILL.md dirs)
|
||||
- packages (CLI packages to put on PATH)
|
||||
- needs (stateDirs + requiredEnv)
|
||||
|
||||
Example:
|
||||
clawdisPlugin = {
|
||||
clawdbotPlugin = {
|
||||
name = "my-plugin";
|
||||
skills = [ ./skills/my-plugin ];
|
||||
packages = [ self.packages.${system}.default ];
|
||||
@ -351,8 +351,8 @@ Deliverables: flake output, env overrides, AGENTS.md, skill update.
|
||||
|
||||
## How it wires up
|
||||
|
||||
- Nix pulls the plugin, reads `clawdisPlugin`, and installs the CLI(s).
|
||||
- Skills are symlinked into `~/.clawdis/skills/<plugin>/<skill>`.
|
||||
- Nix pulls the plugin, reads `clawdbotPlugin`, and installs the CLI(s).
|
||||
- Skills are symlinked into `~/.clawdbot/skills/<plugin>/<skill>`.
|
||||
- Clawdbot loads managed skills automatically at runtime.
|
||||
- Any plugin services run as **user‑level** launchd agents (no sudo).
|
||||
- MVP scope: tools/skills should come **from plugins only** (no ad‑hoc installs).
|
||||
@ -360,8 +360,8 @@ Deliverables: flake output, env overrides, AGENTS.md, skill update.
|
||||
|
||||
## What you get
|
||||
|
||||
- Launchd keeps the gateway alive (`com.steipete.clawdis.gateway`)
|
||||
- Logs at `/tmp/clawdis/clawdis-gateway.log`
|
||||
- Launchd keeps the gateway alive (`com.steipete.clawdbot.gateway`)
|
||||
- Logs at `/tmp/clawdbot/clawdbot-gateway.log`
|
||||
- Message your bot in Telegram, get a response
|
||||
- All the tools: whisper, spotify_player, camsnap, peekaboo, and more
|
||||
|
||||
@ -381,9 +381,9 @@ Deliverables: flake output, env overrides, AGENTS.md, skill update.
|
||||
|
||||
| Package | Contents |
|
||||
| --- | --- |
|
||||
| `clawdis` (default) | Gateway + app + full toolchain |
|
||||
| `clawdis-gateway` | Gateway CLI only |
|
||||
| `clawdis-app` | macOS app only |
|
||||
| `clawdbot` (default) | Gateway + app + full toolchain |
|
||||
| `clawdbot-gateway` | Gateway CLI only |
|
||||
| `clawdbot-app` | macOS app only |
|
||||
|
||||
## Plugin collisions (override policy)
|
||||
|
||||
@ -407,13 +407,13 @@ We should warn on collisions so it’s obvious.
|
||||
|
||||
```bash
|
||||
# Check service
|
||||
launchctl print gui/$UID/com.steipete.clawdis.gateway | grep state
|
||||
launchctl print gui/$UID/com.steipete.clawdbot.gateway | grep state
|
||||
|
||||
# View logs
|
||||
tail -50 /tmp/clawdis/clawdis-gateway.log
|
||||
tail -50 /tmp/clawdbot/clawdbot-gateway.log
|
||||
|
||||
# Restart
|
||||
launchctl kickstart -k gui/$UID/com.steipete.clawdis.gateway
|
||||
launchctl kickstart -k gui/$UID/com.steipete.clawdbot.gateway
|
||||
|
||||
# Rollback
|
||||
home-manager generations # list
|
||||
|
||||
@ -61,19 +61,19 @@ Non‑goals:
|
||||
|
||||
- **Package derivation**: builds Clawdbot gateway from a pinned source.
|
||||
- **App bundle**: installs Clawdbot.app from a pinned DMG matching the gateway version.
|
||||
- **Home Manager module**: declarative config, writes `~/.clawdis/clawdis.json`, manages services.
|
||||
- **Home Manager module**: declarative config, writes `~/.clawdbot/clawdbot.json`, manages services.
|
||||
- **Flake outputs**:
|
||||
- `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)
|
||||
- `packages.<system>.clawdbot` (default batteries‑included bundle)
|
||||
- `packages.<system>.clawdbot-gateway`
|
||||
- `packages.<system>.clawdbot-app`
|
||||
- `packages.<system>.clawdbot-tools-base`
|
||||
- `packages.<system>.clawdbot-tools-extended`
|
||||
- `homeManagerModules.clawdbot`
|
||||
- `darwinModules.clawdbot` (if needed)
|
||||
|
||||
## 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) 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 `~/.clawdbot/clawdbot.json`.
|
||||
|
||||
The design constraint: users should not have to write arbitrary JSON. The module is the supported configuration surface for v1.
|
||||
|
||||
@ -124,8 +124,8 @@ No changes to personal `nixos-config` are made in this repo; this is a plan only
|
||||
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` installs gateway + app + tools.
|
||||
- Launchd uses `com.steipete.clawdis.gateway` and logs to `/tmp/clawdis/clawdis-gateway.log`.
|
||||
- `nix run .#clawdbot` installs gateway + app + tools.
|
||||
- Launchd uses `com.steipete.clawdbot.gateway` and logs to `/tmp/clawdbot/clawdbot-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.
|
||||
|
||||
@ -3,5 +3,5 @@
|
||||
This plugin is intentionally tiny.
|
||||
|
||||
Knobs
|
||||
- CLAWDIS_USER (optional): name to greet
|
||||
- CLAWDBOT_USER (optional): name to greet
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
drv = self.packages.${system}.default;
|
||||
};
|
||||
|
||||
clawdisPlugin = {
|
||||
clawdbotPlugin = {
|
||||
name = "hello-world";
|
||||
skills = [ ./skills/hello-world ];
|
||||
packages = [ self.packages.${system}.default ];
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
module github.com/acme/hello-world-clawdis
|
||||
module github.com/acme/hello-world-clawdbot
|
||||
|
||||
go 1.22
|
||||
|
||||
@ -6,7 +6,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
name := os.Getenv("CLAWDIS_USER")
|
||||
name := os.Getenv("CLAWDBOT_USER")
|
||||
if name == "" {
|
||||
name = "human"
|
||||
}
|
||||
|
||||
20
flake.nix
20
flake.nix
@ -21,20 +21,20 @@
|
||||
in
|
||||
{
|
||||
packages = {
|
||||
clawdis-gateway = 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;
|
||||
clawdbot-gateway = pkgs.clawdbot-gateway;
|
||||
clawdbot-app = pkgs.clawdbot-app;
|
||||
clawdbot = pkgs.clawdbot;
|
||||
clawdbot-tools-base = pkgs.clawdbot-tools-base;
|
||||
clawdbot-tools-extended = pkgs.clawdbot-tools-extended;
|
||||
default = pkgs.clawdbot;
|
||||
};
|
||||
|
||||
apps = {
|
||||
clawdis = flake-utils.lib.mkApp { drv = pkgs.clawdis-gateway; };
|
||||
clawdbot = flake-utils.lib.mkApp { drv = pkgs.clawdbot-gateway; };
|
||||
};
|
||||
|
||||
checks = pkgs.lib.optionalAttrs pkgs.stdenv.isDarwin {
|
||||
gateway = pkgs.clawdis-gateway;
|
||||
gateway = pkgs.clawdbot-gateway;
|
||||
};
|
||||
|
||||
devShells.default = pkgs.mkShell {
|
||||
@ -47,7 +47,7 @@
|
||||
}
|
||||
) // {
|
||||
overlays.default = overlay;
|
||||
homeManagerModules.clawdis = import ./nix/modules/home-manager/clawdis.nix;
|
||||
darwinModules.clawdis = import ./nix/modules/darwin/clawdis.nix;
|
||||
homeManagerModules.clawdbot = import ./nix/modules/home-manager/clawdbot.nix;
|
||||
darwinModules.clawdbot = import ./nix/modules/darwin/clawdbot.nix;
|
||||
};
|
||||
}
|
||||
|
||||
@ -2,6 +2,6 @@
|
||||
|
||||
{
|
||||
config = lib.mkIf (config ? home-manager) {
|
||||
home-manager.sharedModules = [ ../home-manager/clawdis.nix ];
|
||||
home-manager.sharedModules = [ ../home-manager/clawdbot.nix ];
|
||||
};
|
||||
}
|
||||
36
nix/modules/home-manager/clawdbot-reload.sh
Normal file
36
nix/modules/home-manager/clawdbot-reload.sh
Normal file
@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage: clawdbot-reload [test|prod|both]
|
||||
|
||||
Re-render Clawdbot config via Home Manager (no sudo) and restart gateway(s).
|
||||
|
||||
Defaults to: test
|
||||
EOF
|
||||
}
|
||||
|
||||
instance="${1:-test}"
|
||||
|
||||
case "$instance" in
|
||||
test) labels=("com.steipete.clawdbot.gateway.nix-test") ;;
|
||||
prod) labels=("com.steipete.clawdbot.gateway.nix") ;;
|
||||
both) labels=("com.steipete.clawdbot.gateway.nix" "com.steipete.clawdbot.gateway.nix-test") ;;
|
||||
-h|--help) usage; exit 0 ;;
|
||||
*) usage; exit 1 ;;
|
||||
esac
|
||||
|
||||
if command -v hm-apply >/dev/null 2>&1; then
|
||||
hm-apply
|
||||
elif [[ -n "${CLAWDBOT_RELOAD_HM_CMD:-}" ]]; then
|
||||
eval "$CLAWDBOT_RELOAD_HM_CMD"
|
||||
else
|
||||
echo "[clawdbot-reload] no Home Manager command available." >&2
|
||||
echo "[clawdbot-reload] install hm-apply or set CLAWDBOT_RELOAD_HM_CMD." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for label in "${labels[@]}"; do
|
||||
/bin/launchctl kickstart -k "gui/$UID/$label"
|
||||
done
|
||||
@ -1,7 +1,7 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.programs.clawdis;
|
||||
cfg = config.programs.clawdbot;
|
||||
homeDir = config.home.homeDirectory;
|
||||
appPackage = if cfg.appPackage != null then cfg.appPackage else cfg.package;
|
||||
|
||||
@ -33,53 +33,53 @@ let
|
||||
enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "Enable this Clawdis instance.";
|
||||
description = "Enable this Clawdbot instance.";
|
||||
};
|
||||
|
||||
package = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
default = cfg.package;
|
||||
description = "Clawdis batteries-included package.";
|
||||
description = "Clawdbot batteries-included package.";
|
||||
};
|
||||
|
||||
stateDir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = if name == "default"
|
||||
then "${homeDir}/.clawdis"
|
||||
else "${homeDir}/.clawdis-${name}";
|
||||
description = "State directory for this Clawdis instance (logs, sessions, config).";
|
||||
then "${homeDir}/.clawdbot"
|
||||
else "${homeDir}/.clawdbot-${name}";
|
||||
description = "State directory for this Clawdbot instance (logs, sessions, config).";
|
||||
};
|
||||
|
||||
workspaceDir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${config.stateDir}/workspace";
|
||||
description = "Workspace directory for this Clawdis instance.";
|
||||
description = "Workspace directory for this Clawdbot instance.";
|
||||
};
|
||||
|
||||
configPath = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${config.stateDir}/clawdis.json";
|
||||
description = "Path to generated Clawdis config JSON.";
|
||||
default = "${config.stateDir}/clawdbot.json";
|
||||
description = "Path to generated Clawdbot config JSON.";
|
||||
};
|
||||
|
||||
logPath = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = if name == "default"
|
||||
then "/tmp/clawdis/clawdis-gateway.log"
|
||||
else "/tmp/clawdis/clawdis-gateway-${name}.log";
|
||||
description = "Log path for this Clawdis gateway instance.";
|
||||
then "/tmp/clawdbot/clawdbot-gateway.log"
|
||||
else "/tmp/clawdbot/clawdbot-gateway-${name}.log";
|
||||
description = "Log path for this Clawdbot gateway instance.";
|
||||
};
|
||||
|
||||
gatewayPort = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 18789;
|
||||
description = "Gateway port used by the Clawdis desktop app.";
|
||||
description = "Gateway port used by the Clawdbot desktop app.";
|
||||
};
|
||||
|
||||
gatewayPath = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = "Local path to Clawdis gateway source (dev only).";
|
||||
description = "Local path to Clawdbot gateway source (dev only).";
|
||||
};
|
||||
|
||||
gatewayPnpmDepsHash = lib.mkOption {
|
||||
@ -165,27 +165,27 @@ let
|
||||
launchd.enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "Run Clawdis gateway via launchd (macOS).";
|
||||
description = "Run Clawdbot gateway via launchd (macOS).";
|
||||
};
|
||||
|
||||
launchd.label = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = if name == "default"
|
||||
then "com.steipete.clawdis.gateway"
|
||||
else "com.steipete.clawdis.gateway.${name}";
|
||||
then "com.steipete.clawdbot.gateway"
|
||||
else "com.steipete.clawdbot.gateway.${name}";
|
||||
description = "launchd label for this instance.";
|
||||
};
|
||||
|
||||
app.install.enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Install Clawdis.app for this instance.";
|
||||
description = "Install Clawdbot.app for this instance.";
|
||||
};
|
||||
|
||||
app.install.path = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${homeDir}/Applications/Clawdis.app";
|
||||
description = "Destination path for this instance's Clawdis.app bundle.";
|
||||
default = "${homeDir}/Applications/Clawdbot.app";
|
||||
description = "Destination path for this instance's Clawdbot.app bundle.";
|
||||
};
|
||||
|
||||
appDefaults = {
|
||||
@ -205,7 +205,7 @@ let
|
||||
configOverrides = lib.mkOption {
|
||||
type = lib.types.attrs;
|
||||
default = {};
|
||||
description = "Additional Clawdis config to merge into the generated JSON.";
|
||||
description = "Additional Clawdbot config to merge into the generated JSON.";
|
||||
};
|
||||
};
|
||||
};
|
||||
@ -215,8 +215,8 @@ let
|
||||
package = cfg.package;
|
||||
stateDir = cfg.stateDir;
|
||||
workspaceDir = cfg.workspaceDir;
|
||||
configPath = "${cfg.stateDir}/clawdis.json";
|
||||
logPath = "/tmp/clawdis/clawdis-gateway.log";
|
||||
configPath = "${cfg.stateDir}/clawdbot.json";
|
||||
logPath = "/tmp/clawdbot/clawdbot-gateway.log";
|
||||
gatewayPort = 18789;
|
||||
providers = cfg.providers;
|
||||
routing = cfg.routing;
|
||||
@ -230,7 +230,7 @@ let
|
||||
app = {
|
||||
install = {
|
||||
enable = false;
|
||||
path = "${homeDir}/Applications/Clawdis.app";
|
||||
path = "${homeDir}/Applications/Clawdbot.app";
|
||||
};
|
||||
};
|
||||
};
|
||||
@ -240,7 +240,7 @@ let
|
||||
else lib.optionalAttrs cfg.enable { default = defaultInstance; };
|
||||
|
||||
enabledInstances = lib.filterAttrs (_: inst: inst.enable) instances;
|
||||
managedSkillsDir = "${homeDir}/.clawdis/skills";
|
||||
managedSkillsDir = "${homeDir}/.clawdbot/skills";
|
||||
|
||||
documentsEnabled = cfg.documents != null;
|
||||
|
||||
@ -261,19 +261,19 @@ let
|
||||
documentsAssertions = lib.optionals documentsEnabled [
|
||||
{
|
||||
assertion = builtins.pathExists cfg.documents;
|
||||
message = "programs.clawdis.documents must point to an existing directory.";
|
||||
message = "programs.clawdbot.documents must point to an existing directory.";
|
||||
}
|
||||
{
|
||||
assertion = builtins.pathExists (cfg.documents + "/AGENTS.md");
|
||||
message = "Missing AGENTS.md in programs.clawdis.documents.";
|
||||
message = "Missing AGENTS.md in programs.clawdbot.documents.";
|
||||
}
|
||||
{
|
||||
assertion = builtins.pathExists (cfg.documents + "/SOUL.md");
|
||||
message = "Missing SOUL.md in programs.clawdis.documents.";
|
||||
message = "Missing SOUL.md in programs.clawdbot.documents.";
|
||||
}
|
||||
{
|
||||
assertion = builtins.pathExists (cfg.documents + "/TOOLS.md");
|
||||
message = "Missing TOOLS.md in programs.clawdis.documents.";
|
||||
message = "Missing TOOLS.md in programs.clawdbot.documents.";
|
||||
}
|
||||
];
|
||||
|
||||
@ -282,7 +282,7 @@ let
|
||||
let
|
||||
guardLine = file: ''
|
||||
if [ -e "${file}" ] && [ ! -L "${file}" ]; then
|
||||
echo "Clawdis documents are managed by Nix. Please adopt ${file} into your documents directory and re-run." >&2
|
||||
echo "Clawdbot documents are managed by Nix. Please adopt ${file} into your documents directory and re-run." >&2
|
||||
exit 1
|
||||
fi
|
||||
'';
|
||||
@ -325,13 +325,13 @@ let
|
||||
];
|
||||
reportText = lib.concatStringsSep "\n" reportLines;
|
||||
in
|
||||
pkgs.writeText "clawdis-tools-report.md" reportText
|
||||
pkgs.writeText "clawdbot-tools-report.md" reportText
|
||||
else
|
||||
null;
|
||||
|
||||
toolsWithReport =
|
||||
if documentsEnabled then
|
||||
pkgs.runCommand "clawdis-tools-with-report.md" {} ''
|
||||
pkgs.runCommand "clawdbot-tools-with-report.md" {} ''
|
||||
cat ${cfg.documents + "/TOOLS.md"} > $out
|
||||
echo "" >> $out
|
||||
cat ${toolsReport} >> $out
|
||||
@ -360,15 +360,15 @@ let
|
||||
|
||||
resolvePlugin = plugin: let
|
||||
flake = builtins.getFlake plugin.source;
|
||||
clawdisPlugin =
|
||||
if flake ? clawdisPlugin then flake.clawdisPlugin
|
||||
else throw "clawdisPlugin missing in ${plugin.source}";
|
||||
needs = clawdisPlugin.needs or {};
|
||||
clawdbotPlugin =
|
||||
if flake ? clawdbotPlugin then flake.clawdbotPlugin
|
||||
else throw "clawdbotPlugin missing in ${plugin.source}";
|
||||
needs = clawdbotPlugin.needs or {};
|
||||
in {
|
||||
source = plugin.source;
|
||||
name = clawdisPlugin.name or (throw "clawdisPlugin.name missing in ${plugin.source}");
|
||||
skills = clawdisPlugin.skills or [];
|
||||
packages = clawdisPlugin.packages or [];
|
||||
name = clawdbotPlugin.name or (throw "clawdbotPlugin.name missing in ${plugin.source}");
|
||||
skills = clawdbotPlugin.skills or [];
|
||||
packages = clawdbotPlugin.packages or [];
|
||||
needs = {
|
||||
stateDirs = needs.stateDirs or [];
|
||||
requiredEnv = needs.requiredEnv or [];
|
||||
@ -390,7 +390,7 @@ let
|
||||
if duplicates == []
|
||||
then ordered
|
||||
else lib.warn
|
||||
"programs.clawdis.instances.${instName}: duplicate plugin names detected (${lib.concatStringsSep ", " duplicates}); last entry wins."
|
||||
"programs.clawdbot.instances.${instName}: duplicate plugin names detected (${lib.concatStringsSep ", " duplicates}); last entry wins."
|
||||
ordered
|
||||
) enabledInstances;
|
||||
|
||||
@ -437,11 +437,11 @@ let
|
||||
let missing = missingFor p;
|
||||
in {
|
||||
assertion = missing == [];
|
||||
message = "programs.clawdis.instances.${instName}: plugin ${p.name} missing required env: ${lib.concatStringsSep ", " missing}";
|
||||
message = "programs.clawdbot.instances.${instName}: plugin ${p.name} missing required env: ${lib.concatStringsSep ", " missing}";
|
||||
};
|
||||
mkConfigAssertion = p: {
|
||||
assertion = !(configMissingStateDir p);
|
||||
message = "programs.clawdis.instances.${instName}: plugin ${p.name} provides settings but declares no stateDirs (needed for config.json).";
|
||||
message = "programs.clawdbot.instances.${instName}: plugin ${p.name} provides settings but declares no stateDirs (needed for config.json).";
|
||||
};
|
||||
in
|
||||
(map mkAssertion plugins) ++ (map mkConfigAssertion plugins)
|
||||
@ -451,7 +451,7 @@ let
|
||||
let
|
||||
skillEntriesFor = p:
|
||||
map (skillPath: {
|
||||
name = ".clawdis/skills/${p.name}/${builtins.baseNameOf skillPath}";
|
||||
name = ".clawdbot/skills/${p.name}/${builtins.baseNameOf skillPath}";
|
||||
value = { source = skillPath; recursive = true; };
|
||||
}) p.skills;
|
||||
allEntries =
|
||||
@ -513,7 +513,7 @@ let
|
||||
lib.flatten (lib.concatLists (lib.mapAttrsToList (_: plugins:
|
||||
map (p:
|
||||
map (skillPath:
|
||||
".clawdis/skills/${p.name}/${builtins.baseNameOf skillPath}"
|
||||
".clawdbot/skills/${p.name}/${builtins.baseNameOf skillPath}"
|
||||
) p.skills
|
||||
) plugins
|
||||
) resolvedPluginsByInstance));
|
||||
@ -531,10 +531,10 @@ let
|
||||
mkInstanceConfig = name: inst: let
|
||||
gatewayPackage =
|
||||
if inst.gatewayPath != null then
|
||||
pkgs.callPackage ../../packages/clawdis-gateway.nix {
|
||||
pkgs.callPackage ../../packages/clawdbot-gateway.nix {
|
||||
gatewaySrc = builtins.path {
|
||||
path = inst.gatewayPath;
|
||||
name = "clawdis-gateway-src";
|
||||
name = "clawdbot-gateway-src";
|
||||
};
|
||||
pnpmDepsHash = inst.gatewayPnpmDepsHash;
|
||||
}
|
||||
@ -547,7 +547,7 @@ let
|
||||
(lib.recursiveUpdate baseConfig (lib.recursiveUpdate (mkTelegramConfig inst) (mkRoutingConfig inst)))
|
||||
inst.configOverrides;
|
||||
configJson = builtins.toJSON mergedConfig;
|
||||
gatewayWrapper = pkgs.writeShellScriptBin "clawdis-gateway-${name}" ''
|
||||
gatewayWrapper = pkgs.writeShellScriptBin "clawdbot-gateway-${name}" ''
|
||||
set -euo pipefail
|
||||
|
||||
if [ "${toString (pluginPackages != [])}" = "true" ]; then
|
||||
@ -569,7 +569,7 @@ let
|
||||
export ANTHROPIC_API_KEY
|
||||
fi
|
||||
|
||||
exec "${gatewayPackage}/bin/clawdis" "$@"
|
||||
exec "${gatewayPackage}/bin/clawdbot" "$@"
|
||||
'';
|
||||
in {
|
||||
homeFile = {
|
||||
@ -585,7 +585,7 @@ let
|
||||
config = {
|
||||
Label = inst.launchd.label;
|
||||
ProgramArguments = [
|
||||
"${gatewayWrapper}/bin/clawdis-gateway-${name}"
|
||||
"${gatewayWrapper}/bin/clawdbot-gateway-${name}"
|
||||
"gateway"
|
||||
"--port"
|
||||
"${toString inst.gatewayPort}"
|
||||
@ -597,10 +597,10 @@ let
|
||||
StandardErrorPath = inst.logPath;
|
||||
EnvironmentVariables = {
|
||||
HOME = homeDir;
|
||||
CLAWDIS_CONFIG_PATH = inst.configPath;
|
||||
CLAWDIS_STATE_DIR = inst.stateDir;
|
||||
CLAWDIS_IMAGE_BACKEND = "sips";
|
||||
CLAWDIS_NIX_MODE = "1";
|
||||
CLAWDBOT_CONFIG_PATH = inst.configPath;
|
||||
CLAWDBOT_STATE_DIR = inst.stateDir;
|
||||
CLAWDBOT_IMAGE_BACKEND = "sips";
|
||||
CLAWDBOT_NIX_MODE = "1";
|
||||
};
|
||||
};
|
||||
};
|
||||
@ -616,7 +616,7 @@ let
|
||||
else {
|
||||
name = lib.removePrefix "${homeDir}/" inst.app.install.path;
|
||||
value = {
|
||||
source = "${appPackage}/Applications/Clawdis.app";
|
||||
source = "${appPackage}/Applications/Clawdbot.app";
|
||||
recursive = true;
|
||||
force = true;
|
||||
};
|
||||
@ -636,46 +636,46 @@ let
|
||||
assertions = lib.flatten (lib.mapAttrsToList (name: inst: [
|
||||
{
|
||||
assertion = !inst.providers.telegram.enable || inst.providers.telegram.botTokenFile != "";
|
||||
message = "programs.clawdis.instances.${name}.providers.telegram.botTokenFile must be set when Telegram is enabled.";
|
||||
message = "programs.clawdbot.instances.${name}.providers.telegram.botTokenFile must be set when Telegram is enabled.";
|
||||
}
|
||||
{
|
||||
assertion = !inst.providers.telegram.enable || (lib.length inst.providers.telegram.allowFrom > 0);
|
||||
message = "programs.clawdis.instances.${name}.providers.telegram.allowFrom must be non-empty when Telegram is enabled.";
|
||||
message = "programs.clawdbot.instances.${name}.providers.telegram.allowFrom must be non-empty when Telegram is enabled.";
|
||||
}
|
||||
]) enabledInstances);
|
||||
|
||||
in {
|
||||
options.programs.clawdis = {
|
||||
enable = lib.mkEnableOption "Clawdis (batteries-included)";
|
||||
options.programs.clawdbot = {
|
||||
enable = lib.mkEnableOption "Clawdbot (batteries-included)";
|
||||
|
||||
package = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
default = pkgs.clawdis;
|
||||
description = "Clawdis batteries-included package.";
|
||||
default = pkgs.clawdbot;
|
||||
description = "Clawdbot batteries-included package.";
|
||||
};
|
||||
|
||||
appPackage = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.package;
|
||||
default = null;
|
||||
description = "Optional Clawdis app package (defaults to package if unset).";
|
||||
description = "Optional Clawdbot app package (defaults to package if unset).";
|
||||
};
|
||||
|
||||
installApp = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "Install Clawdis.app at the default location.";
|
||||
description = "Install Clawdbot.app at the default location.";
|
||||
};
|
||||
|
||||
stateDir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${homeDir}/.clawdis";
|
||||
description = "State directory for Clawdis (logs, sessions, config).";
|
||||
default = "${homeDir}/.clawdbot";
|
||||
description = "State directory for Clawdbot (logs, sessions, config).";
|
||||
};
|
||||
|
||||
workspaceDir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${homeDir}/.clawdis/workspace";
|
||||
description = "Workspace directory for Clawdis agent skills.";
|
||||
default = "${homeDir}/.clawdbot/workspace";
|
||||
description = "Workspace directory for Clawdbot agent skills.";
|
||||
};
|
||||
|
||||
documents = lib.mkOption {
|
||||
@ -754,20 +754,20 @@ in {
|
||||
launchd.enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "Run Clawdis gateway via launchd (macOS).";
|
||||
description = "Run Clawdbot gateway via launchd (macOS).";
|
||||
};
|
||||
|
||||
instances = lib.mkOption {
|
||||
type = lib.types.attrsOf (lib.types.submodule instanceModule);
|
||||
default = {};
|
||||
description = "Named Clawdis instances (prod/test).";
|
||||
description = "Named Clawdbot instances (prod/test).";
|
||||
};
|
||||
|
||||
reloadScript = {
|
||||
enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Install clawdis-reload helper for no-sudo config refresh + gateway restart.";
|
||||
description = "Install clawdbot-reload helper for no-sudo config refresh + gateway restart.";
|
||||
};
|
||||
};
|
||||
};
|
||||
@ -776,7 +776,7 @@ in {
|
||||
assertions = assertions ++ [
|
||||
{
|
||||
assertion = lib.length (lib.attrNames appDefaultsEnabled) <= 1;
|
||||
message = "Only one Clawdis instance may enable appDefaults.";
|
||||
message = "Only one Clawdbot instance may enable appDefaults.";
|
||||
}
|
||||
] ++ documentsAssertions ++ pluginAssertions ++ pluginSkillAssertions;
|
||||
|
||||
@ -785,8 +785,8 @@ in {
|
||||
home.file =
|
||||
(lib.listToAttrs (map (item: item.homeFile) instanceConfigs))
|
||||
// (lib.optionalAttrs (pkgs.stdenv.hostPlatform.isDarwin && appPackage != null && cfg.installApp) {
|
||||
"Applications/Clawdis.app" = {
|
||||
source = "${appPackage}/Applications/Clawdis.app";
|
||||
"Applications/Clawdbot.app" = {
|
||||
source = "${appPackage}/Applications/Clawdbot.app";
|
||||
recursive = true;
|
||||
force = true;
|
||||
};
|
||||
@ -796,33 +796,33 @@ in {
|
||||
// pluginSkillsFiles
|
||||
// pluginConfigFiles
|
||||
// (lib.optionalAttrs cfg.reloadScript.enable {
|
||||
".local/bin/clawdis-reload" = {
|
||||
".local/bin/clawdbot-reload" = {
|
||||
executable = true;
|
||||
source = ./clawdis-reload.sh;
|
||||
source = ./clawdbot-reload.sh;
|
||||
};
|
||||
});
|
||||
|
||||
home.activation.clawdisDocumentGuard = lib.mkIf documentsEnabled (
|
||||
home.activation.clawdbotDocumentGuard = lib.mkIf documentsEnabled (
|
||||
lib.hm.dag.entryBefore [ "writeBoundary" ] ''
|
||||
set -euo pipefail
|
||||
${documentsGuard}
|
||||
''
|
||||
);
|
||||
|
||||
home.activation.clawdisDirs = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
|
||||
home.activation.clawdbotDirs = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
|
||||
/bin/mkdir -p ${lib.concatStringsSep " " (lib.concatMap (item: item.dirs) instanceConfigs)}
|
||||
${lib.optionalString (pluginStateDirsAll != []) "/bin/mkdir -p ${lib.concatStringsSep " " pluginStateDirsAll}"}
|
||||
'';
|
||||
|
||||
home.activation.clawdisPluginGuard = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
|
||||
home.activation.clawdbotPluginGuard = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
|
||||
set -euo pipefail
|
||||
${pluginGuards}
|
||||
'';
|
||||
|
||||
home.activation.clawdisAppDefaults = lib.mkIf (pkgs.stdenv.hostPlatform.isDarwin && appDefaults != {}) (
|
||||
home.activation.clawdbotAppDefaults = lib.mkIf (pkgs.stdenv.hostPlatform.isDarwin && appDefaults != {}) (
|
||||
lib.hm.dag.entryAfter [ "writeBoundary" ] ''
|
||||
/usr/bin/defaults write com.steipete.Clawdis clawdis.gateway.attachExistingOnly -bool ${lib.boolToString (appDefaults.attachExistingOnly or true)}
|
||||
/usr/bin/defaults write com.steipete.Clawdis gatewayPort -int ${toString (appDefaults.gatewayPort or 18789)}
|
||||
/usr/bin/defaults write com.steipete.Clawdbot clawdbot.gateway.attachExistingOnly -bool ${lib.boolToString (appDefaults.attachExistingOnly or true)}
|
||||
/usr/bin/defaults write com.steipete.Clawdbot gatewayPort -int ${toString (appDefaults.gatewayPort or 18789)}
|
||||
''
|
||||
);
|
||||
|
||||
@ -1,36 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage: clawdis-reload [test|prod|both]
|
||||
|
||||
Re-render Clawdis config via Home Manager (no sudo) and restart gateway(s).
|
||||
|
||||
Defaults to: test
|
||||
EOF
|
||||
}
|
||||
|
||||
instance="${1:-test}"
|
||||
|
||||
case "$instance" in
|
||||
test) labels=("com.steipete.clawdis.gateway.nix-test") ;;
|
||||
prod) labels=("com.steipete.clawdis.gateway.nix") ;;
|
||||
both) labels=("com.steipete.clawdis.gateway.nix" "com.steipete.clawdis.gateway.nix-test") ;;
|
||||
-h|--help) usage; exit 0 ;;
|
||||
*) usage; exit 1 ;;
|
||||
esac
|
||||
|
||||
if command -v hm-apply >/dev/null 2>&1; then
|
||||
hm-apply
|
||||
elif [[ -n "${CLAWDIS_RELOAD_HM_CMD:-}" ]]; then
|
||||
eval "$CLAWDIS_RELOAD_HM_CMD"
|
||||
else
|
||||
echo "[clawdis-reload] no Home Manager command available." >&2
|
||||
echo "[clawdis-reload] install hm-apply or set CLAWDIS_RELOAD_HM_CMD." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for label in "${labels[@]}"; do
|
||||
/bin/launchctl kickstart -k "gui/$UID/$label"
|
||||
done
|
||||
@ -1,20 +1,20 @@
|
||||
self: super:
|
||||
let
|
||||
sourceInfo = import ./sources/clawdis-source.nix;
|
||||
clawdisGateway = super.callPackage ./packages/clawdis-gateway.nix {
|
||||
sourceInfo = import ./sources/clawdbot-source.nix;
|
||||
clawdbotGateway = super.callPackage ./packages/clawdbot-gateway.nix {
|
||||
inherit sourceInfo;
|
||||
};
|
||||
clawdisApp = super.callPackage ./packages/clawdis-app.nix { };
|
||||
clawdbotApp = super.callPackage ./packages/clawdbot-app.nix { };
|
||||
toolSets = import ./tools/extended.nix { pkgs = super; };
|
||||
clawdisBundle = super.callPackage ./packages/clawdis-batteries.nix {
|
||||
clawdis-gateway = clawdisGateway;
|
||||
clawdis-app = clawdisApp;
|
||||
clawdbotBundle = super.callPackage ./packages/clawdbot-batteries.nix {
|
||||
clawdbot-gateway = clawdbotGateway;
|
||||
clawdbot-app = clawdbotApp;
|
||||
extendedTools = toolSets.base;
|
||||
};
|
||||
in {
|
||||
clawdis-gateway = clawdisGateway;
|
||||
clawdis-app = clawdisApp;
|
||||
clawdis = clawdisBundle;
|
||||
clawdis-tools-base = toolSets.base;
|
||||
clawdis-tools-extended = toolSets.extended;
|
||||
clawdbot-gateway = clawdbotGateway;
|
||||
clawdbot-app = clawdbotApp;
|
||||
clawdbot = clawdbotBundle;
|
||||
clawdbot-tools-base = toolSets.base;
|
||||
clawdbot-tools-extended = toolSets.extended;
|
||||
}
|
||||
|
||||
@ -4,11 +4,11 @@
|
||||
}:
|
||||
|
||||
stdenvNoCC.mkDerivation {
|
||||
pname = "clawdis-app";
|
||||
pname = "clawdbot-app";
|
||||
version = "2.0.0-beta4";
|
||||
|
||||
src = fetchzip {
|
||||
url = "https://github.com/clawdbot/clawdbot/releases/download/v2.0.0-beta4/Clawdis-2.0.0-beta4.zip";
|
||||
url = "https://github.com/clawdbot/clawdbot/releases/download/v2.0.0-beta4/Clawdbot-2.0.0-beta4.zip";
|
||||
hash = "sha256-Oa7cejVFfZtJBSmjDaRjqocVyXo+WeS/xucGpJFDzIg=";
|
||||
stripRoot = false;
|
||||
};
|
||||
@ -18,12 +18,12 @@ stdenvNoCC.mkDerivation {
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
mkdir -p $out/Applications
|
||||
app_path="$(find "$src" -maxdepth 2 -name 'Clawdis.app' -print -quit)"
|
||||
app_path="$(find "$src" -maxdepth 2 -name 'Clawdbot.app' -print -quit)"
|
||||
if [ -z "$app_path" ]; then
|
||||
echo "Clawdis.app not found in $src" >&2
|
||||
echo "Clawdbot.app not found in $src" >&2
|
||||
exit 1
|
||||
fi
|
||||
cp -R "$app_path" "$out/Applications/Clawdis.app"
|
||||
cp -R "$app_path" "$out/Applications/Clawdbot.app"
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
{ lib
|
||||
, buildEnv
|
||||
, clawdis-gateway
|
||||
, clawdis-app
|
||||
, clawdbot-gateway
|
||||
, clawdbot-app
|
||||
, extendedTools
|
||||
}:
|
||||
|
||||
buildEnv {
|
||||
name = "clawdis-2.0.0-beta4";
|
||||
paths = [ clawdis-gateway clawdis-app ] ++ extendedTools;
|
||||
name = "clawdbot-2.0.0-beta4";
|
||||
paths = [ clawdbot-gateway clawdbot-app ] ++ extendedTools;
|
||||
pathsToLink = [ "/bin" "/Applications" ];
|
||||
|
||||
meta = with lib; {
|
||||
@ -15,7 +15,7 @@
|
||||
assert gatewaySrc == null || pnpmDepsHash != null;
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "clawdis-gateway";
|
||||
pname = "clawdbot-gateway";
|
||||
version = "2.0.0-beta4";
|
||||
|
||||
src = if gatewaySrc != null then gatewaySrc else fetchFromGitHub sourceInfo;
|
||||
@ -53,13 +53,13 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
mkdir -p $out/lib/clawdis $out/bin
|
||||
mkdir -p $out/lib/clawdbot $out/bin
|
||||
|
||||
cp -r dist node_modules package.json ui $out/lib/clawdis/
|
||||
cp -r dist node_modules package.json ui $out/lib/clawdbot/
|
||||
|
||||
makeWrapper ${nodejs_22}/bin/node $out/bin/clawdis \
|
||||
--add-flags "$out/lib/clawdis/dist/index.js" \
|
||||
--set-default CLAWDIS_NIX_MODE "1"
|
||||
makeWrapper ${nodejs_22}/bin/node $out/bin/clawdbot \
|
||||
--add-flags "$out/lib/clawdbot/dist/index.js" \
|
||||
--set-default CLAWDBOT_NIX_MODE "1"
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
@ -69,6 +69,6 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
homepage = "https://github.com/clawdbot/clawdbot";
|
||||
license = licenses.mit;
|
||||
platforms = platforms.darwin;
|
||||
mainProgram = "clawdis";
|
||||
mainProgram = "clawdbot";
|
||||
};
|
||||
})
|
||||
@ -18,7 +18,7 @@
|
||||
homeConfigurations."<user>" = home-manager.lib.homeManagerConfiguration {
|
||||
inherit pkgs;
|
||||
modules = [
|
||||
nix-clawdbot.homeManagerModules.clawdis
|
||||
nix-clawdbot.homeManagerModules.clawdbot
|
||||
{
|
||||
# Required for Home Manager standalone
|
||||
home.username = "<user>";
|
||||
@ -26,7 +26,7 @@
|
||||
home.stateVersion = "24.11";
|
||||
programs.home-manager.enable = true;
|
||||
|
||||
programs.clawdis = {
|
||||
programs.clawdbot = {
|
||||
# REPLACE: path to your managed documents directory
|
||||
documents = ./documents;
|
||||
instances.default = {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user