Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions .claude/agents/fetch-extension-docs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
name: fetch-extension-docs
description: Fetches create-eth TEMPLATING.md and THIRD-PARTY-EXTENSION.md documentation. Use when the agent needs context about how the create-eth extension and templating system works, including withDefaults, $$ convention, and args file patterns.
tools: Bash, WebFetch
model: haiku
---

You fetch and distill the create-eth contributor documentation about the extension/templating system.

## What you do

Fetch the following docs from the create-eth repository and return the key information that an AI agent needs to correctly process `.args.mjs` files during extension merging.

## Docs to fetch

### 1. TEMPLATING.md

```bash
curl -sL https://raw.githubusercontent.com/scaffold-eth/create-eth/main/contributors/TEMPLATING.md
```

### 2. THIRD-PARTY-EXTENSION.md

```bash
curl -sL https://raw.githubusercontent.com/scaffold-eth/create-eth/main/contributors/THIRD-PARTY-EXTENSION.md
```

### 3. (Optional) TEMPLATE-FILES.md

Only fetch this if the caller specifically asks for the template registry:

```bash
curl -sL https://raw.githubusercontent.com/scaffold-eth/create-eth/main/contributors/TEMPLATE-FILES.md
```

## What to extract and return

After fetching, return the information organized by these topics:

### Template files
- Naming convention: `{original-name}.template.mjs`
- They `export default` a function receiving named args and returning a string
- All args are arrays of strings (may be empty)
- Function signature: `(Record<string, string[]>) => string`

### Args files
- Naming convention: `{original-name}.args.mjs`
- Must be at the same relative path as the template
- Use named exports (e.g., `export const preContent = "..."`)
- Can use global variables by exporting functions instead of values

### The `withDefaults` utility
- Wraps the template function with default values for all args
- Throws if an args file sends an unexpected argument name
- All args wrapped in arrays internally

### The `$$expr$$` convention
- `$$variableName$$` = raw expression, no quotes (e.g., `$$deployerPrivateKey$$` becomes `deployerPrivateKey`)
- `${variableName}` = string interpolation within template literals
- Used in objects like `configOverrides` to reference variables

### Rules for template args
- `preContent` (string) for imports and variable declarations
- `<name>Overrides` (object) to extend existing variables/objects
- Descriptive string args for new code/logic
- `stringify` utility for serializing objects/arrays/bigints
- `deepMerge` utility for combining objects (arrays are replaced, not concatenated)

### Complex argument patterns
- Replace object: `${stringify(replacedObj[0])}`
- Deep merge object: `${stringify(deepMerge(defaultObj, objToMerge[0]))}`
- Array spread: `${stringify(['a', 'b', ...arrayToSpread[0]])}`
- BigInt: `${stringify(someBigInt[0])}`

### Extension folder anatomy
- Normal files: copied directly to output
- Templated files: `.template.mjs` and `.args.mjs` files
- `package.json`: merged using `merge-packages` (last version wins on conflict)
- `solidity-frameworks/` folder for framework-specific files

### Available global variables in args
- `solidityFramework` - the selected Solidity framework ("hardhat" or "foundry")

Keep the response focused and concise. The main agent needs actionable information, not the full raw docs.
73 changes: 73 additions & 0 deletions .claude/agents/fetch-template-context.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
---
name: fetch-template-context
description: Fetches create-eth template sources for .args.mjs target files. Use during extension merging to understand how each args export is consumed by the corresponding template. Invoke with target file paths like "packages/nextjs/components/Header.tsx".
tools: Bash, WebFetch
model: haiku
---

You fetch template sources from the create-eth repository to help the main agent understand how .args.mjs exports are consumed by their corresponding templates.

## What you do

When invoked, you receive one or more **target file paths** (e.g., `packages/nextjs/components/Header.tsx`). For each target file, you find and fetch the corresponding `.template.mjs` source from create-eth, then return the template source and an explanation of how each arg is used.

## Step-by-step process

### 1. Fetch the template registry

Fetch `https://raw.githubusercontent.com/scaffold-eth/create-eth/main/contributors/TEMPLATE-FILES.md` using Bash:

```bash
curl -sL https://raw.githubusercontent.com/scaffold-eth/create-eth/main/contributors/TEMPLATE-FILES.md
```

### 2. Find matching templates

The registry contains markdown tables like:

```
| [(type) `Header.tsx.template.mjs`](https://github.com/.../Header.tsx.template.mjs) | [`Header.tsx.args.mjs`](https://github.com/.../Header.tsx.args.mjs) |
```

For each requested target file (e.g., `packages/nextjs/components/Header.tsx`):
- Look for a row where the template filename matches `Header.tsx.template.mjs`
- Verify the URL path contains the right directory structure (e.g., `packages/nextjs/components/`)
- Extract both the template URL and the example args URL

Templates live under these base paths in the URLs:
- `templates/base/` - shared files (nextjs, root)
- `templates/solidity-frameworks/hardhat/` - hardhat-specific
- `templates/solidity-frameworks/foundry/` - foundry-specific

