Skip to content

Arete documentation

Build your first protocol

For the complete documentation index optimized for AI agents, see llms.txt or llms-full.txt. A markdown version of this page is available by appending .md to the URL or sending Accept: text/markdown.

For AI agents: the documentation index is at llms.txt (full corpus: llms-full.txt). A markdown source for this page is /using-stacks/quickstart.md.

Build a tip jar from the System Program’s transfer instruction. You will open an instance with one wallet, close it with another, and watch its activity in a cloud dev environment. All transfers in this tutorial use forked state.

You need Node.js 22.13 or later with npm, and an Arete owner account with cloud dev-environment access. The restricted account used for agent discovery does not grant this access.

Terminal window
curl -fsSL https://arete.run/install.sh | sh

The installer prints the binary’s location. Open a new terminal if a4 is not yet on your path. No Rust toolchain is needed. Update with a4 self update.

Authenticate with a4 auth login --key <your-secret-key> using your account’s secret key, or provide ARETE_API_KEY through your usual secret manager. Keep keys out of source control and screenshots.

Terminal window
a4 protocol init my-tip-jar
cd my-tip-jar
npm install
a4 init -y
a4 doctor --json
npx arete-protocol check

The scaffold writes protocol.ts, project configuration, and the System Program SDK, installed from the registry. If the registry install fails, init stops with the error and the command to retry; it never substitutes a local IDL. a4 init adds coding-agent instructions, skills, and MCP setup; doctor reports configuration problems and fixes.

Read protocol.ts. The open step transfers an amount from its caller to a recipient and creates an instance in state open, emitting tipJar.opened. Any wallet can tip the recipient while the jar is open, as often as it likes. The recipient’s close step transfers an amount back to the creator and moves the instance to terminal state closed, emitting tipJar.closed.

automations/index.ts tips on supporters’ behalf once they opt in: daily for a jar they chose, and on every new jar for a recipient they follow. a4 dev up runs it too; the project’s README.md walks through both, and Your first automation explains how it works.

This is a teaching example built from transfers. It does not lock funds in escrow or require the recipient to return them.

Terminal window
a4 dev up --open

Keep this terminal running. Arete creates or reuses your project’s persistent mainnet fork, builds the protocol, deploys it privately, and generates a client pointing at that deployment. The CLI prints the RPC and dev UI URLs. The dev UI and wallet keys are local; execution happens in your hosted fork.

If your plan cannot create an environment, the command reports that limit. Inspect access and usage with a4 dev list.

In a second terminal, in the same directory:

Terminal window
a4 dev wallet recipient
a4 dev wallet creator

These create local test keypairs and fund them in the environment when needed. Copy the recipient’s public key into this command:

Terminal window
a4 dev step open --wallet creator --args '{"recipient":"<recipient-pubkey>","amount":"1000000"}'

Amounts are decimal strings in base units: "1000000" is one million lamports. The command prepares, signs locally, submits, and waits for the execution outcome. Copy the returned instance id.

Terminal window
a4 dev instance <instance-id> --wallet recipient
a4 protocol actions --dev --wallet recipient --instance <instance-id>
a4 stream --dev --instance <instance-id>

You should see the open instance and its activity. Leave the stream running, or stop it with Ctrl-C before the next commands.

Try closing with the creator. This is expected to be rejected and exits non-zero because the creator is not the bound recipient:

Terminal window
a4 dev step close --wallet creator --instance <instance-id> --args '{"amount":"1000000"}'

Now use the recipient:

Terminal window
a4 dev step close --wallet recipient --instance <instance-id> --args '{"amount":"1000000"}'
a4 dev instance <instance-id> --wallet recipient

The instance is closed. Attempting another instance step returns instance_terminal. This is how an app learns that the workflow has finished.

Change the amount_zero guard in open to require at least two million lamports:

guards: { amount_zero: "args.amount >= 2000000" },

a4 dev up rebuilds and activates a new deployment, updates the generated client, and retires the previous deployment after success. A failed build leaves the previous deployment running. Re-run open with one million to see the rejection, then with two million to create a new instance.

Changes do not migrate the old deployment’s instances. Query the current deployment and create a fresh instance for the new definition.

Ctrl-C stops the local RPC endpoint and UI. The environment retains its state until its retention limit; a4 dev down --sleep also puts it to sleep now. See the environment guide for lifecycle and limits.

If you only need an existing program’s readers and builders, start with Program SDKs. For data investigation, use Explore on-chain.