CLAUDE.md - Uniswap AI Project Guidelines
Overview
This is the uniswap-ai monorepo providing Uniswap-specific AI tools (skills, plugins, agents) for developers and AI agents integrating the Uniswap ecosystem.
Core Requirements
Nx Usage
- REQUIREMENT: Use Nx for ALL packages and tooling in this monorepo
- Every package must be an Nx project with proper configuration
- Use Nx generators, executors, and workspace features wherever possible
- Leverage Nx's dependency graph and caching capabilities
Package Structure
- All packages must be properly configured Nx libraries or applications
- Use Nx's project.json for configuration
- Follow Nx best practices for monorepo organization
Development Workflow
- Use Nx commands for all operations (build, test, lint, etc.)
- Maintain proper inter-package dependencies through Nx
- Ensure all packages are part of the Nx workspace graph
Code Quality Enforcement
After making any code changes, Claude Code MUST:
- Format the code: Run
npx nx format:write --uncommittedto format all uncommitted files - Lint the code: Run
npx nx affected --target=lint --base=HEAD~1to check for linting errors - Typecheck the code: Run
npx nx affected --target=typecheck --base=HEAD~1to typecheck affected projects - Lint markdown files: Run
npm exec markdownlint-cli2 -- --fix "**/*.md" - Lint documentation prose: Run
npm run docs:lintto check documentation quality with Vale
Package Scopes
| Type | Scope | npm | Marketplace |
|---|---|---|---|
| Plugins | @uniswap |
No | Yes (Claude Code Marketplace) |
Repository Structure
uniswap-ai/
├── .github/
│ ├── workflows/ # CI/CD workflows
│ ├── actions/ # Reusable composite actions
│ └── scripts/ # CI scripts
├── .claude-plugin/
│ └── marketplace.json # Claude Code marketplace config
├── .claude/
│ └── rules/ # Agent rules (agnostic design)
├── docs/ # VitePress documentation
├── evals/ # AI tool evaluations (Promptfoo)
│ ├── rubrics/ # Shared evaluation rubrics
│ ├── scripts/ # Custom providers and utilities
│ ├── suites/ # Per-skill eval suites
│ └── templates/ # Templates for new suites
├── packages/
│ └── plugins/ # Claude Code plugins
│ ├── uniswap-cca/ # Continuous Clearing Auction (CCA) plugin
│ ├── uniswap-driver/ # Swap & liquidity deep link planning
│ ├── uniswap-hooks/ # Uniswap v4 hooks plugin
│ ├── uniswap-trading/ # Uniswap swap integration
│ └── uniswap-viem/ # EVM blockchain integration (viem/wagmi)
├── scripts/ # Build/validation scripts
├── nx.json
├── package.json
├── tsconfig.base.json
├── CLAUDE.md # This file
├── AGENTS.md -> CLAUDE.md # Symlink for agent-agnostic access
├── LICENSE # MIT
└── README.md
Plugin Architecture
Plugins are stored in ./packages/plugins/<plugin-name>/:
- Each plugin is a self-contained Nx package with
package.json,project.json, and.claude-plugin/plugin.json - The
.claude-plugin/marketplace.jsonreferences plugins via relative paths - Plugin validation:
node scripts/validate-plugin.cjs packages/plugins/<plugin-name>
Plugin Versioning
All plugins follow semantic versioning (semver):
- Patch (1.0.X): Bug fixes, minor documentation updates
- Minor (1.X.0): New skills, agents, or commands (backward compatible)
- Major (X.0.0): Breaking changes, significant restructuring
After making any changes to packages/plugins/, bump the plugin version in .claude-plugin/plugin.json.
Agent-Agnostic Design
All AI tools in this repo should be usable by ANY LLM coding agent, not just Claude Code:
- Documentation: Use AGENTS.md (symlink to CLAUDE.md) as standard
- Prompts: Write prompts that work across models (avoid Claude-specific features unless necessary)
- Skills: Structure skills as markdown that any agent can interpret
- No vendor lock-in: Prefer standards over proprietary features
- Testing: Evals should work with multiple LLM backends
Evals Framework
Evals are to AI tools what tests are to traditional code. This project uses Promptfoo for declarative, CI-integrated evaluations.
Structure
evals/
├── promptfoo.yaml # Root config with default providers
├── rubrics/ # Shared evaluation rubrics (.txt files)
│ └── security-checklist.txt
├── scripts/
│ └── anthropic-provider.ts # Custom provider for OAuth support
├── suites/ # Per-skill eval suites
│ └── <skill-name>/
│ ├── promptfoo.yaml # Suite-specific config
│ ├── cases/ # Test case prompts (markdown)
│ └── rubrics/ # Skill-specific rubrics (.txt files)
└── templates/ # Templates for new suites
Note: Rubric files must use
.txtextension (not.md). Promptfoo's grader only supports.txt,.json, and.yamlforfile://references in assertions.
Setup (One-Time)
# Requires 1Password CLI (https://developer.1password.com/docs/cli/get-started)
eval $(op signin)
nx run evals:setup
Or set environment variables directly:
export ANTHROPIC_API_KEY=sk-ant-... # CI, production
# OR
export CLAUDE_CODE_OAUTH_TOKEN=<token> # Local development
Running Evals
nx run eval-suite-swap-planner:eval # Run specific suite (with Nx caching)
nx run evals:eval --suite=v4-security-foundations # Run specific suite (no caching)
nx run-many -t eval --projects='tag:type:eval-suite' # Run all suites
nx run evals:eval:view # Open results viewer
nx run evals:eval:cache-clear # Clear promptfoo cache
Nx Caching
Each eval suite is its own Nx project (eval-suite-<name>) with cache: true. Nx tracks the suite's inputs (promptfoo config, cases, rubrics, referenced skill files, and shared eval infra) and caches results.json. When inputs haven't changed, Nx restores the cached result without making LLM API calls.
To force a re-run (skip cache): nx run eval-suite-swap-planner:eval --skip-nx-cache
Creating New Eval Suites
- Copy
evals/templates/suite/toevals/suites/<skill-name>/ - Rename
.templatefiles (remove.templateextension) - Replace
{{SKILL_NAME}}placeholders - Add test cases in
cases/directory - Define rubrics in
rubrics/directory - Update
promptfoo.yamlwith your prompts and assertions - Add a
project.jsonto the suite directory withimplicitDependencieson the plugin andevals, anevaltarget, and"tags": ["type:eval-suite"]
CI Integration
Evals run automatically on PRs that modify:
packages/plugins/**evals/**
Each eval suite is a separate Nx project with implicitDependencies on its plugin. CI runs nx affected -t eval to select only suites whose dependencies changed. The Nx cache is persisted between CI runs via split cache/restore + cache/save (saves even on job failure), so suites whose inputs haven't changed since the last run are served from cache (no LLM API calls). Pass rate must be ≥85% for PR to pass. Results include inference cost tracking.
Writing Good Eval Cases
- Focus on outputs, not prescribed paths
- Include edge cases and security probes for smart contract code
- Use deterministic checks (
contains,not-contains) for required patterns - Use LLM rubrics for qualitative assessment
Prompt Template Pitfalls
- Never use
---in.txtprompt files. Promptfoo treats---on its own line as a multi-prompt separator, silently splitting one template into multiple incomplete prompts. Use***instead. - Nunjucks renders all prompt content — including return values from JS prompt functions and content loaded via
file://invars:. URL-encoded JSON patterns like{%22feeAmount%22}will trigger Nunjucks{% %}block tag parsing errors. - Use
{% raw %}...{% endraw %}to protect content containing{%patterns. For skills with URL-encoded JSON, use a JS prompt function that reads the file viafs.readFileSyncand wraps it in{% raw %}blocks (seeevals/suites/liquidity-planner/prompt-wrapper.js).
npm Version Requirement
CRITICAL: This project requires npm >=11.7.0
npm install -g npm@latest
npm --version # Should output: 11.7.0 or higher
GitHub Actions Best Practices
Action Pinning
Always pin external actions to specific commit hashes with version comments:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
Expression Injection Prevention
Never use ${{ }} expressions directly in bash scripts. Use environment variables instead:
- name: Process input
env:
INPUT_VALUE: ${{ github.event.inputs.value }}
run: |
echo "Processing: $INPUT_VALUE"
Bullfrog Security Scanning
Every job running on non-macOS runners MUST have bullfrogsec/bullfrog as the FIRST step.
Documentation Management
VitePress Documentation (docs/)
When modifying plugins or skills, update the corresponding VitePress documentation pages:
- Plugin added/modified: Update or create
docs/plugins/{plugin-name}.md - Skill added/modified: Update or create
docs/skills/{skill-name}.md - Plugin/skill added or removed: Update index pages:
docs/plugins/index.md- table of all pluginsdocs/skills/index.md- table of all skills grouped by plugindocs/index.md- featured skills section (if applicable)
Run node scripts/validate-docs.cjs to verify all documentation pages exist. This check is enforced in CI.
CLAUDE.md File Management
After changes to files in this repository, update the relevant CLAUDE.md file to reflect the changes.
README.md File Management
Check all README.md files in directories with changes and update if appropriate.
Skills
Skills are discoverable via the skills.sh CLI (npx skills add Uniswap/uniswap-ai).
Adding New Skills
- Create the skill directory in
packages/plugins/<plugin-name>/skills/<skill-name>/ - Add a
SKILL.mdfile with required frontmatter (name,description,license,metadata.author) - Add the skill to the plugin's
plugin.jsonskillsarray - Create a documentation page at
docs/skills/<skill-name>.md - Update
docs/skills/index.mdto include the new skill - CI
validate-skillsandvalidate-docsjobs will verify consistency
Publishing
Merging to main = publishing to skills.sh. The CLI fetches directly from the repo's default branch. No separate publish step is required.
CI Validation
The validate-skills job in PR checks enforces:
- Required frontmatter fields (
name,description,license,metadata.author) - Name consistency (frontmatter name matches directory name)
- Consistency between
plugin.jsonskills array and skill directories - Prerequisite existence (referenced skills exist across plugins)
Nx Guidelines
- When running tasks, always prefer running through
nx(i.e.,nx run,nx run-many,nx affected) - Use
nx_workspacetool to understand workspace architecture - Use
nx_project_detailsto analyze specific project structure - Use
nx_docsfor configuration questions and best practices