The OrcaSlicer API Bridge
OrcaSlicer has no plugin API. Shamu fixes that — without forking or touching a line of C++.
Install · API Reference · Build an Addon · Security · Roadmap
OrcaSlicer stores all settings, profiles, and sliced G-code as plain JSON and text files on disk. Shamu is a small background service that watches those files and wraps them in a clean HTTP + WebSocket API at localhost:7878. Write your addon in Python, JavaScript, Rust — anything that speaks HTTP.
OrcaSlicer ←── reads/writes JSON files ──→ Shamu ←── HTTP / WebSocket ──→ Your Addon
No forking. No C++. No waiting for a native plugin system to land in core.
pip install shamuOr from source:
git clone https://github.com/breakingcircuits1337/Shamu
cd Shamu && pip install -e .Start the bridge:
shamu[Shamu] Starting on http://127.0.0.1:7878
[Shamu] Token file: ~/.config/shamu/token
[Shamu] API docs: http://127.0.0.1:7878/docs
[Shamu] OrcaSlicer: ~/.config/OrcaSlicer
[Shamu] Watching: ~/.config/OrcaSlicer
Open http://localhost:7878/docs for the full interactive API explorer.
Options:
| Flag | Default | Description |
|---|---|---|
--port |
7878 |
Port to listen on |
--host |
127.0.0.1 |
Bind address — 0.0.0.0 exposes to network, use with caution |
--config-dir |
auto-detected | Path to OrcaSlicer config directory |
--show-token |
— | Print the current API token and exit |
Health check. Public endpoint — no token required.
{
"shamu": "ok",
"version": "0.1.0",
"orca_detected": true,
"connected_addons": 2
}Returns the merged active profile (process + printer + filament) as a single flat JSON object.
curl http://localhost:7878/settings \
-H "X-Shamu-Token: $(cat ~/.config/shamu/token)"{
"layer_height": 0.2,
"infill_density": 15,
"print_speed": 200,
"nozzle_temperature": 220
}Merge changes into the active process profile. OrcaSlicer picks them up on the next slice. Keys must be snake_case — anything else is rejected.
curl -X PATCH http://localhost:7878/settings \
-H "X-Shamu-Token: $(cat ~/.config/shamu/token)" \
-H "Content-Type: application/json" \
-d '{"layer_height": 0.15, "infill_density": 20}'Get individual profile types.
List all available profiles by type — both user-created and system defaults.
{
"process": { "user": ["My Fast Profile"], "system": ["0.20mm Standard"] },
"filament": { "user": [], "system": ["Generic PLA", "Generic PETG"] },
"machine": { "user": [], "system": ["Bambu P1S 0.4 nozzle"] }
}Load a specific profile by type (process, filament, printer) and name.
Raw G-code from the most recent slice. Add ?lines=N to get only the first N lines.
Parsed stats from the latest G-code header — no comment scraping required.
{
"estimated_time_str": "1h 23m 10s",
"filament_used_g": 42.3,
"layer_count": 412,
"nozzle_temp": 220,
"bed_temp": 65,
"filament_type": "PLA",
"printer_model": "Bambu P1S"
}Real-time event stream. Connect once, receive events as they happen. Pass token as a query param.
import asyncio, websockets, json
from pathlib import Path
token = Path("~/.config/shamu/token").expanduser().read_text().strip()
async def listen():
async with websockets.connect(f"ws://localhost:7878/events?token={token}") as ws:
async for msg in ws:
event = json.loads(msg)
print(event["event"], event)
asyncio.run(listen())Event types:
| Event | Fires when | Key payload fields |
|---|---|---|
shamu_ready |
Client connects | orca_detected |
slice_complete |
OrcaSlicer writes a .gcode file |
gcode_path, stats |
profile_changed |
Any profile JSON is saved | profile_type, name |
settings_changed |
PATCH /settings is called |
source, changes |
Any program that can make HTTP requests is a Shamu addon. Read the token from ~/.config/shamu/token and send it as X-Shamu-Token on every request.
import httpx
from pathlib import Path
token = Path("~/.config/shamu/token").expanduser().read_text().strip()
headers = {"X-Shamu-Token": token}
# Read current settings
settings = httpx.get("http://localhost:7878/settings", headers=headers).json()
print(f"Layer height: {settings['layer_height']}")
# Apply changes — OrcaSlicer picks these up on next slice
httpx.patch("http://localhost:7878/settings", headers=headers, json={
"layer_height": 0.15,
"print_speed": 150,
})const fs = require('fs');
const token = fs.readFileSync(require('os').homedir() + '/.config/shamu/token', 'utf8').trim();
const h = { 'X-Shamu-Token': token };
// Get settings
const settings = await fetch('http://localhost:7878/settings', { headers: h }).then(r => r.json());
// Listen for slice events
const ws = new WebSocket(`ws://localhost:7878/events?token=${token}`);
ws.onmessage = (e) => {
const event = JSON.parse(e.data);
if (event.event === 'slice_complete') console.log('Slice done!', event.stats);
};addons/example_ai_addon/ ships a working Claude-powered settings advisor. Tell it what you want in plain English — it figures out which settings to change.
pip install shamu[addon]
export ANTHROPIC_API_KEY=sk-ant-...
python addons/example_ai_addon/addon_ai_advisor.pyConnected to Shamu v0.1.0
What do you want to optimize?
> reduce stringing with PETG
Suggested changes (3 settings):
retraction_length: 0.8 → 1.4
retraction_speed: 35 → 45
print_speed: 200 → 160
Apply? [y/N] y
Applied. Re-slice in OrcaSlicer to see the effect.
Shamu only ever binds to 127.0.0.1 by default. Four layers of protection keep your settings safe:
| Measure | What it prevents | |
|---|---|---|
| 🔑 | Token auth on every endpoint | Unauthorized processes calling the API |
| 🛡️ | CORS restricted to null origin |
Malicious websites silently reading/writing your settings via browser fetch |
| 🚫 | Path traversal prevention on profile inputs | Escaping the config directory via crafted profile names |
| ⏱️ | Constant-time token comparison (secrets.compare_digest) |
Timing attacks on the auth header |
The token is generated with 256 bits of entropy on first run and stored at ~/.config/shamu/token with chmod 600 (owner read/write only).
Shamu auto-detects the OrcaSlicer config directory per OS. Override with --config-dir /your/path.
| OS | Path |
|---|---|
| 🪟 Windows | %APPDATA%\OrcaSlicer |
| 🍎 macOS | ~/Library/Application Support/OrcaSlicer |
| 🐧 Linux | ~/.config/OrcaSlicer |
- REST API — read and write active OrcaSlicer settings
- WebSocket events —
slice_complete,profile_changed,settings_changed - Token auth + CORS hardening + path traversal prevention
- AI advisor addon powered by Claude
-
POST /slice— trigger a headless slice via OrcaSlicer CLI - Profile diff endpoint — compare two profiles side-by-side
- Addon manifest format — declare dependencies, permissions, metadata
- Tray icon companion app
- Submit to OrcaSlicer upstream as a first-party companion tool
Pull requests welcome. If you build an addon using Shamu, open a PR to add it to the addons/ directory.
Relevant upstream discussion: OrcaSlicer/OrcaSlicer#9960 — Structured Addon/Extension Support
MIT License · Built by breakingcircuits1337
Is it a whale? Is it an API? Yes.