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:
Optional Sections
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
[ 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
[ 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
[ 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
Pin Versions in Production
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"
Use Different Program IDs per Cluster
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
Use Hooks for Build Verification
Automate verification in your deployment workflow: [ hooks ]
pre-deploy = [
"anchor build --verifiable" ,
"cargo clippy -- -D warnings" ,
"cargo test"
]
post-deploy = "anchor run verify"
Resources