Deterministic script runner for the Ancroo ecosystem. Runs user-extensible plugins that transform data — no LLM required.
Phase 0 (Beta) — The runner is functional for local use, but the stack it connects to runs without encryption or authentication by default and is still under active development. Intended for local/trusted networks only. See the Ancroo Roadmap for the security path forward.
Ancroo Runner is a lightweight FastAPI service with a plugin system. Each plugin is a directory with a config file and Python scripts. The runner loads plugins at startup and exposes them as HTTP endpoints.
Browser Extension → Ancroo Backend → Ancroo Runner → Plugin Script
↓
Result (JSON)
The backend calls the runner via the existing custom workflow type — no special integration needed.
Plugins live in two locations:
| Location | Purpose |
|---|---|
plugins/ |
Builtin plugins, shipped with the image |
| User-mounted volume | User plugins, added without rebuilding |
my-plugin/
├── tool.yaml # Endpoint definitions
├── requirements.txt # Python dependencies (optional)
├── my_script.py # def run(input: dict) -> dict
└── another_script.py # Additional scripts (optional)
name: my-plugin
description: What this plugin does
endpoints:
- path: /convert/something
script: my_script.py
description: Convert something to something elseEvery script must export a run function:
def run(input: dict) -> dict:
# Process input
return {"result": "output text"}- Input: JSON body from the HTTP request
- Output: Dict with
"result"key (matches the$.resultresponse mapping convention)
| Endpoint | Description |
|---|---|
POST /convert/html-to-markdown |
Convert HTML to clean Markdown |
Input: {"html": "<b>Hello</b> <a href='https://example.com'>World</a>"}
Output: {"result": "**Hello** [World](https://example.com)"}
| Endpoint | Description |
|---|---|
POST /transcribe/audio |
Transcribe audio with silence-based splitting via Whisper API |
Splits long audio files at speech pauses, transcribes each chunk via a Whisper-compatible API (e.g. Speaches), and reassembles the text. Requires the speaches or whisper-rocm stack module.
Input:
{
"audio_base64": "<base64-encoded audio (WAV, MP3, FLAC, OGG)>",
"language": "de",
"model": "Systran/faster-whisper-large-v3"
}Output:
{
"result": "Transcribed text...",
"duration_s": 45.2,
"chunks_count": 3
}Environment: Set WHISPER_BASE_URL to override the default Whisper API endpoint (http://speaches:8000/v1/audio/transcriptions).
| Endpoint | Description |
|---|---|
POST /convert/webpage-to-ebook |
Convert webpage HTML to an EPUB file (returns base64) |
Takes a full webpage's HTML and converts it to a clean EPUB ebook. Scripts, styles, and non-content elements are stripped automatically.
Input:
{
"html": "<html>...</html>",
"title": "Page Title",
"url": "https://example.com/article"
}Output:
{
"result": "<base64-encoded EPUB>",
"filename": "page-title.epub",
"mime_type": "application/epub+zip"
}Note: This plugin depends on ebooklib (AGPL-3.0). The dependency is isolated to the plugin and installed at container startup only when the plugin is loaded.
If the runner repo is cloned alongside the stack (automatically offered during ancroo-stack/install.sh):
cd ancroo-runner
./install-stack.sh ../ancroo-stackThis symlinks the module files into the stack, adds compose entries, and starts the service. For dev builds from source, set ANCROO_LOCAL_BUILD=y:
ANCROO_LOCAL_BUILD=y ./install-stack.sh ../ancroo-stackAlternatively, if the module files are already in the stack:
bash /path/to/ancroo-runner/install-stack.sh /path/to/ancroo-stackdocker build --build-arg BUILD_COMMIT=$(git rev-parse --short HEAD) -t ancroo-runner .
docker run -p 8510:8000 -v ./my-plugins:/app/user-plugins:ro ancroo-runner- Create a plugin directory with
tool.yamland scripts - Place it in the user plugins volume (default:
data/ancroo-runner/plugins/) - Restart the container
docker compose restart ancroo-runnerThe runner integrates with Ancroo Backend via the custom workflow type. Example workflow definitions are in the workflows/ directory. To use them, import them via the backend admin panel or API.
Important: The runner listens on port 8000 inside the Docker network. The host port (default 8510) is only for external access. When creating backend workflows that call the runner, use the internal URL:
http://ancroo-runner:8000/convert/html-to-markdown
See workflows/html-to-markdown.json for a complete example that maps a browser text selection to the runner's /convert/html-to-markdown endpoint.
| Method | Path | Description |
|---|---|---|
GET |
/health |
Health check (includes commit hash and plugin count) |
GET |
/plugins |
List loaded plugins and their endpoints |
POST |
<plugin path> |
Execute a plugin endpoint |
Contributions are welcome! Feel free to open an issue or submit a pull request.
To report a security vulnerability, please use GitHub's private vulnerability reporting instead of opening a public issue.
Stefan Schmidbauer — GitHub · stefan@ancroo.com
This project is built with the following open-source software:
| Project | Purpose | License |
|---|---|---|
| FastAPI | Web framework | MIT |
| Uvicorn | ASGI server | BSD-3-Clause |
| PyYAML | Plugin config parsing | MIT |
Builtin plugins use additional libraries:
| Library | Plugin | License |
|---|---|---|
| markdownify | markdown-utils | MIT |
| Beautiful Soup | webpage-to-ebook | MIT |
| lxml | webpage-to-ebook | BSD-3-Clause |
| ebooklib | webpage-to-ebook | AGPL-3.0 |
| pydub | audio-transcription | MIT |
| Requests | audio-transcription | Apache-2.0 |
Note: The
webpage-to-ebookplugin depends on ebooklib, which is licensed under AGPL-3.0. This dependency is isolated to the plugin and installed at container startup only when the plugin is loaded.
MIT — see LICENSE. The Ancroo name is not covered by this license and remains the property of the author.
Built with the help of AI (Claude by Anthropic).