Development Setup
This guide covers everything you need to develop, test, and deploy Intelligent Contracts — from zero-setup exploration to a full local development environment with linting, testing, and agent-assisted workflows.
Quick Start: GenLayer Studio
The fastest way to start is studio.genlayer.com (opens in a new tab) — a web-based IDE where you can write, deploy, and interact with Intelligent Contracts with zero setup.
You can also import any deployed contract by address to interact with it directly in the Studio — useful for debugging or testing contracts you've deployed from your local environment.
For anything beyond exploration — local testing, CI, agent-assisted development — set up a local environment below.
Local Environment Setup
Prerequisites
Docker is only required if you want to run GenLayer Studio locally. Direct mode tests and GLSim work without Docker.
Clone the Boilerplate
The GenLayer Project Boilerplate (opens in a new tab) is the recommended starting point. It includes contract templates, testing infrastructure, and a frontend scaffold.
git clone https://github.com/genlayerlabs/genlayer-project-boilerplate.git
cd genlayer-project-boilerplateInstall Dependencies
pip install -r requirements.txtThis installs:
genlayer-test— testing framework with direct mode, GLSim, and integration test supportgenvm-linter— static analysis for contract safety and correctness
Project Structure
contracts/ # Your Intelligent Contracts
tests/
direct/ # Fast in-memory tests (no server needed)
integration/ # Full tests against GenLayer Studio
frontend/ # Next.js frontend with GenLayerJS
deploy/ # Deployment scripts
gltest.config.yaml # Test network configurationDevelopment Workflow
The recommended development loop:
1. Write Your Contract
Create or edit a contract in contracts/:
from genlayer import *
class MyContract(gl.Contract):
data: TreeMap[Address, str]
def __init__(self):
self.data = TreeMap()
@gl.public.view
def get_data(self, addr: Address) -> str:
return self.data.get(addr, "")
@gl.public.write
def set_data(self, value: str):
self.data[gl.message.sender_address] = value2. Lint
Run the linter to catch issues before testing:
genvm-lint check contracts/my_contract.pycheck runs both fast AST-based safety checks and SDK-based semantic validation. It catches:
- Forbidden imports —
os,sys,subprocess, etc. - Non-deterministic calls outside equivalence principle blocks
- Invalid storage types — must use
TreeMap/DynArray, notdict/list - Missing decorators and return type annotations
Use --json for machine-readable output (useful for CI and agent workflows).
3. Direct Mode Tests
The fastest feedback loop — runs contracts in-memory without any server:
pytest tests/direct/ -vDirect mode provides Foundry-style test fixtures:
import json
def test_create_and_read(direct_vm, direct_deploy, direct_alice):
contract = direct_deploy("contracts/my_contract.py")
# Set the transaction sender
direct_vm.sender = direct_alice
# Call write methods directly
contract.set_data("hello")
# Call view methods
result = contract.get_data(direct_alice)
assert result == "hello"Mocking Web and LLM Calls
For contracts that use gl.nondet.web or gl.nondet.exec_prompt, mock the responses:
def test_with_mocks(direct_vm, direct_deploy, direct_alice):
contract = direct_deploy("contracts/my_contract.py")
direct_vm.sender = direct_alice
# Mock web requests (regex matches on URL)
direct_vm.mock_web(
r".*api\.example\.com/prices.*",
{"status": 200, "body": '{"price": 42.5}'},
)
# Mock LLM responses (regex matches on prompt)
direct_vm.mock_llm(
r".*Extract the match result.*",
json.dumps({"score": "2:1", "winner": 1}),
)
contract.update_price("ETH/USD")
assert contract.get_price("ETH/USD") == 42.5
# Reset mocks between scenarios
direct_vm.clear_mocks()Testing Failures
def test_expected_failure(direct_vm, direct_deploy, direct_alice):
contract = direct_deploy("contracts/my_contract.py")
direct_vm.sender = direct_alice
with direct_vm.expect_revert("Insufficient balance"):
contract.withdraw(1000)Available fixtures: direct_vm, direct_deploy, direct_alice, direct_bob, direct_charlie, direct_owner, direct_accounts
4. Integration Tests
Once direct tests pass, run against a GenLayer environment (see Environments below) for full end-to-end validation:
gltest tests/integration/ -v -sIntegration tests use the genlayer-test SDK to deploy and interact with contracts through the JSON-RPC API:
from gltest import get_contract_factory
from gltest.assertions import tx_execution_succeeded
def test_full_flow():
factory = get_contract_factory("MyContract")
contract = factory.deploy(args=[])
# Write methods return transaction receipts
tx_receipt = contract.set_data(args=["hello"]).transact()
assert tx_execution_succeeded(tx_receipt)
# Read methods return values directly
result = contract.get_data(args=[contract.address]).call()
assert result == "hello"See the GenLayer Test SDK reference for the full API.
Environments
These are the backends you can develop against. Your frontend, integration tests, and deployment scripts all connect to one of these via JSON-RPC.
GLSim
Setup: pip install genlayer-test[sim]
A lightweight simulator that implements the GenLayer JSON-RPC protocol. Starts in ~1 second, no Docker required. You can point your frontend and integration tests at it for fast iteration.
GLSim runs the Python runner natively — not inside GenVM — so there can be minor incompatibilities with the full runtime. Use it for fast development cycles, then validate against Studio before deploying.
# Start the simulator
glsim --port 4000 --validators 5
# Your frontend connects to http://localhost:4000/api
# Integration tests run against it
gltest tests/integration/ -v -sGenLayer Studio (Local)
Setup: Docker 26+ and GenLayer CLI
Full GenVM execution with real consensus. You get complete validator logs, transaction inspection, and the Studio UI for interactive debugging. This is where you validate that everything works in the real runtime.
npm install -g genlayer
genlayer init
genlayer upOnce running, access Studio at http://localhost:8080/ (opens in a new tab). Your frontend and tests connect to http://localhost:4000/api.
gltest tests/integration/ -v -s --network localnetCLI options for genlayer init and genlayer up
genlayer init options:
--numValidators <number>— number of validators (default: 5)--headless— run without Studio UI--reset-db— start with a clean database--localnet-version <version>— pin a specific localnet version
genlayer up options:
--reset-validators— recreate all validators--numValidators <number>— number of validators--headless— run without Studio UI--reset-db— clean database
studio.genlayer.com
Setup: none
Hosted Studio — convenient when you don't want to run Docker locally. Rate limited compared to a local instance. You can also import any deployed contract by address to interact with it directly in the browser.
gltest tests/integration/ -v -s --network studionetTestnet Bradbury
Setup: account with private keys
The most realistic environment — the actual GenLayer testnet with real validators. You don't get full validator logs like you do with local Studio, so this is best for final pre-production validation rather than active debugging.
gltest tests/integration/ -v -s --network testnet_bradburyConfigure accounts in gltest.config.yaml:
networks:
testnet_bradbury:
accounts:
- "${ACCOUNT_PRIVATE_KEY_1}"
- "${ACCOUNT_PRIVATE_KEY_2}"IDE Support
The GenLayer VS Code Extension (opens in a new tab) provides syntax highlighting, snippets, and language support for Intelligent Contracts. Works with VS Code, Cursor, and other VS Code-compatible editors.
Agent-Assisted Development
The boilerplate is designed to work well with AI coding agents. The linter and direct mode tests provide a fast feedback loop that agents can use without spinning up infrastructure.
The GenLayer Skills (opens in a new tab) repository provides a Claude Code plugin marketplace with operational skills for GenLayer development:
# Add the skills marketplace to Claude Code
/plugin marketplace add genlayerlabs/skillsThe GenLayer MCP Server (opens in a new tab) provides contract generation and GenLayer-specific guidance directly in your IDE via the Model Context Protocol:
# Add to Claude Code
claude mcp add genlayer npx -- -y genlayer-mcpThe GenLayer Docs MCP Server gives your AI agent searchable access to the full GenLayer documentation and SDK reference — so it can look up APIs, patterns, and examples while writing code:
# Add to Claude Code
claude mcp add genlayer-docs --transport sse https://docs-mcp.genlayer.com/sseThis is a hosted service — no local setup required. It provides a search_docs tool that searches across both the GenLayer documentation (opens in a new tab) and the GenLayer SDK reference (opens in a new tab). Compatible with any MCP client (Claude Code, Cursor, Windsurf, etc.).
The boilerplate also includes a CLAUDE.md file pre-configured with commands, architecture context, and testing patterns — so agents understand the project structure immediately.
Frontend Development
The boilerplate includes a Next.js frontend with GenLayerJS integration. See the GenLayerJS SDK documentation for the full API reference.
cd frontend
npm install
npm run devFor building a frontend from scratch:
npm install genlayer-jsimport { createClient } from 'genlayer-js';
const client = createClient({ endpoint: 'http://localhost:4000/api' });
// Read from a contract
const value = await client.readContract({
address: contractAddress,
functionName: "get_data",
args: [],
});
// Write to a contract
const txHash = await client.writeContract({
address: contractAddress,
functionName: "set_data",
args: [newValue],
});
const receipt = await client.waitForTransactionReceipt({
hash: txHash,
status: "FINALIZED",
});