Anchor Program Anatomy
Understand what each file in an Anchor workspace does, how build artifacts are generated, and how a client call becomes an on-chain state change.
After anchor init, most beginners see the file tree and immediately lose the thread.
That is normal.
Anchor generates several files at once, and if you do not know what each one is for, every later lesson feels more complicated than it really is.
This lesson fixes that.
The Mental Model
An Anchor workspace is not one thing.
It is a small system with four separate jobs:
- program code in Rust
- workspace configuration
- test code
- generated build artifacts
If you keep those four buckets clear in your head, the file tree stops looking random.
What anchor init Creates
A default Anchor workspace includes files like these:
anchor_starter/
Anchor.toml
Cargo.toml
package.json
programs/
anchor_starter/
src/
lib.rs
migrations/
tests/
anchor_starter.ts
target/You may also see additional generated folders such as .anchor/ after running tests.
The exact contents can grow over time, but the important parts stay the same.
Start With Anchor.toml
Anchor.toml is the workspace control file.
It tells Anchor things like:
- which cluster to use
- which wallet to use
- which program addresses belong to the workspace
- which script should run during
anchor test
A typical shape looks like this:
[provider]
cluster = "localnet"
wallet = "~/.config/solana/id.json"
[scripts]
test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"
[programs.localnet]
anchor_starter = "YourProgramPubkeyHere"Why this file matters:
anchor buildandanchor testboth depend on it- cluster mistakes often start here
- test behavior is partly controlled here
- local program addresses are recorded here
If something feels wrong at the workspace level, open Anchor.toml first.
The programs/ Directory
This is where your on-chain code lives.
For a normal project, you will spend most of your time in:
programs/<program-name>/src/lib.rs
That file usually contains:
- your instruction handlers inside
#[program] - account validation structs with
#[derive(Accounts)] - state structs with
#[account] - custom errors
- helper logic
This is the security-critical part of the workspace.
If you want to understand what a program really does, start here, not in the frontend and not in the tests.
The Root Cargo.toml
Do not confuse the workspace Cargo.toml with the program crate's Cargo.toml.
At the root, Cargo.toml describes the Rust workspace itself.
Inside programs/<program-name>/Cargo.toml, you configure the actual program crate.
That distinction matters because Anchor workspaces can contain more than one program.
The tests/ Directory
This is where the integration tests live.
In a default setup, Anchor creates a TypeScript test file such as:
tests/anchor_starter.ts
That file does not replace program logic.
It does something different.
It proves that the program behaves correctly when called through real transactions.
In other words:
- Rust program code defines behavior
- tests prove that behavior from the outside
That separation matters.
You should not treat tests as decoration.
The migrations/ Directory
This directory is for deployment scripting.
Most beginners do not need to spend much time here yet.
But you should know why it exists.
As your project grows, deployment stops being just one command.
You may need scripts that coordinate program deploys, account initialization, or environment-specific setup.
That is the role this folder grows into.
The target/ Directory
This is generated output.
Do not confuse it with source code.
The most important subfolders are:
target/deploy/target/idl/target/types/
target/deploy/
This contains build artifacts such as the compiled program binary and deployment keypair material.
target/idl/
This contains the program IDL JSON.
Anchor generates that file during anchor build.
The official docs describe the IDL as the standardized description of your program's instructions and accounts.
That matters because clients use it to understand:
- instruction names
- required accounts
- argument types
- account data layouts
target/types/
This contains generated TypeScript types for the IDL.
These are useful for TypeScript tooling and client-side integration.
What anchor build Actually Changes
When you run:
anchor buildAnchor does more than compile Rust.
It also:
- emits the IDL into
target/idl/ - updates generated TypeScript types in
target/types/ - prepares deploy artifacts in
target/deploy/
That is why build output matters beyond just “did the compiler pass.”
If your instruction signatures changed, the generated artifacts should change too.
How A Client Call Becomes A State Change
Now connect the files together.
When a client calls your program, the flow looks like this:
- the client uses the program interface and account list
- the transaction is sent with the required accounts and signers
- Anchor validates the account context in your Rust program
- your instruction handler runs
- account data is written back on-chain
- the client or test fetches the updated state
That is the whole system.
The workspace exists to support that path.
One Concrete Mapping Exercise
Open these three files at the same time:
programs/<program-name>/src/lib.rstests/<program-name>.tstarget/idl/<program-name>.json
Then pick one instruction and answer:
- where is the Rust handler?
- where is the test that calls it?
- where is that instruction represented in the IDL?
If you can map one instruction across those three files, you are no longer guessing how the workspace fits together.
Common Confusions
Confusion 1: target/ is source code
It is not.
It is generated output.
Read it when useful, but do not treat it as the place where program logic should be edited.
Confusion 2: the IDL is optional trivia
It is not.
The IDL is one of the key contracts between your program and the code that calls it.
Confusion 3: Anchor.toml is only for deployment
It is not.
It affects provider settings, test scripts, and local program addresses too.
Confusion 4: the tests folder is separate from the real program
The tests are separate code, but not separate behavior.
They are how you prove the real behavior from the outside.
What You Should Know Before Moving On
Before the next lesson, you should be able to explain:
- what
Anchor.tomlcontrols - where the Rust program actually lives
- what the IDL is for
- why
target/is generated output, not source code - how one instruction shows up in program code, tests, and the IDL
If those answers are still fuzzy, open the file tree again and trace one instruction manually.
What Comes Next
Now that the workspace layout is clear, the next lesson can focus on the core Anchor model itself:
- instructions
- accounts
- signers
- constraints