Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Snuffles — bounded Linux host context for AI agents

CI License: MIT Node.js 22+ Cloudflare Workers MCP

Observe Linux host metadata, package redacted context, and record guarded action intent—without pretending to be an autonomous remediation platform.

Quick start · Capabilities · Architecture · HQ roadmap · Security


What is Snuffles?

Snuffles is an open-source, observation-first Linux host monitoring toolkit for AI agents and human operators. It combines a Cloudflare Worker/Vinext dashboard, Cloudflare D1 state, an optional signed VPS metadata probe, redacted ZIP snapshots, bounded Telegram delivery, and an experimental Model Context Protocol (MCP) JSON-RPC endpoint.

It is designed for a small Linux server where an agent runs locally, connects through SSH, or calls an explicitly authorized API. Snowball is the opt-in permission boundary for guarded action intent: it can record a qualifying containment request as pending_approval, but it does not change a firewall, host, or Cloudflare rule.

Important

Snuffles is a proof of concept—not a managed security product, SIEM, SOC, incident-response service, high-availability system, backup solution, or autonomous remediation engine. Initial dashboard signals are illustrative until replaced by persisted D1 state.

Why this project exists

Giving an AI agent unrestricted shell access is easy. Giving it a small, inspectable, documented boundary is harder. Snuffles explores that boundary through four principles:

  1. Observe metadata, not raw logs. The optional probe sends a strict projection of host health fields.
  2. Keep secrets write-only. Provider tokens are encrypted with AES-GCM and never returned by state or MCP reads.
  3. Separate intent from execution. Snowball records approval-aware intent; this checkout has no provider mutation engine.
  4. Remain useful without an AI model. Host state and the optional hourly Telegram summary are deterministic local tools.

What works today

Capability Status Boundary
Responsive React/Vinext control-room dashboard ✅ Implemented Uses illustrative data when D1 is unavailable; persisted empty state stays empty
GET / POST /api/state with Cloudflare D1 ✅ Implemented Six explicit state actions; authorization is deployment-configured
Signed Linux host metadata probe ✅ Implemented HMAC-SHA256, replay ID, clock window, 16 KiB limit, no raw logs
Redacted ZIP context snapshots ✅ Implemented Explicit projections, SHA-256 checksum, latest-20 retention
Telegram snapshot and monitoring-summary delivery ✅ Bounded Owner-only, one configured destination, allowlisted metadata
Provider credential checks ✅ Bounded Fixed Cloudflare, Telegram, and Slack verification endpoints only
MCP-compatible JSON-RPC tools 🧪 Experimental Stateless POST; no SSE and no provider-side mutation
Snowball containment intent ✅ Implemented Records pending_approval; applies no host or edge change
Ubuntu systemd handoff 🧰 Prepared Examples only; operator provisioning is required
Live log/event ingestion and automatic remediation ❌ Not implemented Prospective, not advertised as available

The detailed source of truth is docs/capability-status.md.

Quick start

Requirements

  • Node.js 22.13.0 or newer
  • npm
  • A local clone
git clone https://github.com/TurabiOzturk/snuffles.git
cd snuffles
npm ci
cp .env.example .dev.vars
npm run dev

Open the local URL printed by Vinext. The template uses SNUFFLES_API_MODE=ssh-tunnel, which has no application-level login and must remain on loopback. Do not expose that mode to a public network.

The dashboard can render without D1 by showing an explicitly labeled illustrative preview. For durable state, run with the local Cloudflare binding configured by .openai/hosting.json or provide a deployed D1 binding named DB.

Verify the checkout

npm run check              # lint + types + build/tests + production audit
npm run build              # build Worker and static assets
npm audit --omit=dev       # production dependency audit

Architecture