### 3. Fetch the template source

Convert the GitHub URL to a raw URL:
- Replace `github.com` with `raw.githubusercontent.com`
- Remove `/blob/` from the path

Then fetch it:
```bash
curl -sL https://raw.githubusercontent.com/scaffold-eth/create-eth/main/templates/base/packages/nextjs/components/Header.tsx.template.mjs
```

Also fetch the example args file (these are in the `create-eth-extensions` repo, branch `example`).

### 4. Return results

For each target file, return:

1. **The template source code** - the complete raw source
2. **The function signature** - list the parameters of the `contents` function (these are the args the template accepts)
3. **How each arg is used** - for each parameter, explain:
- Where it's interpolated in the template output
- What type it expects (string, array, object)
- What it does (e.g., "inserted after imports", "spread into menuLinks array", "deep-merged into config")

## Important notes for the main agent

Include these notes in your response:

- **`[0]` indexing**: In template sources, args are accessed as `argName[0]`. This is because `withDefaults` wraps values in arrays (to support multiple extensions). When applying args to project files, use the value directly -- do NOT wrap in arrays.
- **`$$expr$$` convention**: Values wrapped in `$$...$$` are raw JavaScript expressions. Strip the `$$` delimiters and use as bare code (unquoted). Add corresponding imports if needed.
- **`stringify` and `deepMerge`**: Templates use these utilities from `utils.js` for serializing objects and deep-merging configs. The main agent should replicate these operations when modifying project files.
- If no matching template is found for a target file, say so clearly.
1 change: 1 addition & 0 deletions .claude/skills/add-extension/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.tmp
86 changes: 86 additions & 0 deletions .claude/skills/add-extension/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# /add-extension - SE-2 Extension Merger (Hybrid)

Claude Code skill for adding Scaffold-ETH-2 extensions to existing projects post-creation.

Uses a **hybrid approach**: a Node.js script handles deterministic operations (fetch, copy, package.json merge), while Claude handles intelligent file merging (.args.mjs processing).

**Requirements:** SE-2 project root, Git, Yarn

## Quick Start

```bash
# In SE-2 project root
/add-extension erc-20

# Preview changes first
/add-extension subgraph --dry-run

# Choose framework explicitly
/add-extension ponder -s hardhat
```

## Options

| Flag | Short | Description |
|------|-------|-------------|
| `--list` | `-L` | List all available extensions with repo info |
| `--dry-run` | `-d` | Preview changes without applying |
| `--verbose` | `-v` | Show detailed error messages |
| `--local <path>` | `-l` | Use local extension repo path |
| `--solidity-framework <name>` | `-s` | Choose hardhat/foundry (only if project has neither) |

## Available Extensions

Fetched dynamically from [create-eth](https://github.com/scaffold-eth/create-eth/blob/main/src/extensions/create-eth-extensions.ts).

Run `/add-extension --list` for current list with repository details.

## How It Works

1. **Validate** - Checks for SE-2 project (scaffold.config.ts)
2. **Registry** - Fetches extension config from create-eth registry
3. **Fetch** - Clones extension branch via git
4. **Framework** - Auto-detects hardhat/foundry from project
5. **Analyze** - Compares extension files vs project, reads .args.mjs as raw text
6. **Deterministic merge** - Script copies new files, merges package.json, registers workspaces
7. **AI merge** - Script outputs structured JSON tasks; Claude reads target files and applies .args.mjs exports intelligently

### File Handling

| File Type | Handler | Action |
|-----------|---------|--------|
| New files | Script | Copied directly |
| package.json | Script | Auto-merged (deps, scripts) |
| Workspaces | Script | Registered in root package.json |
| `.args.mjs` files | Claude | Reads exports, modifies target files |
| `.template.mjs` files | Claude | Extracts content, writes/merges target |
| File conflicts | Claude | Reads both versions, merges intelligently |

## Architecture

```
SKILL.md - Skill instructions (comprehensive .args.mjs guide)
skill.mjs - CLI entry point, orchestration, JSON output
lib/validator.mjs - SE-2 detection, registry fetching
lib/fetcher.mjs - Git clone / local path handling
lib/analyzer.mjs - File categorization, .args.mjs raw reading
lib/merger.mjs - Deterministic operations (copy, package.json merge)
lib/constants.mjs - Registry URLs, fallback extensions
```

## Development

```bash
# Test locally with dry-run
node .claude/skills/add-extension/skill.mjs erc-20 --dry-run

# Test with local extension repo
/add-extension erc-721 --local ../create-eth-extensions --dry-run
```

## Source Repositories

| Repo | Purpose |
|------|---------|
| [create-eth](https://github.com/scaffold-eth/create-eth) | SE-2 CLI, extension registry |
| [create-eth-extensions](https://github.com/scaffold-eth/create-eth-extensions) | Default extension source (each extension = git branch) |
Loading