Skip to main content
The Anchor.toml file is the configuration file for Anchor workspaces. It defines workspace settings, program deployments, testing configuration, and build options.

File Structure

A complete Anchor.toml with all sections:
[toolchain]
anchor_version = "0.32.1"
solana_version = "2.3.0"
package_manager = "yarn"

[features]
resolution = true
skip-lint = false

[registry]
url = "https://api.apr.dev"

[provider]
cluster = "localnet"
wallet = "~/.config/solana/id.json"

[programs.localnet]
my_program = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"

[programs.devnet]
my_program = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"

[programs.mainnet]
my_program = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"

[scripts]
test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"

[hooks]
pre-build = "echo 'Starting build...'"
post-build = "echo 'Build complete!'"
pre-test = ["echo 'Test 1'", "echo 'Test 2'"]
post-test = "echo 'Tests complete!'"
pre-deploy = "echo 'Deploying...'"
post-deploy = "echo 'Deployed!'"

[workspace]
members = ["programs/*"]
exclude = ["programs/excluded"]
types = "app/src/types"

[test]
startup_wait = 5000
shutdown_wait = 2000
upgradeable = false

[[test.genesis]]
address = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
program = "spl_token.so"

[test.validator]
url = "https://api.mainnet-beta.solana.com"
bind_address = "0.0.0.0"
rpc_port = 8899
ledger = ".anchor/test-ledger"
limit_ledger_size = 10000

[[test.validator.clone]]
address = "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"

[[test.validator.account]]
address = "YourAccountAddress"
filename = "account.json"

Required Sections

[provider]

