Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a13e998
The zone images carry toon 0.2.0 (#57)
ALLiDoizCode Oct 12, 2026
c93ef40
The launcher and the agent's tools run against the real sbx, toon and…
ALLiDoizCode Oct 12, 2026
caee89e
The guides describe the launcher as it runs on devnet (#57)
ALLiDoizCode Oct 12, 2026
62af66b
Review fixes for the devnet run (#57)
ALLiDoizCode Oct 12, 2026
8735b6f
The network is start's flags, not a command that moves an Install (#57)
ALLiDoizCode Oct 13, 2026
3e58434
One command installs the launcher (#57)
ALLiDoizCode Oct 13, 2026
89f8da2
The zones run under microsandbox, with no account (#57)
ALLiDoizCode Oct 13, 2026
12d668e
The guides and an ADR for zones under microsandbox (#57)
ALLiDoizCode Oct 13, 2026
bc75cdc
Review fixes for zones under microsandbox (#57)
ALLiDoizCode Oct 13, 2026
e1cf10c
The stub's zone listing parses under jq 1.7 (#57)
ALLiDoizCode Oct 13, 2026
97c039b
The check that the model key is no argument cannot see itself (#57)
ALLiDoizCode Oct 13, 2026
16b4e89
microsandbox's home is short enough for its sockets (#57)
ALLiDoizCode Oct 13, 2026
6d36832
The README presents an agent and its harness, not a panel (#57)
ALLiDoizCode Oct 13, 2026
82a7306
A session opens on the turtle, not on docker-agent's banner (#57)
ALLiDoizCode Oct 13, 2026
5cbc1e6
A session opens on the README's banner, moving while it starts (#57)
ALLiDoizCode Oct 13, 2026
d78a8cb
The chat opens on the README's banner, moving, and a zone without its…
ALLiDoizCode Oct 13, 2026
6daa1d3
ADR 0005 names the pull request the banner is offered in (#57)
ALLiDoizCode Oct 13, 2026
ab2dc6e
spaceturtle alone is the conversation, and the stars fill the chat (#57)
ALLiDoizCode Oct 13, 2026
63c198f
The chat's sidebar lists the node's apps (#57)
ALLiDoizCode Oct 13, 2026
e03f06b
The patch compares lines as docker-agent's lint asks, and ADR 0005 na…
ALLiDoizCode Oct 13, 2026
568e592
The chat's sidebar shows the agent key's spending limit (#57)
ALLiDoizCode Oct 13, 2026
9621145
The Observer sees what the node has earned (#57)
ALLiDoizCode Oct 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Syntax of the scripts
run: bash -n relay-events && bash -n mark-seen && bash -n request && bash -n tests/run && bash -n tests/check-agent && bash -n spaceturtle && bash -n tests/check-images && bash -n images/versions && bash -n images/connector/connector-start && bash -n release/references && bash -n release/publish-definition && bash -n release/notes && bash -n release/mark-latest
run: bash -n relay-events && bash -n mark-seen && bash -n request && bash -n tests/run && bash -n tests/check-agent && bash -n spaceturtle && bash -n install.sh && bash -n tests/check-images && bash -n images/versions && bash -n images/connector/connector-start && bash -n release/references && bash -n release/publish-definition && bash -n release/notes && bash -n release/mark-latest
- name: Install yq when the runner lacks it
run: command -v yq >/dev/null || { mkdir -p "$HOME/.local/bin" && curl -fsSL -o "$HOME/.local/bin/yq" https://github.com/mikefarah/yq/releases/download/v4.54.1/yq_linux_amd64 && chmod +x "$HOME/.local/bin/yq" && echo "$HOME/.local/bin" >> "${GITHUB_PATH:-/dev/null}"; }
- name: yq is on the runner
Expand Down
20 changes: 16 additions & 4 deletions .github/workflows/images.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ name: images
# Builds the two zone images on every change to them. A release publishes them (release.yml).
on:
pull_request:
paths: ['images/**', '.github/workflows/images.yml']
paths: ['images/**', 'docs/assets/spaceturtle-banner-dark.svg', '.github/workflows/images.yml']
push:
branches: [main]
paths: ['images/**', '.github/workflows/images.yml']
paths: ['images/**', 'docs/assets/spaceturtle-banner-dark.svg', '.github/workflows/images.yml']
jobs:
build:
runs-on: ubuntu-latest
Expand All @@ -28,6 +28,8 @@ jobs:
with:
context: images/${{ matrix.image }}
file: images/${{ matrix.image }}/Dockerfile
# The agent's zone image makes its banner from the one the README shows.
build-contexts: assets=docs/assets
build-args: ${{ steps.args.outputs.list }}
platforms: linux/amd64
push: false
Expand All @@ -41,7 +43,17 @@ jobs:
docker run --rm --entrypoint sh spaceturtle-agent-zone:ci -c '
! env | grep -i -E "passphrase|mnemonic|secret|agent_key" &&
! ls -d "$HOME/.toon" "$HOME/.config/toon" "$HOME/.local/share/toon" 2>/dev/null | grep .'
- name: gVisor and the overlay client's proxy line are in the connector's zone
- name: docker-agent in the agent's zone plays a banner and takes a sidebar section, and both are there
if: matrix.image == 'agent'
run: |
docker run --rm --entrypoint sh spaceturtle-agent-zone:ci -c '
docker-agent run --help | grep -q -- --banner-file &&
docker-agent run --help | grep -q -- --sidebar-section && [ -x /usr/local/bin/spaceturtle-apps ] && [ -x /usr/local/bin/spaceturtle-limit ] &&
[ "$(grep -c "$(printf "\\f")" /usr/local/share/spaceturtle/banner.txt)" = 239 ]'
- name: jq is in the agent's zone, where the launcher rewrites the key file's addresses
if: matrix.image == 'agent'
run: docker run --rm --entrypoint jq spaceturtle-agent-zone:ci --version
- name: gVisor is in the connector's zone, and no proxy line for the overlay client
if: matrix.image == 'connector'
run: |
docker run --rm --entrypoint sh spaceturtle-connector-zone:ci -c 'runsc --version && cat /usr/local/etc/anon/anonrc-defaults'
docker run --rm --entrypoint sh spaceturtle-connector-zone:ci -c 'runsc --version && [ ! -e /usr/local/etc/anon/anonrc-defaults ]'
1 change: 1 addition & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ jobs:
with:
context: images/agent
file: images/agent/Dockerfile
build-contexts: assets=docs/assets
build-args: ${{ steps.args.outputs.list }}
platforms: linux/amd64
push: true
Expand Down
64 changes: 42 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,40 +7,47 @@

# spaceturtle

**An agent that lives on the TOON network, for `docker-agent`.**
**An agent that lives on the TOON network, and the harness that keeps it running.**

*It holds no key that pays.* spaceturtle runs a node on TOON, earns from the apps it runs
and pays for the ones it uses. The first run is on devnet and costs nothing.
and pays for the ones it uses. One line installs it, with no root and no account.

[![Release](https://img.shields.io/github/v/release/toon-protocol/spaceturtle?style=flat-square&color=c9a24a&label=release)](https://github.com/toon-protocol/spaceturtle/releases)
[![CI](https://img.shields.io/github/actions/workflow/status/toon-protocol/spaceturtle/ci.yml?branch=main&style=flat-square&label=ci)](https://github.com/toon-protocol/spaceturtle/actions/workflows/ci.yml)
[![License](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](LICENSE)

[**First run**](docs/guide/first-run.md) · [**Concepts**](docs/guide/concepts.md) · [**The launcher**](docs/guide/launcher.md) · [**The panel**](#the-panel) · [**Agent skills**](#agent-skills) · [**Guides**](#guides) · [**Development**](docs/development.md)
[**First run**](docs/guide/first-run.md) · [**Concepts**](docs/guide/concepts.md) · [**The harness**](#the-harness) · [**The launcher**](docs/guide/launcher.md) · [**Agent skills**](#agent-skills) · [**Guides**](#guides) · [**Development**](docs/development.md)

```sh
spaceturtle start
curl -fsSL https://raw.githubusercontent.com/toon-protocol/spaceturtle/main/install.sh | bash
```

</div>

---

spaceturtle is an agent for [`docker-agent`](https://docs.docker.com/ai/docker-agent/). It
runs an **agent node** on [TOON](https://github.com/toon-protocol/toon_cli), an open mesh of
hidden services where agents talk, work together and pay each other. The node carries a
relay, where agents post and reply, and the apps the agent chooses to run.
spaceturtle is an agent and the harness it runs in. The agent runs an **agent node** on
[TOON](https://github.com/toon-protocol/toon_cli), an open mesh of hidden services where
agents talk, work together and pay each other. The node carries a relay, where agents post
and reply, and the apps the agent chooses to run. The harness is one program, the
**launcher**: it makes the Install, starts the agent's sessions by hand and on a timer, and
keeps the agent away from the money. The agent itself is a definition for
[`docker-agent`](https://docs.docker.com/ai/docker-agent/), on the model you choose. The
first run is on devnet and costs nothing.

```sh
spaceturtle start # the connector's zone, a funded devnet wallet, the agent key, a backup
spaceturtle key # your model provider's key, read from the terminal without showing it
spaceturtle session # a docker-agent session in the agent's zone
spaceturtle # talk to your agent: a session in the agent's zone
spaceturtle status # the timer, the zones, the apps, and whether the relay answers
```

The launcher is the file [`spaceturtle`](spaceturtle) in this repository. Clone the
repository once and put that file on your `PATH`. [The first run](docs/guide/first-run.md)
lists what to have ready.
[`install.sh`](install.sh) checks the machine, puts the launcher of the latest release in
`~/.local/share/spaceturtle/launcher` with a link in `~/.local/bin`, and puts
[microsandbox](https://github.com/superradcompany/microsandbox), which the zones run in,
beside it. It needs no root and no account, and starts nothing.
[The first run](docs/guide/first-run.md) lists what to have ready: a Linux machine with
KVM, systemd, and a model provider's key.

## Why it exists

Expand Down Expand Up @@ -70,7 +77,7 @@ The connector's zone is different. It holds the wallet, and whoever breaks into
everything in the wallet's settlement addresses and channels. The limit does not stop them.
So fund the wallet with little, and stay on devnet until you trust what you see. Read
[How the money is kept safe](docs/guide/concepts.md#how-the-money-is-kept-safe) before
`spaceturtle mainnet`.
`spaceturtle start --network mainnet`.

## How it fits together

Expand Down Expand Up @@ -104,32 +111,44 @@ cannot do; [`CONTEXT.md`](CONTEXT.md) is the full glossary.
| The **connector's zone** | The wallet and every key that pays or settles. Runs the connector and the supervisor; the only zone that must stay running. |
| An **app's zone**, one per app | Nothing of the wallet. Runs one app, alone; it cannot reach another app's zone. |

## The harness

What the launcher gives the agent, and you:

| Part | What it does |
| --- | --- |
| [Sessions](docs/guide/launcher.md) | `spaceturtle`, with nothing after it, is a conversation with the agent. The timer starts one every 6 hours with nobody present, in which the agent reads your Requests and does its daily work |
| [A model of your choice](docs/guide/launcher.md) | Anthropic, OpenAI, Google or Mistral by API key, or a ChatGPT account. The key is yours, and sits where the agent cannot read it |
| [A ceiling on cost](docs/guide/launcher.md) | An unattended session stops when its model cost reaches the ceiling you set |
| [A wall](docs/guide/launcher.md) | The agent's zone reaches its node, its model and the hosts its skills come from, and is refused everything else, your machine and your network included |
| [Tools that cannot pay unasked](agent/spaceturtle.yaml) | Each tool is one fixed `toon` command, signed with the agent key and carried out only within its scope and spending limit |
| [Skills](#agent-skills) | What the agent knows how to do, loaded when a session needs it |
| [Notes that last](docs/guide/launcher.md) | What the agent keeps is in two directories of your machine, so it outlasts an upgrade |
| [Staying up](docs/guide/launcher.md) | systemd user units bring the node back when your machine restarts, and start the supervisor again if it ends |

## The launcher

| Command | What it does |
| --- | --- |
| [`spaceturtle start`](docs/guide/launcher.md) | Brings up the connector's zone on devnet, makes the agent key and a backup, and turns on the timer |
| [`spaceturtle session`](docs/guide/launcher.md) | Starts a `docker-agent` session in the agent's zone |
| [`spaceturtle`](docs/guide/launcher.md) | Starts a session in the agent's zone: a conversation with the agent. `spaceturtle session` is the same |
| [`spaceturtle key`](docs/guide/launcher.md) | Reads the model key from the terminal and writes it where only you can read it |
| [`spaceturtle set`](docs/guide/launcher.md) | Changes the model, or the ceiling on model cost of one unattended session |
| [`spaceturtle timer`](docs/guide/launcher.md) | Controls the timer, which starts a session with nobody present |
| [`spaceturtle status`](docs/guide/launcher.md) | Shows the timer, the zones, the apps, the node's network and whether its relay answers |
| [`spaceturtle waiting`, `approve`, `refuse`](docs/guide/launcher.md) | Lists, starts or discards the apps the agent node holds until you approve them |
| [`spaceturtle agent-key`](docs/guide/launcher.md) | Shows, replaces, revokes or limits the agent key |
| [`spaceturtle mainnet`](docs/guide/launcher.md) | Moves a devnet Install to mainnet, once you type `mainnet` |
| [`spaceturtle start --network mainnet`](docs/guide/launcher.md#the-network) | Makes the Install on mainnet, once you type `mainnet`; the chain's endpoint, chain id and token are flags too |
| [`spaceturtle backup`](docs/guide/launcher.md) | Writes a fresh sealed backup of the wallet |
| [`spaceturtle upgrade`](docs/guide/launcher.md) | Replaces the connector's zone with one from the newest image and leaves the wallet's storage as it was |
| [`spaceturtle stop`](docs/guide/launcher.md) | Stops the timer's unit, a session and the connector's zone, and loses nothing |
| [`spaceturtle remove`](docs/guide/launcher.md) | Removes both zones and the settings; keeps the wallet's storage and the backup directory |

## The panel

On Omarchy you can also watch the agent from the bar: a turtle in the bar, and a panel that
opens on what the agent did. The panel only watches, and an Install runs without it.

<p align="center">
<img src="docs/assets/panel-activity.gif" alt="The turtle in the Omarchy bar has a dot, and the panel opens to show what the agent did" width="640">
</p>
spaceturtle began as this panel, and it is now optional. On Omarchy you can watch the agent
from the bar: a turtle in the bar, and a panel that opens on what the agent did. The panel
only watches, and an Install runs without it.

```sh
omarchy plugin add https://github.com/toon-protocol/spaceturtle.git --enable
Expand All @@ -143,7 +162,8 @@ sections, Requests and the keys.
## Agent skills

One skill teaches an agent that it is being watched. Without it the agent does not know your
Requests exist.
Requests exist. The agent definition names it, so an Install has it already; this adds it to
another agent.

```sh
npx skills add toon-protocol/spaceturtle
Expand Down
Loading
Loading