- Why I Built SheetBot
- Philosophy
- AI Usage
- Conceptual Architecture
- Features
- Getting Started
- Known Issues
- Initialization
- Scripts
- Protocol and API
- Data Management
- Agent Workflow
- Programmability and Extensibility
- Project Structure
An open-source automation and CI tool built with Deno, Express.js, SQLite, Web Components (Lit), and JSON Schema. SheetBot provides flexible task orchestration and a widget-based UI for visualization, enabling cross-platform builds, remote installations, and bespoke automation without heavy dependencies.
For a detailed human-written account of SheetBot's development and philosophy, see: https://mooses.nl/blog/sheetbot_opensource_release/
I needed a quick build system for testing modifications to my projects across Linux, Windows, and MacOS. Existing open-source CI systems had too many dependencies, strong opinions on configuration, weak cross-platform support, and weren't designed for pet-like machines or extensibility through code. SheetBot solves these by using SQLite for storage, JSON Schema for task matching, and opaque scripts that can be written in any language.
SheetBot embraces "primitive emergent architecture": simple primitives (tasks, schemas, widgets) that combine into powerful systems. It's designed for configuration as code, easy extensibility, and integration with diverse environments. Tasks are opaque to SheetBot, allowing scripts in any language with custom runners. The API is simple; add a new runner with a few hours of work or an AI prompt.
Built with familiar tools: Express, JSON Schema, SQLite and Web Components. No complex dependencies, no complex build tooling, no opinions on build scripts, just flexible automation and the ability to get started with a simple git clone and deno run command.
As much compute as possible is pushed out to the viewer side (the web UI) or build agents, and kept away from the server side so that the server is lightweight and doesn't need a lot of compute. For example, visualizations depicting which tasks can be ran by which agents is performed client-side in the UI.
SheetBot is unlikely to be as easy to learn and use compared to existing CI tools, but once you understand how it works and how things fit together, it should be far easier to modify it to suit your needs. For me personally, that has saved time in the long run.
Much of the SheetBot codebase since March 2025 has been developed with assistance from AI tools like Claude Code, Amazon Q Developer CLI, and OpenCode. The project's architecture lends itself well to AI-assisted development, particularly for creating custom widgets and integrations. This approach has accelerated feature development and demonstrated the potential of configuration as code with extensible scripting languages.
If you prefer to work with code developed without AI influence, refer to this commit from before any AI tools were utilized. AI usage was minor (function-level only) after that commit until March 2025.
SheetBot's core concepts are:
- Tasks: custom jobs containing arbitrary opaque scripts that can run in any programming language
- Agents: worker processes that execute tasks on various machines; SheetBot doesn't control them, they aren't persistent, and typical agent flows are simple scripts running in a cron job, e.g.,
curl -fsSL ${SHEETBOT_BASEURL}/scripts/agent.sh | bash - Sheets: tables for storing and visualizing data from tasks, mimicking classic spreadsheets like Excel
- Artefacts: files uploaded or generated by tasks
- Transitions: automated rules for changing task states
These primitives interact to create a flexible automation system where tasks are matched to agents based on requirements like OS or memory. Agents run the scripts, report results, and store data in sheets for visualization with customizable widgets. Transitions manage task lifecycles automatically. Both task matching and transitions are done via JSON Schema validation.
For more details on why JSON Schema is used for task matching and transitions, see why_json_schema.md.
This primitive emergent architecture makes SheetBot unique by allowing configuration entirely as code, supporting diverse environments from Raspberry Pis to gaming handhelds, and enabling easy customization without complex build tools.
While SheetBot provides core automation primitives, it differs from full-featured CI/CD platforms like GitHub Actions or GitLab CI/CD. Traditional systems typically include event-driven triggers, multi-stage pipelines, built-in caching, deployment environments, security scanning, and notifications.
These features can be implemented in SheetBot using its primitives:
- Triggers: Via polling tasks that periodically check Git repos for updates and spawn build tasks, or by adding custom webhooks to the Express.js app
- Pipelines: Through task dependencies and transitions, comprehensive scripts, or the experimental distributed promise runtime (Distributed Runtime)—a Deno-only feature—that enables a higher-level programming paradigm where tasks serve as modular compute blocks orchestrated via natural async TypeScript code into distributed DAGs
- Caching/Workspaces: Data persistence via artefacts and sheet-stored metadata; manual caching with tools like sccache; workspaces via capability schemas or environment variables directing tasks to pre-existing local project directories for checkout reuse and incremental builds
- Security/Notifications: Via custom scripts in tasks or Express.js app modifications (implementation depends on use case)
SheetBot's ephemeral tasks — automatically deleted via transitions when completed/failed or reset to awaiting for periodic compute — provide an excellent core compute layer. This flexibility makes it suitable for diverse automation needs, where traditional CI/CD systems offer specific implementations and APIs for similar features. SheetBot's core concepts are fewer than traditional CI/CD's, but they cover more ground.
Conceptually, this looks like this:
- Flexible Task Orchestration: Tasks with arbitrary scripts matched to agents via JSON Schema capabilities
- Distributed Runtime: Agents poll for tasks based on type and capabilities (e.g., OS, memory, installed software)
- Widget-Based UI: HTML table interface with customizable widgets for data visualization (text, images, code, downloads). Supports keyboard navigation, multi-cell selection with click-and-drag, and copying selected cells to clipboard as text or HTML tables. Columns can display multiple widgets with right-click context menus to switch between views.
- Opaque Scripts: Run tasks in any language: Deno, Python, Bash, or custom runners
- Dependency Management: Tasks can depend on others which blocks them until the others complete
- Artefacts & Data Storage: File uploads and SQLite-backed sheets for persistent data
- Transitions: Automatable task status changes (e.g., auto-delete, periodic resets)
- Cross-Platform: Works on diverse hardware from Raspberry Pis to gaming handhelds
- Extensibility: Modify code for custom auth, endpoints, widgets, or task types
See Distributed Runtime for info on an experimental distributed runtime system that's also included.
- Ensure Deno is installed, then clone this repository
- Add a user via
deno run adduser.ts- this will prompt you first for read and write access to files like the user database file; read through them and accept if you agree, then type in the username and password to generate a new user. Use*for permissions to give access to all features, or see docs/permissions.md for more info on the permissions system. - (Optional) Generate an API key via
deno run -A addapikey.tsfor secure agent authentication - see docs/api_keys.md for details. - Run the main server:
deno run --allow-read=./static --allow-read=./secret.txt --allow-read=./users.db --allow-write=./users.db --allow-read=./tasks.db --allow-write=./tasks.db --allow-read=./artefacts/ --allow-write=./artefacts/ --allow-read=./sheets/ --allow-write=./sheets/ --allow-read=./library/ --allow-read=./scripts/ --allow-read=./init/ main.ts- this will again prompt for a few extra permissions; read through them and accept if you agree. - Access the web interface at http://localhost:3000/
- To test SheetBot, go to the Library page and add the "Hello World" task.
- Run an agent to execute the task:
export SHEETBOT_AUTH_USER=your_username export SHEETBOT_AUTH_PASS=your_password # Alternatively, use an API key: # export SHEETBOT_AUTH_APIKEY=your.api.key export SHEETBOT_BASEURL=http://localhost:3000 deno run --allow-net --allow-env --allow-read ${SHEETBOT_BASEURL}/scripts/agent.ts
- (Optional) View tasks from the terminal using the TUI:
deno run --allow-net --allow-env ${SHEETBOT_BASEURL}/tui.ts
By default, SheetBot listens on all interfaces (0.0.0.0) - change this in main.ts as needed.
See Known Issues for current limitations and workarounds.
See Initialization System for details on the startup initialization system that runs TypeScript scripts on every server startup.
scripts/directory: Contains agent template files (agent.template.ts,agent.template.py,agent.template.sh)library/directory: Contains automation scripts for various use cases (game development, web deployment, system automation, etc.) - See examples
Library scripts use special XML-like annotations in comments to define task metadata. See Library Script Annotations for details on how to use <name>, <capabilitiesSchema>, <data>, and <addTaskComments> annotations.
See Protocol for task execution flows and Artefacts for artefact management.
See Data Management for details on task data, dependency injection, sheet data, and sheet updates during tasks.
See Agent Workflow for information on how agents poll for tasks and execute them using various runners.
See Programmability for key extension points and how to customize SheetBot.
lib/: Core libraries and data providersscripts/: Agent template fileslibrary/: Automation scriptssheets/: Generated sheet filesstatic/: Web assets and HTML filesdocs/: Documentation filesinit/: Initialization scripts that run on server startupartefacts/: File artefacts uploaded by tasksadduser.ts: Script to add users to the databaseaddtask.ts: Script to add tasks programmaticallyopenapi.yaml: OpenAPI specification for the API- Database files:
users.db,tasks.db,secret.txt(created on first run)

