Skip to main content

HELLO WORLD

In this tutorial, we will install swamp, initialize a repository, then use Claude Code to create models, extend swamp with new functionality, and run a workflow.

What we will build

We are going to set up a swamp project, ask Claude Code to create a model called hello-world, run it, then add a random weather report and wire everything into a workflow.

Install swamp

Open your terminal and run:

$ curl -fsSL https://swamp.club/install.sh | sh

Once it finishes, verify the installation:

$ swamp version

You should see output like:

info    version              swamp "20260206.200442.0-sha...."

If the command is not found, restart your shell or add ~/.local/bin to your PATH.

Initialize a repository

Create a new directory and initialize it as a swamp repo:

$ mkdir my-swamp-project
$ cd my-swamp-project
$ swamp repo init

You will see the swamp banner:

    ███████╗██╗    ██╗ █████╗ ███╗   ███╗██████╗
    ██╔════╝██║    ██║██╔══██╗████╗ ████║██╔══██╗
    ███████╗██║ █╗ ██║███████║██╔████╔██║██████╔╝
    ╚════██║██║███╗██║██╔══██║██║╚██╔╝██║██╔═══╝
    ███████║╚███╔███╔╝██║  ██║██║ ╚═╝ ██║██║
    ╚══════╝ ╚══╝╚══╝ ╚═╝  ╚═╝╚═╝     ╚═╝╚═╝

    ╔═══════════════════════════════════════════╗
    ║  WELCOME TO THE CLUB                      ║
    ║  for hackers, by hackers                  ║
    ╚═══════════════════════════════════════════╝

info    repo·init            Initialized swamp repository at "..." (tool: "claude")

Notice what swamp created:

$ ls -a
.  ..  .claude  CLAUDE.md  .gitignore  models  .swamp  .swamp.yaml  vaults  workflows

Notice the .claude/ directory and CLAUDE.md file — these are what let Claude Code work with swamp automatically. The .swamp/ directory is where all versioned data will be stored.

Create a model with Claude Code

Note

You will need an AI Agent to work with Swamp. This tutorial assumes you will use Claude Code, but you can use any agent you like.

Open Claude Code in your project directory in a new terminal. Since we ran swamp repo init, Claude Code already has the swamp skills loaded. Ask it:

Create a model called hello-world that echoes "Hello from the swamp!"

Claude Code will create the model. You will see it create a file under models/command/shell/ with the echo command configured.

Run the model

Back in your terminal, run the model:

$ swamp model method run hello-world execute

You will see output like:

info    model·method·run·hello-world·execute Found model "hello-world" ("command/shell")
info    model·method·run·hello-world·execute Evaluating expressions
info    model·method·run·hello-world·execute Executing method "execute"
info    model·method·run·hello-world·execute Hello from the swamp!
info    model·method·run·hello-world·execute Data saved to ".swamp/data/..."
info    model·method·run·hello-world·execute Data saved to ".swamp/data/..."
info    model·method·run·hello-world·execute Running report: "@swamp/method-summary"
── Report: @swamp/method-summary ──────────────────────────────────────
# hello-world (command/shell) → execute: succeeded

execute on hello-world (command/shell) succeeded, producing 1 resource
(result), 1 file (log).

## Data Output

┌────────┬──────────┬───────────────────────────────────────────────┐
│ Name   │ Kind     │ Retrieval Command                             │
├────────┼──────────┼───────────────────────────────────────────────┤
│ result │ resource │ swamp data get hello-world result --version 1 │
├────────┼──────────┼───────────────────────────────────────────────┤
│ log    │ file     │ swamp data get hello-world log --version 1    │
└────────┴──────────┴───────────────────────────────────────────────┘

───────────────────────────────────────────────────────────────────────
info    model·method·run·hello-world·execute Method "execute" completed
                                             on "hello-world"

Notice the Hello from the swamp! line in the output, and the method summary report listing the data that was saved.

Query the stored data

Now query the data that swamp stored:

$ swamp data query 'modelName == "hello-world"'

You will see output like:

┌────────┬─────────────┬──────────┬──────────┬─────────┬──────┐
│ name   │ modelName   │ specName │ dataType │ version │ size │
├────────┼─────────────┼──────────┼──────────┼─────────┼──────┤
│ log    │ hello-world │ log      │ file     │ 1       │ 30B  │
├────────┼─────────────┼──────────┼──────────┼─────────┼──────┤
│ result │ hello-world │ result   │ resource │ 1       │ 155B │
└────────┴─────────────┴──────────┴──────────┴─────────┴──────┘

2 results

Notice the two data artifacts — result and log — matching what the method summary reported.

Now query just the stdout from the result:

$ swamp data query \
    'modelName == "hello-world" && specName == "result"' \
    --select 'attributes.stdout'

You will see output like:

Hello from the swamp!

Compose a workflow

Now we will add a weather report and wire everything into a workflow. Ask Claude Code:

Create a new extension model type named @tutorial/random-status
that randomly returns one of a list of statuses. The extension
should store the selected status in a resource named "output"
with a "status" property. Then create a model called
weather-report that uses it to return one of: murky, misty,
gloomy, stinky and humid. Then create a model called
morning-message that takes the hello-world stdout and the
weather-report status as inputs and echoes "{hello world} The
weather is {status} - best to stay inside." Create a workflow
called swamp-morning with two jobs: a "gather" job that runs
hello-world and weather-report, and a "combine" job that
depends on gather and runs morning-message.

Notice that we asked for functionality that does not exist yet — random weather selection. Claude Code will create the extension, the models, and the workflow. You will see new files appear under extensions/, models/, and workflows/.

Run the workflow

Back in your terminal:

$ swamp workflow run swamp-morning

You will see output like:

gather                                                          ✓2 steps
│ [hello-world → execute]
│ Hello from the swamp!
...
│ [weather-report → run]
...
combine                                                         ✓morning-message → execute
│ Hello from the swamp! The weather is gloomy - best to stay inside.
...
── @swamp/workflow-summary ─────────────────────────────────
# swamp-morning: succeeded

3 succeeded · 0 failed · 0 skipped

## Job: gather (succeeded)

┌────────────────┬───────────────────────┬───────────┐
│ Step           │ Model                 │ Status    │
├────────────────┼───────────────────────┼───────────┤
│ weather-report │ weather-report → run  │ succeeded │
├────────────────┼───────────────────────┼───────────┤
│ hello-world    │ hello-world → execute │ succeeded │
└────────────────┴───────────────────────┴───────────┘

## Job: combine (succeeded)

┌─────────────────┬───────────────────────────┬───────────┐
│ Step            │ Model                     │ Status    │
├─────────────────┼───────────────────────────┼───────────┤
│ morning-message │ morning-message → execute │ succeeded │
└─────────────────┴───────────────────────────┴───────────┘

Notice that gather ran hello-world and weather-report in parallel, then combine ran after both succeeded. The weather status will be different each time you run the workflow.

Query the final result

$ swamp data query \
    'modelName == "morning-message" && specName == "result"' \
    --select 'attributes.stdout'

You will see output like:

Hello from the swamp! The weather is misty - best to stay inside.

You have installed swamp, created models with Claude Code, composed them into a workflow with dependencies, and queried the stored results. Every execution is versioned data in .swamp/.