ApeShift: How I Automated 93% of the Brownie → Ape Framework Migration with Codemods
--
Brownie is officially deprecated. Its own README now directs all Python Ethereum developers to migrate to Ape Framework. But the migration involves 14+ distinct API changes across imports, accounts, contracts, networks, testing, and config — and there was no automated tool to do it. I built ApeShift to fix that.
Brownie was the dominant Python smart contract framework for years. Thousands of open-source repos — from Chainlink tutorials to DeFi protocols — were built on it. When Brownie was deprecated, every one of those projects needed to migrate manually.
Here’s a sample of what that migration looks like by hand: Before (Brownie):
from brownie import accounts, SimpleStorage, network
def deploy():
account = accounts[0]
storage = SimpleStorage.deploy({"from": account})
if network.show_active() == "development":
return accounts[0]After (Ape):
from ape import accounts, project, networks
def deploy():
account = accounts.test_accounts[0]
storage = project.SimpleStorage.deploy(sender=account)
if networks.provider.network.name == "development":
return accounts.test_accounts[0]Every file, every function, every test needs this treatment. On a real project with 50+ files, this takes days.
ApeShift is a production-grade codemod workflow built with 14 deterministic jssg/ast-grep transforms. It automates 93% of the migration with zero false positives. One command migrates your entire project:
npx codemod apeshift -t ./my-brownie-projectHere are the key transformations:
Sender dicts
Before: from brownie import accounts, network, Contract
After: from ape import accounts, networks, project
Contract deploy
Before: contract.fn({“from”: account})
After: contract.fn(sender=account)
Network detection
Before: Token.deploy({“from”: account})
After: project.Token.deploy(sender=account)
Revert testing
Before: with brownie.reverts(“error”):
After: with ape.reverts(“error”):
Exceptions
Before: except brownie.exceptions.VirtualMachineError as e:
After: except ape.exceptions.ContractLogicError as e:
Container access
Before: Token[-1].address
After: project.Token.deployments[-1].address
Numeric literals
Before: 1e18
After: 1 * 10**18
Real-World Results
I tested ApeShift on 5 real open-source Brownie repositories: | Repository | Files | Auto% | FP | Ape Compile | Ape Test | | — -| — -| — -| — -| — -| — -| | brownie_simple_storage | 4 | 92% | 0 | PASS | 2/2 PASS | |
brownie_fund_me | 7 | 96% | 0 | FAIL* | FAIL* | |
chainlink-mix | 21 | 96% | 0 | FAIL* | FAIL* | |
brownie-nft-course | 18 | 86% | 0 | FAIL* | FAIL* | |
token-mix | 6 | 97% | 0 | PASS | review† | | Combined | 56 | 93% | 0 | | |
- Chainlink/OpenZeppelin npm dependency missing — not a migration bug. Run: npm install @chainlink/contracts before ape compile. †Project test setup requires minor manual review.
- Zero false positives across all 56 files and 279 patterns detected.
Hackathon scoring formula result: Score = 100 × (1 − ((0×5 + 11×1) ÷ (279×6))) = 99.34%
What’s Left for AI
ApeShift is intentionally conservative. When a pattern is ambiguous, it adds a TODO comment with specific instructions instead of guessing:
accounts.add(config[“wallets”][“from_key”]) # TODO(apeshift): accounts.add(key) not valid in Ape; # use accounts.load(“account-name”) after: ape accounts import <name>
The 4 categories left for human/AI review:
- accounts.add(key) → accounts.load(“name”) — alias is a human choice
- web3.eth.contract() → Contract() — ABI source varies per project
- Complex event filters — contract name required
- priority_fee — no direct Ape equivalent
Zero false positives is more valuable than 100% coverage with broken output.
Architecture
- 14 deterministic jssg/ast-grep transform rules
- TypeScript cleanup layer for numeric literals and import syntax
- Post-migration validator (ape compile + ape test)
- Confidence score report per migration run — ApeWorX docs PR content generator
Tech stack: TypeScript, jssg/ast-grep, commander.js, vitest, execa
How to Use It:
npx codemod apeshift -t ./my-brownie-projectFor local development:
git clone https://github.com/vinod820/apeshift
npm install
npm run build
node dist/src/cli.js migrate ./my-brownie-projectLinks
GitHub: https://github.com/vinod820/apeshift
Codemod Registry: https://app.codemod.com/registry/apeshift — ApeWorX
Docs PR: https://github.com/ApeWorX/ape/pull/2773
ApeWorX issue #640: https://github.com/ApeWorX/ape/issues/640
Brownie deprecation: https://github.com/eth-brownie/brownie#readme
Built for the Boring AI Hackathon (Codemod track).