FlowOS Documentation
FlowOS is an AI-powered desktop operating system interface. The AI has real system access — it runs commands, manages files, installs packages, and controls your machine through natural conversation.
Project links
| Resource | URL |
|---|---|
| Source code | github.com/Mattjhagen/FlowOS-Project-Aquarius |
| Download ISO | projectaquarius.space |
| Documentation | flowos.wiki |
Architecture
FlowOS wraps the Anthropic Claude API in an agentic loop. On each turn, Claude receives the conversation history, a system prompt describing its role as the OS, and a list of tool definitions. When Claude wants to take a system action it emits a tool_use block; FlowOS executes the tool and feeds the result back as a tool_result. This continues until Claude emits a final text response with no tool calls.
File structure
flowos-desktop/
├── flowos.py # CLI entry point — --store flag for GUI
├── tools.py # Core tool definitions + handlers
├── plugin_manager.py # Plugin registry, config, setup wizard
├── session.py # Session persistence (~/.flowos/sessions/)
├── plugins/
│ ├── base.py # Plugin base class
│ ├── git_plugin.py
│ ├── docker_plugin.py
│ ├── ssh_plugin.py
│ ├── browser_plugin.py
│ ├── spotify_plugin.py
│ ├── homeserver_plugin.py
│ ├── notes_plugin.py
│ ├── weather_plugin.py
│ └── clipboard_plugin.py
├── gui/
│ ├── server.py # FastAPI backend
│ └── store.html # Plugin store UI
├── iso/
│ ├── build.sh # ISO build entry point
│ ├── Dockerfile
│ ├── initramfs/init # Custom boot init
│ ├── grub/grub.cfg
│ ├── scripts/ # rootfs, initramfs, ISO assembly
│ └── overlay/ # Files baked into the rootfs
└── docs/ # projectaquarius.space (GitHub Pages)Installation
FlowOS runs on macOS and Linux. Requires Python 3.10+ and an Anthropic API key.
# Clone the repo
git clone https://github.com/Mattjhagen/FlowOS-Project-Aquarius.git
cd FlowOS-Project-Aquarius
# Install dependencies
pip3 install -r requirements.txt
# Set your API key
export ANTHROPIC_API_KEY=your_key_here
# Run
python3 flowos.pyDependencies
| Package | Version | Purpose |
|---|---|---|
anthropic | ≥0.40.0 | Claude API client |
rich | ≥13.0.0 | Terminal formatting, markdown rendering |
prompt_toolkit | ≥3.0.0 | Input history, auto-suggest |
psutil | ≥5.9.0 | System resource monitoring |
fastapi | ≥0.115.0 | Plugin store API server |
uvicorn | ≥0.32.0 | ASGI server for GUI store |
First Run
On first launch, FlowOS presents a plugin setup wizard. You can enable plugins now or skip and manage them later with the plugins command.
python3 flowos.pySessions are persisted to ~/.flowos/sessions/. Resume a previous session:
python3 flowos.py --resumeLaunch the visual plugin store in your browser:
python3 flowos.py --storeThe API key is read from the ANTHROPIC_API_KEY environment variable. Get a key at console.anthropic.com. When booting from the ISO, the key is stored in ~/.flowos/api_key and prompted on first boot.
Booting the ISO
Download the latest flowos.iso from GitHub Releases and flash it to a USB drive.
Flash with Etcher (recommended)
Download Balena Etcher, select flowos.iso, select your USB drive, and click Flash.
Flash with dd (Linux/Mac)
# Linux — replace sdX with your USB device
sudo dd if=flowos.iso of=/dev/sdX bs=4M status=progress && sync
# macOS — replace diskN with your USB disk number
diskutil unmountDisk /dev/diskN
sudo dd if=flowos.iso of=/dev/rdiskN bs=4mBoot sequence
- Restart and select the USB drive from your boot menu (usually F12 or Del)
- GRUB loads — select FlowOS Desktop
- Kernel boots (~3–5 seconds) into the FlowOS banner
- On first boot: enter your Anthropic API key when prompted
- FlowOS CLI launches automatically
FlowOS boots in RAM mode by default — your USB drive is not modified and your hard drive is untouched. Changes made during a session are lost on reboot unless you have a persistent partition.
Built-in Commands
These are handled by the FlowOS shell before being sent to the AI:
| Command | Action |
|---|---|
exit / quit / q | Exit FlowOS |
clear | Reset session and clear screen |
sessions | List and resume past sessions |
plugins | Open interactive plugin toggle menu |
enable <name> | Enable a plugin by name |
disable <name> | Disable a plugin by name |
reload plugins | Reload plugins without restarting |
Everything else is sent to Claude as a user message. The AI decides which tools to call and in what order.
Core Tools
These six tools are always available — no plugin required. Defined in tools.py.
run_command
Execute a shell command and return stdout/stderr.
read_file
Read the contents of a file at a given path.
write_file
Write or overwrite a file. Creates parent directories as needed.
get_system_info
Returns CPU %, memory (used/total/%), disk (used/total/%), and top 5 processes by memory.
list_processes
List running processes, optionally filtered and sorted.
cpu | memory | nameinstall_package
Install a package using the appropriate package manager. Auto-detects snap → brew → apt → pip.
auto | snap | brew | apt | pip | npm | cargoAgent Loop
The run_agent_loop() function in flowos.py drives the multi-turn tool use cycle:
while True:
response = client.messages.create(
model="claude-sonnet-4-5",
tools=all_tools, # core + active plugins
messages=messages
)
for block in response.content:
if block.type == "text":
render_markdown(block.text)
elif block.type == "tool_use":
result = execute_tool(block.name, block.input)
tool_results.append(result)
if response.stop_reason == "end_turn":
break # Claude is done
messages.append(tool_results) # feed results backTool results longer than 3,000 characters are truncated before being added to the message history.
Plugins
Plugins add new tool definitions to the AI. Active plugins are stored in ~/.flowos/plugins.json. Plugin state persists across sessions.
# Enable a plugin
→ enable docker
# Disable a plugin
→ disable weather
# Interactive toggle menu
→ plugins
# Reload without restarting
→ reload pluginsPlugin: git
Git repository management. All commands accept an optional path parameter (defaults to current directory).
| Tool | Description | Key params |
|---|---|---|
git_status | Working tree status | path? |
git_commit | Stage all changes and commit | message, path? |
git_push | Push to remote | path?, branch? |
git_log | Recent commit history | count? (default 10) |
git_diff | Show unstaged or staged changes | staged? |
Plugin: docker
Docker container and image management. Requires Docker to be installed. snap: docker
| Tool | Description | Key params |
|---|---|---|
docker_ps | List containers | all? |
docker_logs | Container logs | container, lines? |
docker_start_stop | Start, stop, or restart a container | container, action |
docker_images | List images | — |
Plugin: ssh
Run commands and transfer files on remote machines over SSH.
| Tool | Description | Key params |
|---|---|---|
ssh_run | Execute command on remote host | host, command, port? |
ssh_copy_file | Copy file via scp | source, destination |
Use user@host format for the host parameter, e.g. matt@192.168.0.169. SSH key auth must be configured; password auth is not supported.
Plugin: browser
Open URLs, search the web, take headless screenshots, and fetch page text. Screenshots require Chromium. snap: chromium
| Tool | Description | Key params |
|---|---|---|
browser_open | Open a URL in the default browser | url |
browser_search | Open a web search | query, engine? |
browser_screenshot | Headless screenshot (Chromium) | url, output? |
browser_fetch | Fetch readable page text | url |
Plugin: spotify
Control Spotify playback. Uses AppleScript on macOS and D-Bus MPRIS on Linux. snap: spotify
| Tool | Description |
|---|---|
spotify_play_pause | Toggle play/pause |
spotify_next | Skip to next track |
spotify_prev | Previous track |
spotify_current | Get current track info |
spotify_volume | Set volume 0–100 |
spotify_open | Open Spotify app |
spotify_search | Search and open results |
Plugin: homeserver
Manage your home server at 192.168.0.169 over SSH. All tools accept an optional host parameter to target a different machine.
| Tool | Description |
|---|---|
server_status | CPU, memory, disk, uptime |
server_services | List running systemd services |
server_logs | journald logs for a service |
server_restart_service | Restart a systemd service |
server_docker_ps | Docker containers on server |
server_docker_logs | Container logs on server |
server_deploy | git pull + docker compose up |
server_snap_list | Installed snaps on server |
server_snap_install | Install snap on server |
server_run | Run arbitrary command on server |
Plugin: notes
Persistent markdown notes stored in ~/.flowos/notes/.
| Tool | Description | Key params |
|---|---|---|
note_save | Save or overwrite a note | title, content |
note_get | Retrieve a note by title (fuzzy) | title |
note_list | List all notes | — |
note_delete | Delete a note | title |
Plugin: weather
Current conditions and 3-day forecast via wttr.in. No API key required.
| Tool | Description | Key params |
|---|---|---|
weather_now | Current weather | location? (auto-detect if blank) |
weather_forecast | 3-day forecast | location? |
Plugin: clipboard
Read and write the system clipboard. Uses pbcopy/pbpaste on macOS and xclip on Linux.
| Tool | Description |
|---|---|
clipboard_read | Read clipboard contents |
clipboard_write | Write text to clipboard |
Writing a Plugin
Create a file in plugins/ that subclasses Plugin, then register it in plugin_manager.py.
# plugins/hello_plugin.py
from plugins.base import Plugin
class HelloPlugin(Plugin):
name = "hello"
description = "Greets people and tells the time"
version = "1.0.0"
@classmethod
def tool_definitions(cls):
return [{
"name": "say_hello",
"description": "Greet someone by name",
"input_schema": {
"type": "object",
"properties": {
"name": {"type": "string", "description": "Person's name"}
},
"required": ["name"]
}
}]
@classmethod
def tool_handlers(cls):
return {
"say_hello": lambda name: f"Hello, {name}!"
}Then register it in plugin_manager.py:
AVAILABLE_PLUGINS = {
# ... existing plugins ...
"hello": ("plugins.hello_plugin", "HelloPlugin", "Greets people"),
}Enable it:
→ enable helloPlugin API Reference
Plugin base class
| Attribute / Method | Type | Description |
|---|---|---|
name | str | Unique plugin identifier. Used in CLI commands. |
description | str | Short description shown in the plugin store and wizard. |
version | str | Semver version string. Default: "1.0.0". |
requires | list | pip packages to install. Currently informational only. |
tool_definitions() | list[dict] | Returns Anthropic tool definition objects. |
tool_handlers() | dict[str, callable] | Maps tool name → handler function. Handler receives tool input as kwargs. |
on_load() | None | Called once when the plugin is activated. Use for setup/validation. |
Tool definition schema
{
"name": "tool_name", # snake_case, globally unique
"description": "...", # Claude reads this to decide when to call the tool
"input_schema": {
"type": "object",
"properties": {
"param": {
"type": "string", # string | integer | boolean | array
"description": "...",
"enum": ["a", "b"] # optional: constrain to values
}
},
"required": ["param"] # omit for optional params
}
}Tool handler return values are converted to strings. Returning None produces "Done.". Values longer than 3,000 characters are truncated before being fed back to Claude.
ISO Build Guide
Build a bootable flowos.iso using Docker. Works on macOS and Linux.
Prerequisites
- Docker Desktop (macOS) or Docker Engine (Linux)
- ~3 GB free disk space for the build cache
- Internet connection (downloads Alpine packages)
Build
git clone https://github.com/Mattjhagen/FlowOS-Project-Aquarius.git
cd FlowOS-Project-Aquarius
./iso/build.shOutput: dist/flowos.iso. First build takes 10–15 minutes. Subsequent builds use Docker layer cache.
# Force full rebuild (clears cache)
./iso/build.sh --no-cacheISO Internals
Boot sequence
Build scripts
| Script | Purpose |
|---|---|
iso/build.sh | Orchestrator. Runs Docker build, extracts ISO to dist/. |
iso/Dockerfile | Multi-stage Alpine build. Runs all three scripts below. |
iso/scripts/build-rootfs.sh | Bootstraps Alpine into /build/rootfs, installs Python + FlowOS deps, copies source, configures users and OpenRC. |
iso/scripts/build-initramfs.sh | Creates a minimal cpio initramfs with busybox + squashfs/overlay/loop kernel modules. |
iso/scripts/create-iso.sh | Runs mksquashfs on the rootfs, installs GRUB (BIOS + EFI), creates hybrid ISO with xorriso. |
iso/initramfs/init | The /init script inside the initramfs. Mounts ISO → squashfs → overlayfs → switch_root. |
GUI Store API
The plugin store runs a FastAPI server on port 7070. Launch it with:
python3 flowos.py --storeEndpoints
| Method | Path | Description |
|---|---|---|
| GET | / | Serves gui/store.html |
| GET | /api/plugins | List all plugins with name, description, enabled, category, snap |
| POST | /api/plugins/{name}/enable | Enable a plugin |
| POST | /api/plugins/{name}/disable | Disable a plugin |
| GET | /api/system | CPU %, memory %, disk %, plugin counts |
| POST | /api/launch | Open FlowOS CLI in a new terminal window |
The store UI polls /api/system every 8 seconds for live system stats. Plugin toggles update ~/.flowos/plugins.json immediately — changes take effect on the next FlowOS CLI launch or reload plugins.