Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion bundles/browser/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "browser",
"name": "Browser Automation",
"version": "1.3.5",
"version": "1.3.6",
"description": "Stealth browser automation — navigate, fill forms, take screenshots, extract content via Chrome DevTools Protocol with VNC viewing",
"type": "bundle",
"author": "Crow",
Expand All @@ -12,6 +12,10 @@
"composefile": "docker-compose.yml"
},
"privileged": true,
"install_consent_messages": {
"en": "The browser container uses host networking, so the browser it runs can reach every service on this machine that listens only on 127.0.0.1, as well as the internet. Its control port (Chrome DevTools) listens on 127.0.0.1 only. The VNC viewer (ports 6080 and 5900) listens on every network interface of this machine and is protected by the generated VNC password. It saves downloads under your Crow folder.",
"es": "El contenedor del navegador usa la red del host, así que el navegador que ejecuta puede llegar a todos los servicios de esta máquina que escuchan solo en 127.0.0.1, además de a internet. Su puerto de control (Chrome DevTools) escucha solo en 127.0.0.1. El visor VNC (puertos 6080 y 5900) escucha en todas las interfaces de red de esta máquina y está protegido por la contraseña VNC generada. Guarda las descargas dentro de tu carpeta de Crow."
},
"server": {
"command": "node",
"args": ["server/index.js"],
Expand Down
3 changes: 2 additions & 1 deletion bundles/companion/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ services:
- companion-models:/app/models
- companion-cache:/app/cache
- companion-history:/app/chat_history
- ${EIKANYA_MODELS_DIR:-}:/app/live2d-models/eikanya:ro
# Unset → an empty folder inside the bundle (an empty host path is a compose error).
- ${EIKANYA_MODELS_DIR:-./eikanya-models}:/app/live2d-models/eikanya:ro
- ${CROW_DB_PATH:-~/.crow/data/crow.db}:/crow-data/crow.db:ro
- ${HOME}/.crow/bundles:/crow-bundles:ro
environment:
Expand Down
7 changes: 6 additions & 1 deletion bundles/companion/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
{
"id": "companion",
"name": "AI Companion",
"version": "1.0.2",
"version": "1.0.3",
"privileged": true,
"install_consent_messages": {
"en": "The AI Companion uses host networking so it can reach Crow and your local models on this machine. That also lets it reach every service on this machine that listens only on 127.0.0.1. Its own web page listens on 127.0.0.1 by default (COMPANION_BIND_HOST), and Crow serves it to your tailnet over HTTPS. It mounts Crow's database and your installed extensions folder read-only (that folder holds the other extensions' settings and passwords), and it is given Crow's local MCP token.",
"es": "El AI Companion usa la red del host para poder llegar a Crow y a tus modelos locales en esta máquina. Eso también le permite llegar a todos los servicios de esta máquina que escuchan solo en 127.0.0.1. Su propia página web escucha por defecto en 127.0.0.1 (COMPANION_BIND_HOST), y Crow la sirve a tu tailnet por HTTPS. Monta en solo lectura la base de datos de Crow y la carpeta de tus extensiones instaladas (esa carpeta guarda los ajustes y las contraseñas de las demás extensiones), y recibe el token MCP local de Crow."
},
"description": "Voice-interactive AI companion with animated Live2D avatar. Powered by Open-LLM-VTuber with Crow's BYOAI profiles.",
"type": "bundle",
"author": "Crow",
Expand Down
7 changes: 6 additions & 1 deletion bundles/coturn/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
{
"id": "coturn",
"name": "TURN Server (coturn)",
"version": "1.0.1",
"version": "1.0.2",
"privileged": true,
"install_consent_messages": {
"en": "The TURN relay uses host networking because it relays calls over a range of UDP ports (49152-49252) as well as ports 3478 and 5349. It listens on every network interface of this machine so devices outside your network can reach it. Only callers holding a short-lived credential from Crow can relay through it, but a caller who holds one can relay traffic to addresses on your local network and tailnet too.",
"es": "El relé TURN usa la red del host porque retransmite llamadas por un rango de puertos UDP (49152-49252) además de los puertos 3478 y 5349. Escucha en todas las interfaces de red de esta máquina para que los dispositivos fuera de tu red puedan alcanzarlo. Solo quien tenga una credencial temporal de Crow puede retransmitir a través de él, pero quien tenga una también puede retransmitir tráfico hacia direcciones de tu red local y de tu tailnet."
},
"description": "Self-hosted TURN relay for WebRTC voice chat. Enables NAT traversal for remote companion access when STUN alone is not sufficient.",
"type": "bundle",
"author": "Crow",
Expand Down
1 change: 0 additions & 1 deletion bundles/forgejo/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ services:
- "127.0.0.1:2224:22"
volumes:
- ${FORGEJO_DATA_DIR:-~/.crow/forgejo/data}:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
environment:
- USER_UID=1000
Expand Down
2 changes: 1 addition & 1 deletion bundles/forgejo/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "forgejo",
"name": "Forgejo",
"version": "1.0.0",
"version": "1.0.1",
"description": "Community-driven soft-fork of Gitea — self-hosted git with an independent governance model and ActivityPub federation roadmap",
"type": "bundle",
"author": "Crow",
Expand Down
7 changes: 4 additions & 3 deletions bundles/frigate/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ services:
- "127.0.0.1:8971:8971"
# RTSP restreamer (cameras pull from this for multi-consumer restreaming)
- "127.0.0.1:8554:8554"
# WebRTC (low-latency live view). Both TCP and UDP needed; bind to all interfaces for LAN access
- "8555:8555/tcp"
- "8555:8555/udp"
# WebRTC (low-latency live view). Both TCP and UDP. Loopback only, like every
# other Crow port: other devices watch through the authenticated UI above.
- "127.0.0.1:8555:8555/tcp"
- "127.0.0.1:8555:8555/udp"
# Port 5000 (internal unauthenticated API) intentionally NOT published — would bypass auth.
volumes:
- ${FRIGATE_CONFIG_PATH:-frigate-config}:/config
Expand Down
2 changes: 1 addition & 1 deletion bundles/frigate/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "frigate",
"name": "Frigate NVR",
"version": "1.0.0",
"version": "1.0.1",
"description": "Self-hosted NVR with AI object detection — cameras, events, clips. RTSP/ONVIF cameras, local CPU detection, optional Coral TPU.",
"type": "bundle",
"author": "Crow",
Expand Down
1 change: 0 additions & 1 deletion bundles/gitea/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ services:
- "127.0.0.1:2223:22"
volumes:
- ${GITEA_DATA_DIR:-~/.crow/gitea/data}:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
environment:
- USER_UID=1000
Expand Down
2 changes: 1 addition & 1 deletion bundles/gitea/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "gitea",
"name": "Gitea",
"version": "1.0.0",
"version": "1.0.1",
"description": "Self-hosted git service — repos, issues, pull requests, and built-in SSH server for git over SSH",
"type": "bundle",
"author": "Crow",
Expand Down
6 changes: 4 additions & 2 deletions bundles/netdata/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
# platform blocks /etc and we accept reduced hostname/OS metadata).
#
# NOT in the MVP:
# - SYS_PTRACE capability + pid:host (per-process stats). Would require
# privileged:true, deliberately excluded for MVP scope.
# - the process-tracing capability + a shared host PID namespace (per-process
# stats). Would require privileged:true, deliberately excluded for MVP scope.
# (Not named literally here: the install security check reads this file as
# text, comments included.)

services:
netdata:
Expand Down
2 changes: 1 addition & 1 deletion bundles/netdata/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "netdata",
"name": "Netdata",
"version": "1.0.0",
"version": "1.0.1",
"description": "Real-time infrastructure and container monitoring — CPU, memory, disk, network, and Docker container metrics with one-second granularity.",
"type": "bundle",
"author": "Crow",
Expand Down
2 changes: 1 addition & 1 deletion bundles/nominatim/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ services:
- nominatim-data:/var/lib/postgresql/14/main
- nominatim-flat:/nominatim/flatnode
ports:
- "${NOMINATIM_PORT:-8088}:8080"
- "127.0.0.1:${NOMINATIM_PORT:-8088}:8080"
mem_limit: 4g
shm_size: 1g
healthcheck:
Expand Down
2 changes: 1 addition & 1 deletion bundles/nominatim/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "nominatim",
"name": "Nominatim GIS",
"version": "1.0.2",
"version": "1.0.3",
"description": "Self-hosted geocoding and GIS — forward/reverse geocode, batch geocode data columns, generate GeoJSON, map visualizations",
"type": "bundle",
"author": "Crow",
Expand Down
5 changes: 3 additions & 2 deletions bundles/phone/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "phone",
"name": "Phone",
"version": "0.2.4",
"version": "0.2.5",
"description": "Your assistant calls businesses for you: book appointments and ask questions, with your approval on every call.",
"type": "bundle",
"author": "Crow",
Expand All @@ -13,7 +13,8 @@
"panelRoutes": "panel/routes.js",
"privileged": true,
"install_consent_messages": {
"en": "The phone runner uses host networking, bound to 127.0.0.1 only, so it can reach Crow and your local models. It opens no network ports to other machines."
"en": "The phone runner uses host networking, bound to 127.0.0.1 only, so it can reach Crow and your local models. It opens no network ports to other machines.",
"es": "El ejecutor del teléfono usa la red del host, vinculado solo a 127.0.0.1, para poder llegar a Crow y a tus modelos locales. No abre puertos de red hacia otras máquinas."
},
"ports": [3065],
"requires": { "env": ["PHONE_RUNNER_SECRET"], "min_ram_mb": 256, "min_disk_mb": 200 },
Expand Down
2 changes: 1 addition & 1 deletion bundles/phone/server/mcp.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export function createPhoneMcpServer({ db, ownerNumber, McpServer, z, notify, no
catch (e) { console.warn(`[phone] card push failed for ${id}: ${e.message}`); }
};
if (!McpServer || !z) throw new Error("createPhoneMcpServer needs the gateway's McpServer and z (dependency injection)");
const server = new McpServer({ name: "crow-phone", version: "0.2.4" });
const server = new McpServer({ name: "crow-phone", version: "0.2.5" });

server.tool("phone_plan_call",
"Propose a phone call to a BUSINESS for the owner. This never dials: the owner must approve the plan (in this chat's call card, or in Crow's Nest → Phone). Give the goal, the limits the agent may agree to, and only the personal details the business needs.",
Expand Down
7 changes: 6 additions & 1 deletion bundles/plex/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
{
"id": "plex",
"name": "Plex",
"version": "1.0.1",
"version": "1.0.2",
"privileged": true,
"install_consent_messages": {
"en": "Crow does not start a Plex server at install: it runs only if you start it from Extensions. If you do, the self-hosted Plex server uses host networking (Plex's own recommendation) so devices on your local network can discover it. It listens on every network interface of this machine (port 32400 and Plex's discovery ports) and mounts your media folder read-write. Until you claim it with your Plex account (PLEX_CLAIM_TOKEN), the first person who opens it can claim it.",
"es": "Crow no inicia un servidor Plex al instalar: solo se ejecuta si lo inicias desde Extensiones. Si lo haces, el servidor Plex autoalojado usa la red del host (lo que recomienda Plex) para que los dispositivos de tu red local puedan descubrirlo. Escucha en todas las interfaces de red de esta máquina (el puerto 32400 y los puertos de descubrimiento de Plex) y monta tu carpeta de medios con lectura y escritura. Hasta que lo reclames con tu cuenta de Plex (PLEX_CLAIM_TOKEN), la primera persona que lo abra puede reclamarlo."
},
"description": "Connect to Plex Media Server — search library, browse collections, control playback, view active sessions",
"type": "mcp-server",
"author": "Crow",
Expand Down
2 changes: 1 addition & 1 deletion bundles/rookery/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ ROOKERY_MODEL_API_KEY=local
# serving layer you put in front of 127.0.0.1:3061 is the boundary).
ROOKERY_CORS_ORIGINS=
# Host dir where audit workspaces are assembled (shared with the MCP tool)
ROOKERY_WORKSPACES_DIR=~/.crow/data/rookery/workspaces
ROOKERY_WORKSPACES_DIR=~/.crow/data/rookery-workspaces
# Where the reviewer UI is reachable on YOUR deployment (root-origin serving:
# a Tailscale Serve HTTPS port, a reverse proxy, or an ssh -L tunnel to
# 127.0.0.1:3061). Shown by the panel and the MCP tool. Empty = local default.
Expand Down
2 changes: 1 addition & 1 deletion bundles/rookery/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ host.docker.internal:host-gateway`) but the connection times out; verified
on a live install 2026-07-14),
`ROOKERY_MODEL_ID` (as reported by the endpoint's `/v1/models`),
`ROOKERY_MODEL_API_KEY` (only if your endpoint checks it; default `local`),
`ROOKERY_WORKSPACES_DIR` (default `~/.crow/data/rookery/workspaces` is
`ROOKERY_WORKSPACES_DIR` (default `~/.crow/data/rookery-workspaces`, beside the bundle data folder, not inside it, is
usually fine), and `ROOKERY_CORS_ORIGINS`/`ROOKERY_REVIEWER_URL` — see below.
Host prerequisite: the `rookery_assemble_exp` MCP tool and the panel's
assemble form both run via `uv` at `~/.local/bin/uv` (rookery is the first
Expand Down
2 changes: 1 addition & 1 deletion bundles/rookery/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ services:
MCP_RESEARCH_URL: ${ROOKERY_MCP_RESEARCH_URL:-}
volumes:
- ${HOME}/.crow/data/rookery:/data
- ${ROOKERY_WORKSPACES_DIR:-${HOME}/.crow/data/rookery/workspaces}:/workspaces
- ${ROOKERY_WORKSPACES_DIR:-${HOME}/.crow/data/rookery-workspaces}:/workspaces
ports:
- "127.0.0.1:3061:3061"
extra_hosts:
Expand Down
4 changes: 2 additions & 2 deletions bundles/rookery/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"id": "rookery",
"name": "Open Science Reviewer",
"origin": "community",
"version": "0.1.1",
"version": "0.1.2",
"description": "Self-hosted OpenScience reviewer + experiment-audit workspace assembler — audit a report's numeric claims against its registered evidence, on your own local model",
"type": "bundle",
"author": "kh0pper",
Expand All @@ -22,7 +22,7 @@
{ "name": "ROOKERY_MODEL_BASE_URL", "description": "OpenAI-compatible endpoint for the reviewer model (e.g. a local llama.cpp/vLLM server; find your configured endpoint in Crow's AI settings). If the host service binds a SPECIFIC IP (e.g. a Tailscale address), use that IP directly: http://<host-ip>:<port>/v1 — host.docker.internal only reaches services listening on 0.0.0.0 or the Docker bridge, and times out otherwise (verified 2026-07-14)", "required": true },
{ "name": "ROOKERY_MODEL_ID", "description": "Model id as reported by the endpoint's /v1/models", "default": "local-model", "required": true },
{ "name": "ROOKERY_MODEL_API_KEY", "description": "API key if the endpoint needs one (local servers usually ignore it)", "default": "local", "required": false, "secret": true },
{ "name": "ROOKERY_WORKSPACES_DIR", "description": "Host directory where audit workspaces are assembled (shared by the reviewer and the assemble tool)", "default": "~/.crow/data/rookery/workspaces", "required": false },
{ "name": "ROOKERY_WORKSPACES_DIR", "description": "Host directory where audit workspaces are assembled (shared by the reviewer and the assemble tool)", "default": "~/.crow/data/rookery-workspaces", "required": false },
{ "name": "ROOKERY_CORS_ORIGINS", "description": "Space-separated browser origins for the app's own CORS/CSRF whitelist. RECOMMENDED: set to your serving origin when the reviewer is served beyond localhost. Empty = shim strips Origin (fine for tunnel/localhost use; disables the app's origin check)", "required": false },
{ "name": "ROOKERY_REVIEWER_URL", "description": "Where the reviewer UI is reachable on your deployment (serve 127.0.0.1:3061 at a ROOT origin: Tailscale Serve HTTPS port, reverse proxy, or ssh -L tunnel). Shown by the panel and the assemble tool", "required": false },
{ "name": "UV_NO_CACHE", "description": "Disable uv's download cache for the host MCP process (prevents multi-GB cache growth)", "default": "1", "required": false },
Expand Down
2 changes: 1 addition & 1 deletion bundles/rookery/panel/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { join } from "node:path";
import os from "node:os";

const WORKSPACES = () =>
(process.env.ROOKERY_WORKSPACES_DIR || join(os.homedir(), ".crow/data/rookery/workspaces"))
(process.env.ROOKERY_WORKSPACES_DIR || join(os.homedir(), ".crow/data/rookery-workspaces"))
.replace(/^~(?=\/)/, os.homedir());
// Root-origin serving (plan deviation 4): the reviewer is NOT behind /proxy/<id>/.
// Scheme allowlist: the value lands in anchor hrefs in the tile — a non-http(s)
Expand Down
2 changes: 1 addition & 1 deletion bundles/sdxl/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ services:
container_name: crow-sdxl
restart: unless-stopped
ports:
- "${SDXL_PORT:-3005}:3005"
- "127.0.0.1:${SDXL_PORT:-3005}:3005"
volumes:
- sdxl-backgrounds:/app/backgrounds
- sdxl-models:/app/models
Expand Down
2 changes: 1 addition & 1 deletion bundles/sdxl/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "sdxl",
"name": "SDXL Background Generator",
"version": "1.0.0",
"version": "1.0.1",
"description": "AI-generated backgrounds for the companion avatar using SDXL Turbo. Requires NVIDIA GPU.",
"type": "bundle",
"author": "Crow",
Expand Down
7 changes: 6 additions & 1 deletion bundles/tailscale/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
{
"id": "tailscale",
"name": "Tailscale",
"version": "1.0.0",
"version": "1.0.1",
"privileged": true,
"install_consent_messages": {
"en": "The Tailscale container joins this machine to your tailnet. It uses host networking, the NET_ADMIN capability and the /dev/net/tun device, so it creates a network interface and changes this machine's routing and firewall rules. Do not install it on a machine that already runs Tailscale.",
"es": "El contenedor de Tailscale une esta máquina a tu tailnet. Usa la red del host, la capacidad NET_ADMIN y el dispositivo /dev/net/tun, así que crea una interfaz de red y cambia las rutas y las reglas de firewall de esta máquina. No lo instales en una máquina que ya ejecuta Tailscale."
},
"description": "Private network access — reach your Crow from any device without exposing it to the public internet",
"type": "bundle",
"author": "Crow",
Expand Down
4 changes: 3 additions & 1 deletion bundles/vllm/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ services:
capabilities: [gpu]
ports:
- "127.0.0.1:${VLLM_HTTP_PORT:-8089}:8000"
ipc: host
# Shared memory for PyTorch workers. vLLM documents ipc: host OR a large shm; shm keeps
# the host IPC namespace private (the install check refuses ipc: host without consent).
shm_size: "${VLLM_SHM_SIZE:-8gb}"
environment:
- HUGGING_FACE_HUB_TOKEN=${VLLM_HF_TOKEN:-}
- VLLM_NO_USAGE_STATS=1
Expand Down
2 changes: 1 addition & 1 deletion bundles/vllm/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "vllm",
"name": "vLLM",
"version": "1.0.0",
"version": "1.0.1",
"description": "GPU-accelerated local LLM inference server \u2014 OpenAI-compatible endpoint backed by vLLM's continuous batching and PagedAttention. Recommended classroom engine for Maker Lab: the Phase 0 Ollama benchmark hit unusable p95 latencies at N=25 concurrent learners; vLLM is architecturally the right shape for that scale.",
"type": "bundle",
"author": "Crow",
Expand Down
2 changes: 1 addition & 1 deletion docs/developers/addon-registry.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ The registry is a JSON file at `registry/add-ons.json`:
| `requires.min_disk_mb` | No | Minimum disk space in MB |
| `requires.gpu` | No | Set `true` if the add-on needs a GPU |
| `requires.bundles` | No | Array of bundle IDs that must be installed first. Install endpoint refuses if any are missing; uninstall is blocked while dependents are installed. |
| `privileged` | No | Set `true` for bundles that need NET_ADMIN, NET_RAW, SYS_ADMIN, or `network_mode: host`. Triggers the install-modal consent flow with a server-validated single-use token. |
| `privileged` | No | Set `true` for bundles that need NET_ADMIN, NET_RAW, SYS_ADMIN, or `network_mode: host`. Triggers the install-modal consent flow with a server-validated single-use token. `tests/bundle-compose-gate.test.js` runs the install security check over every first-party compose file, so a bundle that needs one of these and does not declare it fails CI. |
| `consent_required` | No | Set `true` for bundles with significant operational cost or read-Docker-socket access (netdata, dozzle). Triggers the consent modal even if not `privileged`. |
| `install_consent_messages` | No | Object keyed by language code (`en`, `es`, ...) with the warning text shown in the install-confirmation modal. Falls back to `install_consent_message` then a generic string. |
| `install_consent_message` | No | Single-language fallback for `install_consent_messages`. |
Expand Down
Loading
Loading