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.

User input Claude (tool use) System tools Result
flowos.py ─── Core CLI loop + session management
tools.py ─── 6 core system tools (shell, file, process…)
plugin_manager─── Plugin loading, config, setup wizard
plugins/ ─── 9 optional plugins (git, docker, ssh…)
gui/server.py ─── FastAPI plugin store (port 7070)
iso/ ─── Alpine-based bootable ISO build system

Project links

ResourceURL
Source codegithub.com/Mattjhagen/FlowOS-Project-Aquarius
Download ISOprojectaquarius.space
Documentationflowos.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.py

Dependencies

PackageVersionPurpose
anthropic≥0.40.0Claude API client
rich≥13.0.0Terminal formatting, markdown rendering
prompt_toolkit≥3.0.0Input history, auto-suggest
psutil≥5.9.0System resource monitoring
fastapi≥0.115.0Plugin store API server
uvicorn≥0.32.0ASGI 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.py

Sessions are persisted to ~/.flowos/sessions/. Resume a previous session:

python3 flowos.py --resume

Launch the visual plugin store in your browser:

python3 flowos.py --store

The 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=4m

Boot sequence

  1. Restart and select the USB drive from your boot menu (usually F12 or Del)
  2. GRUB loads — select FlowOS Desktop
  3. Kernel boots (~3–5 seconds) into the FlowOS banner
  4. On first boot: enter your Anthropic API key when prompted
  5. 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:

CommandAction
exit / quit / qExit FlowOS
clearReset session and clear screen
sessionsList and resume past sessions
pluginsOpen interactive plugin toggle menu
enable <name>Enable a plugin by name
disable <name>Disable a plugin by name
reload pluginsReload 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.

commandstringrequired — the shell command to run
working_dirstringoptional — directory to run in (default: home)

read_file

Read the contents of a file at a given path.

pathstringrequired — absolute or relative file path

write_file

Write or overwrite a file. Creates parent directories as needed.

pathstringrequired
contentstringrequired

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.

filterstringoptional — filter by process name
sort_byenumoptionalcpu | memory | name

install_package

Install a package using the appropriate package manager. Auto-detects snap → brew → apt → pip.

packagestringrequired
managerenumoptionalauto | snap | brew | apt | pip | npm | cargo

Agent 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 back

Tool 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 plugins

Plugin: git

Git repository management. All commands accept an optional path parameter (defaults to current directory).

ToolDescriptionKey params
git_statusWorking tree statuspath?
git_commitStage all changes and commitmessage, path?
git_pushPush to remotepath?, branch?
git_logRecent commit historycount? (default 10)
git_diffShow unstaged or staged changesstaged?

Plugin: docker

Docker container and image management. Requires Docker to be installed. snap: docker

ToolDescriptionKey params
docker_psList containersall?
docker_logsContainer logscontainer, lines?
docker_start_stopStart, stop, or restart a containercontainer, action
docker_imagesList images

Plugin: ssh

Run commands and transfer files on remote machines over SSH.

ToolDescriptionKey params
ssh_runExecute command on remote hosthost, command, port?
ssh_copy_fileCopy file via scpsource, 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

ToolDescriptionKey params
browser_openOpen a URL in the default browserurl
browser_searchOpen a web searchquery, engine?
browser_screenshotHeadless screenshot (Chromium)url, output?
browser_fetchFetch readable page texturl

Plugin: spotify

Control Spotify playback. Uses AppleScript on macOS and D-Bus MPRIS on Linux. snap: spotify

ToolDescription
spotify_play_pauseToggle play/pause
spotify_nextSkip to next track
spotify_prevPrevious track
spotify_currentGet current track info
spotify_volumeSet volume 0–100
spotify_openOpen Spotify app
spotify_searchSearch 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.

ToolDescription
server_statusCPU, memory, disk, uptime
server_servicesList running systemd services
server_logsjournald logs for a service
server_restart_serviceRestart a systemd service
server_docker_psDocker containers on server
server_docker_logsContainer logs on server
server_deploygit pull + docker compose up
server_snap_listInstalled snaps on server
server_snap_installInstall snap on server
server_runRun arbitrary command on server

Plugin: notes

Persistent markdown notes stored in ~/.flowos/notes/.

ToolDescriptionKey params
note_saveSave or overwrite a notetitle, content
note_getRetrieve a note by title (fuzzy)title
note_listList all notes
note_deleteDelete a notetitle

Plugin: weather

Current conditions and 3-day forecast via wttr.in. No API key required.

ToolDescriptionKey params
weather_nowCurrent weatherlocation? (auto-detect if blank)
weather_forecast3-day forecastlocation?

Plugin: clipboard

Read and write the system clipboard. Uses pbcopy/pbpaste on macOS and xclip on Linux.

ToolDescription
clipboard_readRead clipboard contents
clipboard_writeWrite 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 hello

Plugin API Reference

Plugin base class

Attribute / MethodTypeDescription
namestrUnique plugin identifier. Used in CLI commands.
descriptionstrShort description shown in the plugin store and wizard.
versionstrSemver version string. Default: "1.0.0".
requireslistpip 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()NoneCalled 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.sh

Output: dist/flowos.iso. First build takes 10–15 minutes. Subsequent builds use Docker layer cache.

# Force full rebuild (clears cache)
./iso/build.sh --no-cache

ISO Internals

Boot sequence

BIOS/UEFI → GRUB (grub/grub.cfg)
→ kernel (vmlinuz) + initrd (initrd.img)
initramfs/init → scan for ISO device (cdrom/usb)
→ mount iso9660 → mount squashfs (rootfs.squashfs)
→ tmpfs overlayfs (makes rootfs writable)
→ switch_root → /sbin/init (OpenRC)
OpenRC → networking → auto-login (inittab → agetty --autologin flowos)
/home/flowos/.profile → API key prompt (first boot) → FlowOS CLI

Build scripts

ScriptPurpose
iso/build.shOrchestrator. Runs Docker build, extracts ISO to dist/.
iso/DockerfileMulti-stage Alpine build. Runs all three scripts below.
iso/scripts/build-rootfs.shBootstraps Alpine into /build/rootfs, installs Python + FlowOS deps, copies source, configures users and OpenRC.
iso/scripts/build-initramfs.shCreates a minimal cpio initramfs with busybox + squashfs/overlay/loop kernel modules.
iso/scripts/create-iso.shRuns mksquashfs on the rootfs, installs GRUB (BIOS + EFI), creates hybrid ISO with xorriso.
iso/initramfs/initThe /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 --store

Endpoints

MethodPathDescription
GET/Serves gui/store.html
GET/api/pluginsList all plugins with name, description, enabled, category, snap
POST/api/plugins/{name}/enableEnable a plugin
POST/api/plugins/{name}/disableDisable a plugin
GET/api/systemCPU %, memory %, disk %, plugin counts
POST/api/launchOpen 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.