Templates and automation for initializing and configuring Foundry projects. Use when setting up new Foundry projects or adding Foundry to existing codebases.
/plugin marketplace add IvanTorresEdge/molcajete.ai/plugin install ivantorresedge-sol-tech-stacks-solidity@IvanTorresEdge/molcajete.aiThis skill inherits all available tools. When active, it can use any tool Claude has access to.
scripts/init-foundry.shtemplates/foundry.tomlThis skill provides templates, scripts, and best practices for setting up Foundry-based Solidity projects.
Use this skill when:
Prerequisites: Foundry must be installed (foundryup)
Before using this skill, reference the framework-detection skill to:
# Initialize new Foundry project
forge init my-project
cd my-project
# Or initialize in existing directory
forge init --force
Foundry creates this structure:
project/
├── foundry.toml # Configuration
├── .env.example # Environment variables template
├── lib/ # Dependencies (git submodules)
├── src/ # Contract source files
│ ├── interfaces # Interfaces
│ │ └──ICounter # Example interface
│ └── Counter.sol # Example contract
├── test/ # Test files
│ └── Counter.t.sol # Example test
└── script/ # Deployment scripts
└── Counter.s.sol # Example script
See ./templates/foundry.toml for the complete configuration template.
Key Configuration Sections:
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
solc_version = "0.8.30"
optimizer = true
optimizer_runs = 200
via_ir = false
# Testing
verbosity = 2
fuzz_runs = 256
# Gas reporting
gas_reports = ["*"]
# Formatting
line_length = 120
tab_width = 4
bracket_spacing = false
See ./templates/.env.example for complete environment variable template.
Essential Variables:
# RPC URLs
MAINNET_RPC_URL=
SEPOLIA_RPC_URL=
ARBITRUM_RPC_URL=
# Private Keys (NEVER commit actual keys)
PRIVATE_KEY=
# Etherscan API Keys
ETHERSCAN_API_KEY=
ARBISCAN_API_KEY=
# Gas Price Settings
GAS_PRICE=
[profile.production]
optimizer = true
optimizer_runs = 10000
via_ir = true
[profile.test]
verbosity = 3
fuzz_runs = 1000
invariant_runs = 256
[profile.gas-optimized]
optimizer = true
optimizer_runs = 1000000
via_ir = true
gas_reports = ["*"]
[profile.default]
fork_url = "${MAINNET_RPC_URL}"
fork_block_number = 18000000
# Add OpenZeppelin contracts
forge install OpenZeppelin/openzeppelin-contracts
# Add Solmate
forge install transmissions11/solmate
# Add Forge Standard Library (included by default)
forge install foundry-rs/forge-std
Foundry auto-generates remappings.txt, but you can customize:
@openzeppelin/=lib/openzeppelin-contracts/
@solmate/=lib/solmate/src/
forge-std/=lib/forge-std/src/
Or configure in foundry.toml:
remappings = [
"@openzeppelin/=lib/openzeppelin-contracts/",
"@solmate/=lib/solmate/src/"
]
See ./scripts/init-foundry.sh for automated setup.
Usage:
# Basic initialization
./scripts/init-foundry.sh
# With project name
./scripts/init-foundry.sh my-project
# In existing directory
./scripts/init-foundry.sh --force
What the script does:
When adding Foundry to an existing Hardhat project:
# Initialize but don't overwrite existing files
forge init --no-commit
# foundry.toml
[profile.default]
src = "contracts" # Use Hardhat's contracts dir
test = "test/foundry" # Separate Foundry tests
out = "out"
libs = ["node_modules", "lib"] # Include both package managers
# Foundry
out/
cache/
lib/
# Hardhat
artifacts/
cache/
node_modules/
# Install via Foundry
forge install OpenZeppelin/openzeppelin-contracts
# Reference in Hardhat
# Add to hardhat.config.js:
# paths: { sources: "./contracts" }
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
import "forge-std/Test.sol";
import "../src/MyContract.sol";
contract MyContractTest is Test {
MyContract public myContract;
function setUp() public {
myContract = new MyContract();
}
function testBasic() public {
// Test implementation
}
function testFuzz_Amount(uint256 amount) public {
// Fuzz test
}
}
# Run all tests
forge test
# Run specific test
forge test --match-test testBasic
# Run with verbosity
forge test -vvvv
# Run with gas reporting
forge test --gas-report
# Run with coverage
forge coverage
⚠️ CRITICAL: Never store production private keys in .env files!
# Deploy using Ledger
forge script script/Deploy.s.sol:DeployScript \
--rpc-url $RPC_URL \
--ledger \
--broadcast
# Deploy using Trezor
forge script script/Deploy.s.sol:DeployScript \
--rpc-url $RPC_URL \
--trezor \
--broadcast
Create a named keystore:
# Create a new wallet (prompts for password)
cast wallet new ~/.foundry/keystores/deployer
# Import existing private key into keystore
cast wallet import deployer --interactive
Use in deployment:
# Deploy using named account
forge script script/Deploy.s.sol:DeployScript \
--rpc-url $RPC_URL \
--account deployer \
--sender 0xYourAddress \
--broadcast
Update your script to use the account:
contract DeployScript is Script {
function run() external {
// No private key needed - uses --account flag
vm.startBroadcast();
MyContract myContract = new MyContract();
vm.stopBroadcast();
console.log("MyContract deployed to:", address(myContract));
}
}
# Prompts for private key (not stored anywhere)
forge script script/Deploy.s.sol:DeployScript \
--rpc-url $RPC_URL \
--private-key-interactive \
--broadcast
⚠️ Use ONLY for local development or testnet testing with non-production keys!
contract DeployScript is Script {
function run() external {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(deployerPrivateKey);
MyContract myContract = new MyContract();
vm.stopBroadcast();
console.log("MyContract deployed to:", address(myContract));
}
}
If using .env:
# Dry run (simulation)
forge script script/Deploy.s.sol:DeployScript --rpc-url $RPC_URL
# Actual deployment with hardware wallet (RECOMMENDED for production)
forge script script/Deploy.s.sol:DeployScript \
--rpc-url $RPC_URL \
--ledger \
--broadcast \
--verify
# Actual deployment with cast wallet (RECOMMENDED for all deployments)
forge script script/Deploy.s.sol:DeployScript \
--rpc-url $RPC_URL \
--account deployer \
--sender 0xYourAddress \
--broadcast \
--verify
# Development only: with .env private key
forge script script/Deploy.s.sol:DeployScript \
--rpc-url $RPC_URL \
--broadcast \
--verify
cast wallet for all deployments; never store production keys in .envtest/foundry/ for Foundry tests in hybrid setupsvia_ir = true for complex contractssolc_version in foundry.toml# Install/update Foundry
curl -L https://foundry.paradigm.xyz | bash
foundryup
# Prioritize Foundry libs over node_modules
libs = ["lib", "node_modules"]
# Regenerate remappings
forge remappings > remappings.txt
# Check test file naming (must end in .t.sol)
mv test/MyTest.sol test/MyTest.t.sol
| Task | Command | Notes |
|---|---|---|
| Init project | forge init | Creates new project |
| Add dependency | forge install <repo> | Uses git submodules |
| Build | forge build | Compiles contracts |
| Test | forge test | Runs tests |
| Coverage | forge coverage | Test coverage |
| Gas report | forge test --gas-report | Gas usage |
| Format | forge fmt | Code formatting |
| Deploy | forge script | Run deployment |
| Verify | forge verify-contract | Verify on Etherscan |
This skill provides the following templates:
./templates/foundry.toml - Complete Foundry configuration./templates/.env.example - Environment variables templateThis skill provides the following scripts:
./scripts/init-foundry.sh - Automated project initializationNext Steps After Setup:
foundry.toml for your specific needs.env.example to .env and fill in valuesforge installsrc/test/forge test to verify setupThis skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.