Specifies the default cluster and wallet for all Anchor commands.
[provider]
cluster = "localnet"                    # Cluster: localnet, devnet, mainnet, or custom URL
wallet = "~/.config/solana/id.json"     # Path to keypair file
Cluster Options:
  • localnet - Local test validator (default: http://127.0.0.1:8899)
  • devnet - Solana devnet
  • mainnet - Solana mainnet-beta
  • Custom URL: "https://api.devnet.solana.com"
  • Custom with WebSocket:
    [provider]
    cluster = { http = "https://api.custom.com", ws = "wss://api.custom.com" }
    

[scripts]

Defines executable scripts for your workspace. The test script is required for anchor test.
[scripts]
test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"
lint = "yarn run eslint ."
format = "yarn run prettier --write ."
Run scripts with:
anchor run <script-name>

Optional Sections

[toolchain]

Override toolchain versions and settings for the workspace.
[toolchain]
anchor_version = "0.32.1"    # Anchor CLI version (requires avm)
solana_version = "2.3.0"     # Solana tools version
package_manager = "yarn"     # Package manager: npm, yarn, pnpm, bun
Package Manager Values:
  • npm - Node Package Manager
  • yarn - Yarn (default)
  • pnpm - PNPM
  • bun - Bun runtime
The anchor_version field requires AVM (Anchor Version Manager) to be installed.

[features]

Configure Anchor framework features.
[features]
resolution = true      # Enable account resolution (default: true)
skip-lint = false      # Skip safety comment checks (default: false)
resolution: When enabled, the IDL includes account resolution information for clients. skip-lint: Disables checks for safety comments (e.g., // UNSAFE, // TODO) in generated code.

[registry]

Configure the Anchor Package Registry (APR) URL.
[registry]
url = "https://api.apr.dev"  # Default APR endpoint

programs.cluster configuration

Map program library names to their on-chain addresses for each cluster.
[programs.localnet]
my_program = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
other_program = "2RaN5auQwMdg5efgCaVqpETBV8sacWGR8tkK4m9kjo5r"

[programs.devnet]
my_program = "DevnetProgramID111111111111111111111111111"

[programs.mainnet]
my_program = "MainnetProgramID11111111111111111111111111"
Program IDs must match the declare_id!() in your program code. Use anchor keys sync to update program IDs.

[workspace]

Configure workspace member programs and TypeScript type generation.
[workspace]
members = [              # Paths to program Cargo.toml files
    "programs/*",        # Glob patterns supported
    "other_programs/my_program"
]
exclude = [              # Paths to exclude from workspace
    "programs/excluded"
]
types = "app/src/types"  # Directory for generated TypeScript types
members: Defaults to programs/* if not specified. types: When set, anchor build copies generated <program>.ts IDL files to this directory.

[hooks]

Run commands at specific stages of the build/test/deploy pipeline.
[hooks]
pre-build = "echo 'Starting build...'"
post-build = "echo 'Build complete!'"
pre-test = ["echo 'Setup'", "cargo fmt --check"]
post-test = "cargo clippy"
pre-deploy = "anchor build --verifiable"
post-deploy = "anchor idl upload <program-id>"
Available Hooks:
  • pre-build / post-build - Run before/after anchor build
  • pre-test / post-test - Run before/after anchor test
  • pre-deploy / post-deploy - Run before/after anchor deploy
Hook Behavior:
  • Single command: hook = "command"
  • Multiple commands: hook = ["cmd1", "cmd2"] (run in series)
  • Non-zero exit code aborts the operation
  • Supports both kebab-case (pre-build) and snake_case (pre_build)

[test]

Configure test validator behavior.
[test]
startup_wait = 5000      # Milliseconds to wait for validator startup
shutdown_wait = 2000     # Milliseconds to wait for shutdown
upgradeable = false      # Deploy programs as upgradeable
startup_wait: Increase if you’re cloning many accounts (increases startup time). upgradeable: When true, deploys with --upgradeable flag. Initial upgrade authority is set to provider.wallet.

[[test.genesis]]

Load programs at genesis when starting the test validator.
[[test.genesis]]
address = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
program = "spl_token.so"
upgradeable = false

[[test.genesis]]
address = "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"
program = "mpl_token_metadata.so"
upgradeable = true
Use double brackets [[test.genesis]] for multiple entries.

[test.validator]

Configure the Solana test validator options.
[test.validator]
url = "https://api.mainnet-beta.solana.com"  # Cluster URL for cloning
bind_address = "0.0.0.0"                      # IP address to bind
ledger = ".anchor/test-ledger"                # Ledger directory
rpc_port = 8899                               # RPC port
limit_ledger_size = 10000                     # Max shreds in root slots
slots_per_epoch = 432000                      # Slots per epoch
ticks_per_slot = 64                           # Ticks per slot
warp_slot = 1000                              # Warp ledger to slot
gossip_host = "127.0.0.1"                     # Gossip DNS/IP
gossip_port = 8001                            # Gossip port
faucet_port = 9900                            # Faucet port
faucet_sol = 1000000                          # Faucet SOL amount
dynamic_port_range = "8002-8020"              # Dynamic port range
geyser_plugin_config = "config.json"          # Geyser plugin config

[[test.validator.clone]]

Clone accounts from the configured cluster.
[test.validator]
url = "https://api.mainnet-beta.solana.com"

[[test.validator.clone]]
address = "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"

[[test.validator.clone]]
address = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
For upgradeable programs, Anchor automatically clones the program data account.

[[test.validator.account]]

Load account data from JSON files.
[[test.validator.account]]
address = "YourAccountAddress"
filename = "accounts/account1.json"

[[test.validator.account]]
address = "AnotherAccountAddress"
filename = "accounts/account2.json"
JSON Format:
{
  "pubkey": "AccountAddress",
  "account": {
    "lamports": 1000000,
    "data": [1, 2, 3, 4],
    "owner": "11111111111111111111111111111111",
    "executable": false,
    "rentEpoch": 0
  }
}

Command Line Overrides

Override Anchor.toml settings via command line:
# Override cluster
anchor test --provider.cluster devnet

# Override wallet
anchor deploy --provider.wallet ~/.config/solana/mainnet.json

# Override commitment level
anchor test --commitment confirmed

Environment Variables

Set provider options via environment variables:
export ANCHOR_PROVIDER_URL="https://api.devnet.solana.com"
export ANCHOR_WALLET="~/.config/solana/devnet.json"

anchor test

Example Configurations

Minimal Configuration

Anchor.toml
[provider]
cluster = "localnet"
wallet = "~/.config/solana/id.json"

[programs.localnet]
my_program = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"

[scripts]
test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"

Production Configuration

Anchor.toml
[toolchain]
anchor_version = "0.32.1"
solana_version = "2.3.0"
package_manager = "pnpm"

[features]
resolution = true
skip-lint = false

[provider]
cluster = "mainnet"
wallet = "~/.config/solana/mainnet-keypair.json"

[programs.mainnet]
my_program = "MainnetProgramID11111111111111111111111111"

[scripts]
test = "pnpm test"
verify = "anchor verify -p my_program MainnetProgramID11111111111111111111111111"

[hooks]
pre-deploy = "anchor build --verifiable"
post-deploy = "anchor run verify"

[workspace]
types = "app/src/types"

Testing with Mainnet Forks

Anchor.toml
[provider]
cluster = "localnet"
wallet = "~/.config/solana/id.json"

[programs.localnet]
my_program = "11111111111111111111111111111111"

[scripts]
test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"

[test]
startup_wait = 10000  # Increased for account cloning

[test.validator]
url = "https://api.mainnet-beta.solana.com"

[[test.validator.clone]]
address = "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"

[[test.validator.clone]]
address = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"

Best Practices

Always specify exact versions:
[toolchain]
anchor_version = "0.32.1"  # Not "0.32" or "latest"
solana_version = "2.3.0"   # Not "2.3" or "latest"
Maintain separate program IDs for testing and production:
[programs.localnet]
my_program = "LocalTestID1111111111111111111111111111"

[programs.devnet]
my_program = "DevnetID111111111111111111111111111111111"

[programs.mainnet]
my_program = "MainnetID11111111111111111111111111111111"
Always version control your Anchor.toml:
# .gitignore
# Anchor.toml  # <- DO NOT IGNORE
Automate verification in your deployment workflow:
[hooks]
pre-deploy = [
    "anchor build --verifiable",
    "cargo clippy -- -D warnings",
    "cargo test"
]
post-deploy = "anchor run verify"

Resources

Build docs developers (and LLMs) love