flowchart LR
    Operator["Operator / AI agent"] -->|authorized HTTP| State["State API"]
    Client["MCP client"] -->|bounded JSON-RPC POST| MCP["MCP compatibility route"]
    Probe["Optional Linux host probe"] -->|HMAC + replay ID| Agent["Host metadata route"]
    Timer["Optional hourly timer"] --> Notify["Redacted Telegram summary"]

    State --> D1[(Cloudflare D1)]
    MCP --> D1
    Agent --> D1
    D1 --> Snapshot["Redacted ZIP snapshot"]
    Snapshot -->|owner-authorized| Telegram["Configured Telegram destination"]

    Snowball["Snowball permission"] -. "allows intent record" .-> Pending["pending_approval"]
    Pending -. "no execution path" .-> Boundary["Host/provider unchanged"]
Loading

Runtime options

Mode Use case Security boundary
Local preview UI, API, and contract development Localhost only
Ubuntu handoff Local Worker/D1 on a small Linux VPS 127.0.0.1:4417 through SSH forwarding
Cloudflare Hosted Worker with provisioned D1 Private Site identity, API token, or signed webhook

See docs/deployment-modes.md before exposing an instance.

Roadmap: Snuffles HQ

Snuffles HQ is the planned singular monitoring and coordination node for a fleet of independent Snuffles hosts. Each host will keep its local observation boundary, state, and optional delivery path; HQ will provide one place to understand and coordinate the fleet.

flowchart LR
    H1["Snuffles host A"] -->|normalized metadata| HQ["Snuffles HQ\nsingular coordination node"]
    H2["Snuffles host B"] -->|normalized metadata| HQ
    H3["Snuffles host N"] -->|normalized metadata| HQ
    HQ --> Fleet["Fleet status + presentation"]
    HQ --> Index["Redacted snapshot index"]
    HQ --> Coordination["Operator / agent coordination"]
Loading

Planned HQ responsibilities:

  • register multiple Snuffles hosts and show their latest normalized health state;
  • aggregate allowlisted metadata and signal summaries without becoming a raw-log or secret collector;
  • present fleet-level status, redacted snapshot indexes, and action-intent history;
  • coordinate reviewed monitoring templates and operator/agent workflows; and
  • preserve explicit authorization, redaction, audit, approval, and failure boundaries for every cross-host operation.

Roadmap sequence:

  • Publish typed host-to-HQ HTTP contracts, OpenAPI artifacts, and generated SDKs.
  • Add authenticated host registration, heartbeat, replay protection, and bounded retention.
  • Build the multi-host fleet dashboard and redacted snapshot index.
  • Add explicit approval coordination and auditable receipts without silently executing host changes.
  • Document backup, migration, degraded-HQ, and host-disconnection behavior before calling HQ production-ready.

Note

HQ is prospective. It is not implemented by the current routes or dashboard, and it will not be the only source of host truth. A Snuffles host must remain understandable and useful when HQ, an AI agent, or a provider integration is unavailable. A singular HQ node is a coordination topology—not a claim of high availability, failover, incident response, or automatic recovery.

HTTP API

Route Methods Purpose
/api/state GET, POST Read workspace state and execute six bounded state actions
/api/agent POST Accept a signed, recent, metadata-only host snapshot
/api/snapshots GET, POST List, create, download, and owner-deliver redacted ZIPs
/api/notifications POST Discover Telegram destination metadata or send one safe summary
/api/mcp POST Initialize MCP, list tools, and perform guarded tool calls

Authorization modes are ssh-tunnel, site-private, token, and webhook. Request headers, signing strings, limits, owner behavior, and replay handling are documented in docs/agent-boundaries.md.

Minimal MCP request

With local loopback-only ssh-tunnel mode:

curl --fail-with-body http://127.0.0.1:3000/api/mcp \
  --header 'content-type: application/json' \
  --data '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/list",
    "params": {}
  }'

Use the URL printed by the local runtime if it selects a different port. Hosted callers must include the credentials required by their configured mode.

MCP tools

