Local-first AI desktop workbench (a lightweight “desktop OS” experience):
- Electron: desktop shell & OS integrations (windows, tray, dialogs)
- React + Vite: renderer UI
- Python (Flask): local AI/Agent runtime and tool orchestration
- Apps (plugins): pluggable sub-apps under
apps/(frontend + Python backend + capability manifest)
Goal: works out of the box and ecosystem-friendly for third-party app developers.
- Node.js LTS (recommended 18/20+)
- Windows PowerShell
- Git (optional)
Run from the repo root:
setup-dev.batIt will:
- Run
npm install - Download and extract Python embeddable into
python-embed/(if missing) - Enable
import siteinpython311._pth - Install Python deps for the main backend (
backend/requirements.txt)
Note: .gitignore excludes python-embed/, so this won’t pollute git changes.
npm run dev- Vite dev server: http://localhost:5173
- Python runtime: http://127.0.0.1:5000
Configure API Key / Base URL / Model in the UI settings panel.
The Python runtime stores config in the user profile (not in the repo):
- Windows:
%APPDATA%\\ailurus-os\\llm_config.json
Note: .gitignore ignores **/llm_config.json to prevent leaking secrets.
- Dev mode: reads the repo
apps/directory - Packaged mode: reads/creates an
apps/directory next to the exe - Each app is described by
ailurus.json:frontend: frontend entry (usuallyfrontend/index.html)backend: Python Flask backend entry (usuallybackend/app.py)capabilities: agent-visible capabilities (name/description/keywords/schema)
- Electron starts the main Python runtime (Flask on port 5000)
- When an app is launched/preloaded:
- Electron asks the main runtime to load the app backend via
/api/tools/<tool_id>/load - The main runtime proxies requests from
/<tool_id>/api/...to that app’s Flaskapp
- Electron asks the main runtime to load the app backend via
- Main runtime endpoint:
/api/agent/execute- routes and orchestrates based on
capabilities - dispatches to
/<tool_id>/api/agent/handle
- routes and orchestrates based on
- Each app can implement its own agent handler:
- parse parameters (optionally using LLM)
- run internal APIs
- return
{ text, data }
apps/my-app/
ailurus.json
frontend/
index.html
main.js
style.css
i18n.json (optional)
backend/
app.py
requirements.txt (optional)
pack_app.py (optional, recommended)
README.md (optional)
name: display nameversion: semver recommendedfrontend: frontend entry filebackend: backend entry file (must exposeapp = Flask(...))capabilities[]:name: capability namedescription: what it doeskeywords: routing keywordsapi:{ method, endpoint, schema }(JSON Schema)
Your backend/app.py should:
- export
app = Flask(__name__) - implement routes referenced by
capabilities[].api.endpoint - (for Agent integration) implement
/api/agent/handle
Optional: export shutdown(); the main runtime will try to call it on unload for cleanup.
Example apps include pack_app.py to produce a .ail package:
cd apps/chron
python pack_app.pyThen import the .ail file in the UI.
npm run packageNotes:
- Electron-builder packages
dist/,electron/,backend/ - Windows builds bundle
python-embed/viaextraFiles
The repo ignores (highlights):
python-embed/(embeddable Python, downloaded locally)release/,dist/,node_modules/(build outputs)**/llm_config.json(secrets)
MIT