Using Marbles
Explore the capabilities you can combine in a local automation.
Once you have run one step, you can add capabilities independently. These examples introduce each one; Foundation explains how their definitions, instances, and contexts fit together.
Run once or keep running
Use marbles roll <name> for one result. Use marbles and press Enter to
open the dashboard and start schedules and monitors. The dashboard also
lets you launch work and answer questions. A schedule declared in a file
needs a running Marbles process to execute.
For a local unattended loop, marbles run </dev/null starts immediately
with plain output. It cannot answer questions. See CLI modes.
Launch work from an MCP client
The source-checkout MCP server lets an external
agent discover your definitions and start work over STDIO. Use
dispatch_workflow for a named workflow or step, or dispatch_agent for
agent work. Both return a runId without waiting for completion.
Follow either run in one CLI call:
marbles watch <runId>
Keep the MCP server connected while work runs. The watcher replays output already produced, follows new output, and exits when the run finishes. CLI reference covers exit codes, state selection, and interruption.
Give work input
Install the schema library in your project:
bun add zod@4.4.3
Save this as .foundry/marbles/count.ts:
import { step } from "@foundry.sh/marbles";
import { z } from "zod";
step("count")
.input(z.object({ extension: z.string() }))
.do(async ({ input, workspaces }) => {
const files = await workspaces.current.files();
return {
extension: input.extension,
files: files.filter((file) => file.path.endsWith(input.extension)).length,
};
});
Run marbles roll count --input '{"extension":".ts"}'. The schema validates
input and supplies its TypeScript type. Schemas exposing Standard JSON
Schema also describe the dashboard’s input form; other schemas use a JSON
field. Input and output.
Run commands
A step can be one command:
import { step } from "@foundry.sh/marbles";
step("test-project").exec("bun test");
Use this in a project with Bun tests. Run marbles roll test-project and
inspect its exit code and output. A nonzero exit fails the step. Commands
also work inside .do() through exec. Execution context.
Connect steps into workflows
A workflow connects steps through their inputs and results. Run dependent work in order and independent work in parallel. For example, collect test results and review findings before producing a report.
Composition builds a small working tree. Software Factory applies the same model to implementation, verification, and approval.
The Workflows runtime records results for both commands and agent work. Durability covers waiting, retries, and restarts.
Work with projects and sandboxes
workspaces.current reads your project. workspace({ path: "../other-project" })
declares another directory. Git worktree callbacks give a task its own
checkout; commands and agent sessions opened inside inherit that location.
These operations come from Workspaces.
sandbox(...) declares an isolated execution environment, which starts on
use. Choose its mounts, network access, and resources explicitly. The sandbox
runtime is optional. Workspaces and sandboxes.
The Sandbox library
supplies the underlying file, command, and container interfaces.
Add an agent and keep its conversation
With an installed, authenticated Claude Code or Codex CLI, save this as
.foundry/marbles/explain.ts:
import { agent, step } from "@foundry.sh/marbles";
const guide = agent({ prompt: "Explain this project without editing files." });
step("explain").do(async ({ agents }) => {
const session = await agents.session(guide);
return (await session.generate("What are the main parts of this project?"))
.text;
});
Run marbles roll explain. Use a session for multiple turns; keep its
session.ref to continue it in a later run. Skills add reusable instructions
and files. Agents and sessions.
Agents keeps the conversation; Models resolves the provider and model. Marbles gives their execution the owning step’s stream, cancellation, and retry policy.
For a ready-made starting point, marbles init developer creates a review
module. init without a choice creates a project summary. These are optional
starters; project setup lists them.
Ask a person and publish results
ask.approval(...) and ask.question(...) pause a step for a dashboard
answer. report.result({ title, body }) posts a readable result to the Feed.
report.artifact(definition, files, { body }) saves versioned files and posts
the supplied body to the Feed with a reference to that version. Use
artifact(...).write(...) for saved state that needs no Feed announcement.
Use the dashboard for work that asks questions. A one-shot roll or an
unattended loop cancels at an ask. Contexts
explains these operations; human approval
puts them together.
Versioned outputs use Artifacts. Artifacts and results explains when to return a value, post a message, or save files for a later run.
Schedule work and react to changes
Save this complete module as .foundry/marbles/heartbeat.ts:
import { monitor, schedule, step } from "@foundry.sh/marbles";
const heartbeat = step("heartbeat").do(({ log }) => {
log("Marbles is running");
return { alive: true };
});
schedule(heartbeat).every("30s");
monitor("**/*.md")
.every("30s")
.do(({ files, log }) => log(files));
Open marbles, press Enter, and wait for a tick. The step logs every 30
seconds while the loop is active. The monitor reports existing Markdown
files on its first poll, then changes on later polls. HTTP monitors use the
same pattern for a URL. Schedules and monitors.
Choose a use case
| Build | Combine |
|---|---|
| Software Factory | Issues, work logs, implementation, review, delivery, and on-call reports. |
| Evaluations | Model comparisons, skill checks, and feedback from file changes. |
| Design | Briefs, wireframes, design iterations, and token maintenance. |
Continue with Foundation to understand the model behind these capabilities. See safety and limits when running agent work or unfamiliar modules.