Tool Kind Effect
snuffles.discover Context Return the safe resource catalog and latest normalized host snapshot
snuffles.observe Read Read persisted normalized signals and status
snuffles.explain Read Return one normalized signal and its evidence array
snuffles.plan_build Plan Produce a deterministic read-only-first build plan
snuffles.test_integration Owner action Call one fixed provider credential-verification endpoint
snuffles.snapshot Context/delivery Create a redacted ZIP; optionally deliver it to Telegram as owner
snowball.recommend Plan Recommend observation or a pending containment request
snowball.contain Guarded intent Record pending_approval; never apply a provider rule
snowball.wake / snowball.sleep Owner action Enable or revoke guarded intent mode

Host metadata contract

The optional probe executes fixed, read-oriented commands and projects only:

  • hostname, OS release, kernel, and architecture;
  • systemd state and failed unit names;
  • root filesystem percentage and available space;
  • Nginx installation/version and configuration-test status;
  • Docker version and running-container count;
  • journal disk usage; and
  • listening addresses and ports.

It does not send Nginx logs, journal entries, SSH event bodies, Docker logs, environment variables, credentials, or arbitrary command output. Bodies are byte-bounded and signed over timestamp.deliveryId.exactBody.

Security model

Snuffles defaults to observation and fails closed when required authorization or secret configuration is absent.

  • Integration tokens are encrypted with AES-GCM, a fresh IV, and provider-bound associated data.
  • Host probes and signed webhooks use separate HMAC-SHA256 secrets and replay IDs.
  • Mutation routes enforce origin checks, strict body limits, explicit JSON errors, action admission limits, and owner checks where required.
  • Snapshot exports contain allowlisted projections rather than raw database rows.
  • Worker responses add anti-sniffing, anti-framing, referrer, permissions, opener, and resource-policy headers.
  • Telegram provider errors are reduced to generic messages; provider payloads are not forwarded.

Read SECURITY.md before deployment. Never commit .env files, provider tokens, API keys, HMAC secrets, owner identifiers, real host snapshots, or production hostnames.

Configuration

Copy .env.example and use synthetic local values. Important variables include:

Variable Purpose
SNUFFLES_API_MODE Select the API authorization boundary
SNUFFLES_API_KEY Authenticate token-mode requests
SNUFFLES_WEBHOOK_SECRET Verify state webhook signatures
SNUFFLES_AGENT_HMAC_SECRET Verify host probe snapshots
SNUFFLES_SECRETS_KEY Encrypt provider credentials; minimum 32 characters
SNUFFLES_WORKSPACE_ID Select the single deployment workspace
SNUFFLES_ALLOWED_ORIGINS Allow additional browser origins for writes/MCP

Several launcher-owned placeholders are intentionally inactive in application code. See docs/configuration.md for the exact consumer of every variable.

Project structure

app/                 Dashboard, API routes, validation, redaction, and MCP tools
db/                  Drizzle schema and D1 access
drizzle/             Reviewed D1 migrations
deploy/              Prepared Ubuntu systemd examples
docs/                Architecture, boundaries, deployment, and capability status
public/              Discovery metadata and original project artwork
scripts/             Optional host probe and hourly monitor
tests/               Rendering, security, snapshot, monitoring, and contract tests
worker/              Cloudflare Worker entry point and response hardening

Documentation

Contributing

Contributions are welcome when they preserve the separation between observation, planning, delivery, and external side effects. Read AGENTS.md, ARCHITECTURE.md, and CONTRIBUTING.md before changing a route, integration, credential path, snapshot, or guarded action.

npm ci
npm run check

A capability is not “implemented” until its authorization, validation, redaction, side effect, bounded failure behavior, tests, and operator documentation all exist.

License

Source code and original project artwork are available under the MIT License. Asset details are recorded in docs/asset-licensing.md.


Snuffles keeps observation useful and action intent small.
Last reviewed: 2026-09-03 · release 0.8.0

About

Observation-first Linux host monitoring toolkit for AI agents, with Cloudflare Workers, D1, MCP, signed metadata probes, and guarded action intent.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages