[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6CZ6X7EVTC92B86G1YRTTTS":3,"skill-same:01M6CZ6X7EVTC92B86G1YRTTTS":141},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":48,"linkOnly":49,"markdownContent":50,"markdownBody":51,"frontMatter":52,"refName":44,"commitSha":67,"skillDirectory":68,"forksCount":69,"repositoryHtmlUrl":70,"repositoryHomepageUrl":71,"ownerHtmlUrl":72,"ownerBlogUrl":71,"ownerDescription":73,"updatedAt":74,"install":75,"resources":88},"01M6CZ6X7EVTC92B86G1YRTTTS","deploy-uni-hook",null,"Generate, simulate, audit, and deploy a Uniswap v4 hook + test pool from a brief, on any Uniswap v4 chain (every testnet and mainnet) - pre-audited templates or a from-scratch freeform hook (flags auto-derived; static audit + dangerous-pattern scan + a behavioral forge test + fork sim gate the deploy). Dry-run by default; explicit arm: to broadcast; testnet default, mainnet behind a double opt-in; records the deploy to main. Every deployed hook inherits a mandatory 10 bps AeonFee protocol fee.","aeonfun\u002Faeon","aeonfun","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F287715280?v=4","01M6CZ23C6MXGMF4N0V1DZ1247","aeon","01M6CZ23GMZP1BR424J8Y8K3DG",792,"MIT","https:\u002F\u002Fgithub.com\u002Faeonfun\u002Faeon\u002Fblob\u002Fmain\u002Fskills\u002Fdeploy-uni-hook\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000011","运维与部署","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47],"deploy","deploy uni hook","uni","hook","etherscan","mode","static","dry","host","chain","uniswap","run","audit","template","generate","onchain","notifications","api","forge","auto","main","pick","default","brief","2026-11-10 10:12:30",false,"---\nname: deploy-uni-hook\ndescription: \"Generate, simulate, audit, and deploy a Uniswap v4 hook + test pool from a brief, on any Uniswap v4 chain (every testnet and mainnet) - pre-audited templates or a from-scratch freeform hook (flags auto-derived; static audit + dangerous-pattern scan + a behavioral forge test + fork sim gate the deploy). Dry-run by default; explicit arm: to broadcast; testnet default, mainnet behind a double opt-in; records the deploy to main. Every deployed hook inherits a mandatory 10 bps AeonFee protocol fee.\"\nmetadata:\n  title: Deploy Uni Hook\n  category: crypto\n  var: \"arm: to broadcast (default is a dry-run), template:dynamic|noop|skim to force a mode, chain:\u003Cname> to pick a chain (default base-sepolia), then the hook brief. Empty prints the grammar.\"\n  tags:\n    - crypto\n    - dev\n    - onchain\n  requires:\n    - HOOK_DEPLOYER_PRIVATE_KEY?\n    - ALCHEMY_API_KEY?\n    - ETHERSCAN_API_KEY?\n  capabilities:\n    - onchain_writes\n    - writes_external_host\n    - sends_notifications\n---\n\n> **${var}** — the hook brief. Grammar: `[arm:][template:\u003Cname>] [chain:\u003Cname>] \u003Cbrief>`\n> - `` (empty) → print help and exit `DEPLOY_HOOK_EMPTY`.\n> - `\u003Cbrief>` → **dry-run**: generate, compile, mine, and simulate. Never broadcasts. *[default — no prefix]*\n> - `arm:\u003Cbrief>` → **broadcast**: do the full dry-run first, then deploy for real if the simulation passes.\n> - `template:\u003Cname>` → force a mode: `dynamic` | `noop` | `skim` (pre-audited templates) or `freeform` (build a whole hook from the prompt). Omit to auto-pick: a brief that matches a template uses it; anything else → `freeform`.\n> - `chain:\u003Cname>` → any Uniswap v4 chain in `chains.tsv` (run `.\u002Fhook-deploy.sh chains` to list). Default `base-sepolia`. Testnets: `base-sepolia`, `unichain-sepolia`, `arbitrum-sepolia`. Mainnets (`testnet: false`, e.g. `base`, `ethereum`, `unichain`, `arbitrum`, `optimism`, `polygon`, `bnb`, `avalanche`, ...) require BOTH `arm:` and an explicit `chain:` — the skill never targets mainnet by default. `base-mainnet` is accepted as an alias for `base`.\n\nToday is ${today}. This skill turns a one-line brief into a live Uniswap v4 hook. It is built to be safe: it simulates every deploy before it broadcasts, it defaults to a dry-run on testnet, and it needs an explicit `arm:` to move on-chain.\n\n## Why this design\n\nA hook binding is immutable and a bad hook can brick a pool or steal funds. So the gates sit BEFORE the deploy: two of them (`dry-run` then `arm:`), a mandatory simulation, and idempotent state. Everything after the broadcast is just recording what already happened — appended to `memory\u002Fstate\u002Fhook-deploys.json` on `main`, no PR (there is nothing left to review). The Foundry flow is the proven one — mine a CREATE2 salt so the address carries the right hook-flag bits, deploy, initialize the pool, add liquidity, run one swap.\n\n## Safety contract (do not skip)\n\n1. **Mainnet needs a triple lock.** Never target a `testnet: false` chain unless `${var}` has BOTH `arm:` AND an explicit `chain:\u003Cmainnet-name>` — AND the instance has `HOOK_MAINNET_OK=1` set as a **repo variable** (a third, operator-level lock enforced inside `hook-deploy.sh`, exit 7; store it as a variable, not a secret - a secret value of `1` masks every `1` in the run log, so tx hashes and links print as `***`). An instance that never authorized mainnet cannot broadcast there even if an armed message asks it to. This skill must only run on an instance whose inbound path is owner-gated (`TELEGRAM_ALLOWED_USER_ID` \u002F the multi-channel allowlist) — a mainnet deploy spends real gas, so an untrusted sender must never be able to dispatch it. On a mainnet chain, first read the deployer balance with `cast balance` and abort (`DEPLOY_HOOK_UNDERFUNDED`) if it cannot cover the simulation's `Estimated amount required`; `hook-deploy.sh` independently enforces a funding floor (exit 8), an optional `MAX_GAS_GWEI` gas-price ceiling (exit 9), and warns if the deployer holds more than `HOOK_MAX_FLOAT_ETH` (default 0.25) — a deploy key must hold gas float only, never LP or treasury capital. Log a clear `MAINNET` warning in the output.\n2. **Simulate before every broadcast.** If the simulation reverts, do not broadcast. Report the revert and exit `DEPLOY_HOOK_SIM_FAILED`.\n3. **Dry-run is the default.** Broadcast only when `${var}` starts with `arm:`.\n4. **Key hygiene.** The deployer key is a burner. Never print it. Never put it on a shell command line — always go through `.\u002Fhook-deploy.sh`, which reads it from the env inside the script.\n5. **Idempotency.** Before broadcasting, read `memory\u002Fstate\u002Fhook-deploys.json`. If an identical brief already deployed within the last hour, do not re-deploy. The deploy script is also idempotent at the address level: it deploys to the *canonical* address (the first flag-matching CREATE2 salt for this exact `(creationCode, flags, PoolManager)`). If that address already holds code, an identical hook is already live, so the script logs `ALREADY_DEPLOYED \u003Caddr>` and does nothing — the runner reports the existing address instead of deploying a duplicate. (HookMiner itself skips occupied addresses, so without this check a re-run would silently deploy another copy at a new address.)\n\n## Inputs and config\n\n- **Templates:** `skills\u002Fdeploy-uni-hook\u002Ftemplates\u002F` - `AeonFee.sol` (the mandatory 10 bps protocol-fee base every hook inherits), `DynamicFeeHook.sol`, `NoOpHook.sol`, `HookFeeHook.sol` (pre-audited), `Hook.sol` + `Hook.t.sol` + `hook.env.example` (freeform scaffold, behavioral-test gate, manifest), plus `DeployHook.s.sol`, `MockERC20.sol`, `foundry.toml`, `chains.tsv`.\n- **Chain config:** `skills\u002Fdeploy-uni-hook\u002Ftemplates\u002Fchains.tsv` is the single source of truth — TAB-separated `name  chainId  testnet  poolManager  stateView  rpc  explorer  alchemy`, one row per Uniswap v4 chain (staged next to `hook-deploy.sh`, which reads it). `memory\u002Funi-deployments.md` mirrors it for humans. To add a chain, append a row to `chains.tsv`.\n- **Authenticated RPC:** the `rpc` column is a public endpoint. When `ALCHEMY_API_KEY` is set and the row has an `alchemy` slug, `hook-deploy.sh` uses `https:\u002F\u002F\u003Cslug>.g.alchemy.com\u002Fv2\u002F$ALCHEMY_API_KEY` instead — a trusted RPC matters for the mainnet sim + broadcast (a lying public RPC can fake a clean sim). Precedence: `RPC_URL` (override, for testing) > Alchemy key + slug > public `rpc`. The RPC path (where the key lives) is never printed — logs show host only.\n- **Deploy helper:** `skills\u002Fdeploy-uni-hook\u002Fhook-deploy.sh` — the only sanctioned broadcast path (hides the key).\n- **State:** `memory\u002Fstate\u002Fhook-deploys.json` — idempotency + the deploy ledger.\n\n### Template picker (when `template:` is not given)\n\n| Brief mentions | Mode |\n|---|---|\n| fee, volatility, dynamic, surge | `dynamic` |\n| skim, hook fee, take a cut, revenue | `skim` |\n| \"minimal\" \u002F \"starter\" \u002F \"empty\" | `noop` |\n| game, leaderboard, points, crown, loyalty | `freeform` (game rules in Labs routing) |\n| anything else (novel logic the templates don't cover) | `freeform` |\n\n## Mandatory AeonFee (every hook)\n\nEvery hook this skill deploys inherits `AeonFee` (`templates\u002FAeonFee.sol`): a MANDATORY 10 bps (0.10%) protocol fee taken in `afterSwap` on the swap's unspecified (output) currency and routed to `AEON_FEE_RECIPIENT` (`0xF1E958db7D1e4C074377946018Ad645db4FB158e`). The rate and recipient are compile-time constants and `afterSwap` is NOT virtual, so no hook can lower, skip, or redirect it. A hook adds its own post-swap logic through `_afterSwapExtra` (which runs AFTER the fee), and any hook fee it charges stacks ON TOP of the 10 bps.\n\nBecause the fee is a return-delta `take()`, EVERY aeon hook's address carries `AFTER_SWAP + AFTER_SWAP_RETURNS_DELTA` (`0x44`) - so **no aeon hook is Uniswap Labs auto-routable**; every one needs the allowlist \u002F a UniswapX filler (see Labs routing below). This is the deliberate trade for a fee that can never be bypassed.\n\n## Labs routing\n\nUniswap Labs auto-routes a hooked pool unless the address starts with `0x91`, or the hook uses `beforeSwapReturnsDelta`, `afterSwapReturnsDelta`, or `dynamicFees`. Anything in that set needs the [allowlist form](https:\u002F\u002Fwww.notion.so\u002Funiswaplabs\u002F1aec52b2548b80f78dbef8d2f0d7183e) or a UniswapX filler. Because AeonFee makes every hook an `afterSwapReturnsDelta` take, **no template auto-routes** - all are allowlist.\n\n| Template | Flags | Labs classic router |\n|---|---|---|\n| `noop` | `0xC4` (beforeSwap + AeonFee `0x44`) | allowlist (`afterSwapReturnsDelta`) |\n| freeform default (`_afterSwapExtra`) | `0x44` (AeonFee) | allowlist (`afterSwapReturnsDelta`) |\n| `dynamic` | `0x10C4` (`0x10C0` + AeonFee `0x04`) + `DYNAMIC_FEE_FLAG` | allowlist (`dynamicFees` + `afterSwapReturnsDelta`) |\n| `skim` | `0x44` (AeonFee + own skim, same bits) | allowlist (`afterSwapReturnsDelta`) |\n\n**Game on a hook** (freeform): the 10 bps fee already runs in the base `afterSwap` via `take()` - a freeform body must NOT implement `afterSwap` (put extra logic in `_afterSwapExtra`).\n1. The mandatory fee is always taken; a hook's own extra fee also goes in `_afterSwapExtra` and stacks on top.\n2. Game runs only when `hookData` names a player. Empty `hookData` (Labs Universal Router) = paid swap, no game, no revert.\n3. Never encode the game in `amountSpecified`, block number, or a required swap direction. Those revert the router and collect nothing.\n4. `sender` is the router, not the user. Do not key game state off `sender`.\n\nDo not generate amount-suffix \u002F block-echo \u002F exact-out-only \u002F direction-gate hooks unless the brief explicitly asks for a revert-gate. The miner skips `0x91...` addresses.\n\n## Fleet audit rules (from aeon.fun hook audits)\n\nThese are standing defects measured on the live fleet. Freeform MUST NOT recreate them. The `skim` template is already patched.\n\n**Fee \u002F `take()`:**\n- Charge the MAGNITUDE of the unspecified delta. Exact-out makes that delta negative. `if (unspecifiedAmount \u003C= 0) return` silently skips the fee on every exact-output swap (shared-base F1).\n- Widen to `int256` before negating. `-type(int128).min` panics and bricks that swap.\n- `poolManager.take(..., feeRecipient, ...)` to an immutable recipient. NEVER `address(this)`. No `withdraw()`. Custody was the CrownClash\u002FLegacyLedger HIGH.\n- An extra skim helper must not copy a `\u003C= 0` early return (second copy of the sign guard).\n\n**Gates** (only if the brief demands a revert-gate):\n- 0. A revert-gate hook that rejects the pre-broadcast seed probe on purpose must declare `HOOK_REVERT_GATE=1` in `$HOOKBUILD_DIR\u002Fhook.env`. Without it, a skipped probe is treated as a bug and simulation exits `1` (`DEPLOY_HOOK_SIM_FAILED`). The flag's only effect is to permit that intentional `SEED_SWAP_SKIPPED` during simulate; it suppresses nothing else. During broadcast the condition only warns and continues (the hook, pool and liquidity are already onchain), so the receipt and explorer verification still run.\n- 1a. Value that moves on its own (`block.number`): a `view` helper answered at head N is wrong at execution N+1. Target the execution block.\n- 1b. Value that moves when someone swaps (price low byte): exact match + zero tolerance is a contention DoS. Need a band, or do not gate.\n- 1c. Shared counter an attacker can park, not advanced on failure: griefing primitive.\n- 2. A contract in the `unlock` frame can satisfy the predicate; a signed tx cannot. That binds the wrong party.\n- 5. Never compare raw `amountSpecified` to a token-denominated constant. The caller picks the specified currency via exact-in vs exact-out. Use a dimensionless bound (tick move \u002F liquidity fraction).\n- 6. A \"balance\" \u002F \"skew\" \u002F \"heavier-side\" gate on the two virtual reserves is a raw-PRICE gate in disguise. `StateLibrary` gives `amount0 = L*2^96\u002FsqrtP` and `amount1 = L*sqrtP\u002F2^96`, so `amount0\u002Famount1 = 1\u002Fprice` and the liquidity `L` cancels exactly. Any test on the two reserves (`b0 >= b1`, a skew band, \"which side is heavier\") therefore reduces to comparing the pool's RAW price to an implicit `1.0`, and raw price is `token1\u002Ftoken0` in smallest units, so it is ~1.0 only for a same-decimals pair near parity. A USDC(6d)\u002FWETH(18d) pool sits ~8 orders of magnitude off; two 18-dec tokens at price 2.0 are already outside a 10% band. Such a gate is permanently one-directional on every real pair: one whole leg reverts forever, and \"every trade rebalances toward 50\u002F50\" is false (a full-range position is already 50\u002F50 by value at any price). Fix: snapshot the pool's OWN reference (its `sqrtPriceX96` at `afterInitialize`, or an explicit target ratio from the brief) and gate the current price against THAT, never a hard-coded 1.0. This needs the `afterInitialize` callback (adds flag bit `0x1000`), so a price\u002Fbalance\u002Fskew hook must include it in the callback set or it cannot know its own starting price.\n- Never `balanceOf(poolManager)`: that is the v4 singleton's global inventory, not this pool. Use `StateLibrary`.\n- `sender` is the router. Do not treat it as the trader.\n\n**Tests:**\n- A fee hook must assert the take on exact-in AND exact-out.\n- A gate needs a hookless negative control (`hooks = address(0)`).\n- Do not cache `block.number` across `vm.roll` (via-ir folds it). Use `vm.getBlockNumber()`.\n- A price \u002F balance \u002F skew gate MUST be asserted at a price away from 1:1. The scaffold's `setUp()` pool starts at 1:1 (`sqrtPriceX96 = 2^96`), the single price where a raw-price-vs-1.0 gate looks correct no matter how it is written. Call `_freshPoolAt(\u003Cnon-1:1 sqrtPriceX96>)` (helper in `Hook.t.sol`) and assert BOTH legs there: the leg that must stay open is not rejected, the leg that must close reverts. A gate proven only at 1:1 is a false pass.\n\n\n\n## Steps\n\n1. **Parse `${var}`.** Extract the `arm:` flag, the optional `template:`, the optional `chain:`, and the free-text brief. Empty brief → exit `DEPLOY_HOOK_EMPTY` with the grammar.\n\n2. **Resolve the chain.** The chain name resolves in `chains.tsv` (default `base-sepolia`); `hook-deploy.sh` maps it to the official `PoolManager` + RPC, so you pass the NAME, not the address. Run `.\u002Fhook-deploy.sh chains` to see the list, or read `chains.tsv`. If the name is not in the registry, exit `DEPLOY_HOOK_BAD_CHAIN`. Look up the row's `testnet` column: if it is `false` (mainnet), enforce the double opt-in — require BOTH `arm:` and an explicit `chain:` in `${var}`, else exit `DEPLOY_HOOK_BAD_CHAIN`. Every Uniswap v4 chain is supported (Base, Ethereum, Unichain, Arbitrum, Optimism, Polygon, BNB, Avalanche, Robinhood, Worldchain, Ink, Soneium, Celo, X Layer + their testnets).\n\n3. **Confirm the staged toolchain + project.** The workflow pre-stages everything before this run (`scripts\u002Fstage-deploy-uni-hook.sh`): Foundry on `$PATH`, a pre-built v4 project at `$HOOKBUILD_DIR` (default `$HOME\u002Fhookbuild`) holding all three templates + `MockERC20.sol` + `DeployHook.s.sol` + the v4 libraries, and `.\u002Fhook-deploy.sh` copied to the repo root. Do **not** install Foundry or clone the libs in-run — the sandbox blocks that. Check `command -v forge` and that `$HOOKBUILD_DIR` exists; if either is missing, degrade to `DEPLOY_HOOK_NO_TOOLCHAIN` (emit the generated source + plan).\n\n4. **Build the hook (brief-driven).**\n   - **Template mode** (`dynamic` \u002F `noop` \u002F `skim`): in `$HOOKBUILD_DIR\u002Fsrc\u002F\u003CHook>.sol`, edit ONLY the region between `\u002F\u002F --- AEON:LOGIC START ---` and `\u002F\u002F --- AEON:LOGIC END ---`. Keep the callback signatures and flag set unchanged. If the default already fits the brief, leave it.\n   - **Freeform mode** (anything else): write the whole hook into `$HOOKBUILD_DIR\u002Fsrc\u002FHook.sol`, replacing the `\u002F\u002F --- AEON:BODY ... ---` region. Rules: keep the contract as `contract Hook is AeonFee` and the constructor as `constructor(IPoolManager _pm) AeonFee(_pm)`. Do NOT implement `afterSwap`, `poolManager`, `onlyPoolManager`, or `NotPoolManager` - they come from `AeonFee` and the mandatory 10 bps fee is taken automatically (the audit rejects a Hook that is not `is AeonFee`, and rejects a redeclared `afterSwap`). For post-swap logic override `_afterSwapExtra` (return 0, or an additional delta the hook itself `take`s). Implement any OTHER v4 callbacks the prompt needs, each with the EXACT `IHooks` signature, `onlyPoolManager`, and the right selector return (`SwapParams`\u002F`ModifyLiquidityParams` import from `@uniswap\u002Fv4-core\u002Fsrc\u002Ftypes\u002FPoolOperation.sol`, not nested in `IPoolManager` - that nesting was removed in v4-core's own PR #964). Do NOT hand-set flags - they are auto-derived from your callbacks (plus the always-on AeonFee `afterSwap`\u002F`afterSwapReturnsDelta` bits). If another callback returns a non-zero delta, set `HOOK_RETURNS_DELTA` in `$HOOKBUILD_DIR\u002Fhook.env`; for a fee-override hook set `HOOK_POOL_FEE=dynamic` there. Follow **Labs routing** and **Fleet audit rules**: empty `hookData` must succeed; a game must not revert a vanilla exact-in swap; an extra `take()` (in `_afterSwapExtra`) must charge magnitude (exact-in and exact-out) and never custody; a price\u002Fbalance\u002Fskew gate must add the `afterInitialize` callback and anchor to the pool's own start price (Gates rule 6), never an implicit 1.0.\n     - **Also write the behavioral test.** In `$HOOKBUILD_DIR\u002Ftest\u002FHook.t.sol`, replace the `\u002F\u002F --- AEON:ASSERT ... ---` region with `test_*` functions that assert the hook's SPECIFIC intended behavior — not just \"does not revert\". For every rule in the brief write at least one positive and one negative case: a swap the hook must REJECT as `_expectSwapRevert(zeroForOne, amount, Hook.SomeError.selector)` (this helper unwraps v4's `WrappedError` for you — do NOT use bare `vm.expectRevert`, it won't match the wrapper); a swap it must ALLOW as a plain `_swap(...)`; any getter\u002Faccounting as `assertEq(hook.someGetter(...), expected)`. For a gate whose decision depends on price or reserve balance, assert it through `_freshPoolAt(\u003Cnon-1:1 sqrtPriceX96>)` (both legs, off parity) - `setUp()`'s pool is at 1:1, where such a gate always looks correct. Do NOT edit `setUp()` or the helpers - only the `AEON:ASSERT` region. If the brief has no rejectable behavior, still assert the observable state the hook changes.\n\n5. **Simulate + audit (always).** Pass mode, kind, and chain (chain omitted = `base-sepolia`):\n   ```bash\n   .\u002Fhook-deploy.sh simulate \u003Ckind> \u003Cchain>\n   ```\n   For `freeform` this runs, in order, three gates before any deploy:\n   1. **Static audit** - derives the flags from the callbacks; checks the contract is named `Hook`, is `is AeonFee` (mandatory fee) and does not redeclare `afterSwap`, has ≥1 callback or `_afterSwapExtra`, every callback carries `onlyPoolManager`, `test\u002FHook.t.sol` has ≥1 `test_` function, and scans for dangerous patterns (`selfdestruct`\u002F`delegatecall` are hard fails; `tx.origin`\u002Fraw value-call\u002Finline `assembly` print a warning to review). A failure exits `DEPLOY_HOOK_AUDIT_FAILED` (never deploy).\n   2. **Behavioral test** — `forge test --fork-url \u003Cchain> --match-contract HookBehaviorTest` runs the agent-written assertions on a fork. A failing OR non-compiling test exits `DEPLOY_HOOK_TEST_FAILED` (never deploy). This proves the hook does what the prompt asked.\n   3. **Fork simulation** — `forge script` compiles, mines the salt, deploys in-memory, initializes the pool, adds liquidity, and runs one swap against a fork of the target chain.\n   On a compile error, fix and retry (max 3). On a sim revert, exit `DEPLOY_HOOK_SIM_FAILED`. Capture the mined hook address, the derived flags, and the `Estimated amount required`. On mainnet, compare that estimate to the deployer balance (`cast balance \u003Caddr> --rpc-url \u003Crpc>`) and exit `DEPLOY_HOOK_UNDERFUNDED` if it will not cover it.\n   For a freeform hook, also **read the generated `Hook.sol` and reason about safety** before arming: does any callback let a caller steal funds, brick the pool (unconditional revert), or reenter? If unsure, stop at the dry-run and report the concern.\n\n6. **Dry-run stop.** If `${var}` did NOT start with `arm:`, STOP here. Report: template, mined address (with its flag bits), the receipt `routing` line (auto-route vs allowlist + reason), the pool key, and the simulation result. Exit `DEPLOY_HOOK_DRY_RUN`.\n\n7. **Arm checks (only if `arm:`).**\n   - Confirm `HOOK_DEPLOYER_PRIVATE_KEY` is set (it is injected via `requires:`). If not, degrade to the dry-run report and exit `DEPLOY_HOOK_NO_KEY`.\n   - Read `memory\u002Fstate\u002Fhook-deploys.json`. If the same `(chain, template, brief)` deployed in the last hour, exit `DEPLOY_HOOK_IDEMPOTENT` with the prior address.\n\n8. **Broadcast.**\n   ```bash\n   .\u002Fhook-deploy.sh broadcast \u003Ckind> \u003Cchain>\n   ```\n   The runner prints a **deploy receipt** (hook address, decoded flag names, explorer deep-link, tx hashes) and, when `ETHERSCAN_API_KEY` is set on an Etherscan-family chain, **auto-verifies** the hook source on the explorer (best-effort — a failed verify never fails a completed deploy). If it printed `ALREADY_DEPLOYED`, treat the reported address as the result (no new deploy). Read the hook address and the transaction hashes from the receipt or `$HOOKBUILD_DIR\u002Fbroadcast\u002FDeployHook.s.sol\u002F\u003CchainId>\u002Frun-latest.json`.\n\n9. **Verify.** With `cast`, read the pool back through `StateView.getSlot0(poolId)` on the RPC. Confirm the pool exists and the hook address low bits equal the template's flags. Confirm the swap emitted the hook event.\n\n10. **Record the deploy.** The deploy already happened on-chain — this is append-only history, not a change to review, so DO NOT open a PR or a branch. Just write the record into the working tree on `main`; the workflow's post-run commit lands it. Write:\n    - `memory\u002Fstate\u002Fhook-deploys.json` — append this deploy (chain, template, brief, hook address, flags, tx hashes, timestamp, poolId, poolKey).\n    - `output\u002Fhooks\u002F\u003Chook-address>.sol` — copy the deployed source from `$HOOKBUILD_DIR\u002Fsrc\u002F\u003CHook>.sol`.\n    - For freeform, also `output\u002Fhooks\u002F\u003Chook-address>.t.sol` — copy `$HOOKBUILD_DIR\u002Ftest\u002FHook.t.sol` (the behavioral test that gated the deploy).\n\n    Do NOT stage the root `.\u002Fhook-deploy.sh` or `.\u002Fchains.tsv` (runtime copies; both gitignored).\n\n11. **Publish to the public hook list (live mainnet deploys only).** If this was a real broadcast (not a dry-run) to a mainnet chain the registry supports (`ethereum base robinhood monad bnb arbitrum unichain`), list the hook on `aeonfun\u002Funiv4-hooks` so it appears on the aeon hook marketplace. Reuse the `submit-hook` skill's helper - it decodes the flags from the address, formats the entry, regenerates the registry, and opens a PR (issue fallback when there is no push access):\n    ```bash\n    python3 skills\u002Fsubmit-hook\u002Fsubmit-univ4.py \\\n      --address \"$HOOK_ADDR\" --chain \"$CHAIN\" \\\n      --name \"$NAME\" --category \"$CATEGORY\" --klass \"$KLASS\" \\\n      --template \"$TEMPLATE\" --stage deployed --source aeon --verified \\\n      --date \"$(date -u +%F)\" \\\n      --mechanic \"$MECHANIC\" --plain \"$PLAIN\" --rule \"$RULE1\" --rule \"$RULE2\"\n    ```\n    Derive `name`\u002F`category`\u002F`klass`\u002F`mechanic`\u002F`plain`\u002F`rules` from the brief exactly as `skills\u002Fsubmit-hook\u002FSKILL.md` describes. This is best-effort: a submission failure must NEVER fail a completed deploy - log it and continue. Skip entirely on a dry-run, a testnet, or an unsupported chain.\n\n12. **Notify + exit.** Send a short notification (template, address, explorer link, `routing` class, dry-run vs live, and the hook-list PR URL when one was opened). Exit `DEPLOY_HOOK_OK` (or `DEPLOY_HOOK_DRY_RUN`).\n\n## Degrade rules\n\n- No key → dry-run report, `DEPLOY_HOOK_NO_KEY`. Never fail hard.\n- Foundry or the staged project missing (`command -v forge` fails or `$HOOKBUILD_DIR` absent) → emit the generated source + plan, `DEPLOY_HOOK_NO_TOOLCHAIN`. Do not try to install in-run (the sandbox blocks it).\n- Bad\u002Fmissing chain, or mainnet without the double opt-in → `DEPLOY_HOOK_BAD_CHAIN`.\n- Mainnet chain but the instance did not set `HOOK_MAINNET_OK=1` (`hook-deploy.sh` exit 7) → `DEPLOY_HOOK_MAINNET_NOT_AUTHORIZED` (never broadcast).\n- Mainnet balance below the simulation estimate, or the deployer is unfunded (`hook-deploy.sh` exit 8) → `DEPLOY_HOOK_UNDERFUNDED` (never broadcast).\n- Gas price above `MAX_GAS_GWEI` (`hook-deploy.sh` exit 9) → `DEPLOY_HOOK_GAS_TOO_HIGH` (never broadcast; retry when fees drop).\n- Freeform static audit fails (bad name \u002F no callback \u002F missing `onlyPoolManager` \u002F no `test_` \u002F `selfdestruct` \u002F `delegatecall`) → `DEPLOY_HOOK_AUDIT_FAILED` (never deploy).\n- Freeform behavioral test fails or does not compile → `DEPLOY_HOOK_TEST_FAILED` (never deploy).\n- Simulation revert → `DEPLOY_HOOK_SIM_FAILED` (never broadcast after a failed sim).\n- Seed probe skipped during simulation and not declared intentional (`hook-deploy.sh` exit 1, logs `SEED_SWAP_SKIPPED`) → `DEPLOY_HOOK_SIM_FAILED`. A revert-gate hook rejecting the probe on purpose must set `HOOK_REVERT_GATE=1` in `hook.env` to pass; the caught revert bytes are logged beside the marker so the operator can tell an intentional gate from a broken probe. During **broadcast** this same condition only warns and continues — the deploy is already onchain, so exiting would strand it with no receipt or explorer verification.\n\n## Notes\n\n- The three templates are pre-validated: each compiles and simulates a full deploy + swap on Base Sepolia. All inherit `AeonFee`, so all carry the return-delta bits and are allowlist (`dynamic` = 0x10C4; `noop` = 0xC4; `skim` = 0x44).\n- **Freeform** builds an arbitrary hook from the prompt into `src\u002FHook.sol` and its behavioral test into `test\u002FHook.t.sol`. Flags are auto-derived from the callbacks (never hand-set). Three gates run before any deploy: a static audit (name\u002Fcallbacks\u002F`onlyPoolManager`\u002Ftest-present\u002Fdangerous-pattern scan), the agent-written `forge test` behavioral assertions on a fork, then the fork simulation. The agent also reads the generated source for steal\u002Fbrick\u002Freentrancy risk before arming. Prefer a matching template when one fits (they are audited); use freeform for novel logic.\n- Every deploy — template or freeform — always simulates on the target chain's fork first, so \"does it work\" is checked before any broadcast.\n- **Any Uniswap v4 chain works.** `chains.tsv` carries every official v4 deployment (Base, Ethereum, Unichain, Arbitrum, Optimism, Polygon, BNB, Avalanche, Robinhood, Worldchain, Ink, Soneium, Celo, X Layer + the Sepolia testnets), each verified to hold the PoolManager. The same flow runs on all of them — only the `PoolManager`\u002FRPC differ, resolved by name. The CREATE2 deployer (`0x4e59…4956C`) is required for the mined address; if a chain lacks it the fork simulation fails closed before any broadcast.\n- **Mainnet is gas-only.** The deploy mints its own `MockERC20` tokens to itself (free) and seeds the demo pool with those mock tokens — a mainnet broadcast risks GAS ONLY, never real capital. The deployed pool is a MockA\u002FMockB demo; the reusable hook contract is the real deliverable. The deployer key must be a funded burner holding gas float only (the runner warns above `HOOK_MAX_FLOAT_ETH`); mainnet also needs the `HOOK_MAINNET_OK=1` operator lock. A future version can add the keyless Base MCP `send_calls` rail so no key sits in the runner.\n- **Authenticated RPC + receipt + verify.** On mainnet the runner prefers an Alchemy endpoint (`ALCHEMY_API_KEY` + the chain's `alchemy` slug) over the public RPC, so a lying public node can't fake a clean sim. After a broadcast it prints a receipt (address, decoded flags, explorer link, tx hashes) and, with `ETHERSCAN_API_KEY` on an Etherscan-family chain, auto-verifies the source (best-effort). All of this is opt-in: with no keys set the skill still runs on public RPCs, unverified.\n","> **${var}** — the hook brief. Grammar: `[arm:][template:\u003Cname>] [chain:\u003Cname>] \u003Cbrief>`\n> - `` (empty) → print help and exit `DEPLOY_HOOK_EMPTY`.\n> - `\u003Cbrief>` → **dry-run**: generate, compile, mine, and simulate. Never broadcasts. *[default — no prefix]*\n> - `arm:\u003Cbrief>` → **broadcast**: do the full dry-run first, then deploy for real if the simulation passes.\n> - `template:\u003Cname>` → force a mode: `dynamic` | `noop` | `skim` (pre-audited templates) or `freeform` (build a whole hook from the prompt). Omit to auto-pick: a brief that matches a template uses it; anything else → `freeform`.\n> - `chain:\u003Cname>` → any Uniswap v4 chain in `chains.tsv` (run `.\u002Fhook-deploy.sh chains` to list). Default `base-sepolia`. Testnets: `base-sepolia`, `unichain-sepolia`, `arbitrum-sepolia`. Mainnets (`testnet: false`, e.g. `base`, `ethereum`, `unichain`, `arbitrum`, `optimism`, `polygon`, `bnb`, `avalanche`, ...) require BOTH `arm:` and an explicit `chain:` — the skill never targets mainnet by default. `base-mainnet` is accepted as an alias for `base`.\n\nToday is ${today}. This skill turns a one-line brief into a live Uniswap v4 hook. It is built to be safe: it simulates every deploy before it broadcasts, it defaults to a dry-run on testnet, and it needs an explicit `arm:` to move on-chain.\n\n## Why this design\n\nA hook binding is immutable and a bad hook can brick a pool or steal funds. So the gates sit BEFORE the deploy: two of them (`dry-run` then `arm:`), a mandatory simulation, and idempotent state. Everything after the broadcast is just recording what already happened — appended to `memory\u002Fstate\u002Fhook-deploys.json` on `main`, no PR (there is nothing left to review). The Foundry flow is the proven one — mine a CREATE2 salt so the address carries the right hook-flag bits, deploy, initialize the pool, add liquidity, run one swap.\n\n## Safety contract (do not skip)\n\n1. **Mainnet needs a triple lock.** Never target a `testnet: false` chain unless `${var}` has BOTH `arm:` AND an explicit `chain:\u003Cmainnet-name>` — AND the instance has `HOOK_MAINNET_OK=1` set as a **repo variable** (a third, operator-level lock enforced inside `hook-deploy.sh`, exit 7; store it as a variable, not a secret - a secret value of `1` masks every `1` in the run log, so tx hashes and links print as `***`). An instance that never authorized mainnet cannot broadcast there even if an armed message asks it to. This skill must only run on an instance whose inbound path is owner-gated (`TELEGRAM_ALLOWED_USER_ID` \u002F the multi-channel allowlist) — a mainnet deploy spends real gas, so an untrusted sender must never be able to dispatch it. On a mainnet chain, first read the deployer balance with `cast balance` and abort (`DEPLOY_HOOK_UNDERFUNDED`) if it cannot cover the simulation's `Estimated amount required`; `hook-deploy.sh` independently enforces a funding floor (exit 8), an optional `MAX_GAS_GWEI` gas-price ceiling (exit 9), and warns if the deployer holds more than `HOOK_MAX_FLOAT_ETH` (default 0.25) — a deploy key must hold gas float only, never LP or treasury capital. Log a clear `MAINNET` warning in the output.\n2. **Simulate before every broadcast.** If the simulation reverts, do not broadcast. Report the revert and exit `DEPLOY_HOOK_SIM_FAILED`.\n3. **Dry-run is the default.** Broadcast only when `${var}` starts with `arm:`.\n4. **Key hygiene.** The deployer key is a burner. Never print it. Never put it on a shell command line — always go through `.\u002Fhook-deploy.sh`, which reads it from the env inside the script.\n5. **Idempotency.** Before broadcasting, read `memory\u002Fstate\u002Fhook-deploys.json`. If an identical brief already deployed within the last hour, do not re-deploy. The deploy script is also idempotent at the address level: it deploys to the *canonical* address (the first flag-matching CREATE2 salt for this exact `(creationCode, flags, PoolManager)`). If that address already holds code, an identical hook is already live, so the script logs `ALREADY_DEPLOYED \u003Caddr>` and does nothing — the runner reports the existing address instead of deploying a duplicate. (HookMiner itself skips occupied addresses, so without this check a re-run would silently deploy another copy at a new address.)\n\n## Inputs and config\n\n- **Templates:** `skills\u002Fdeploy-uni-hook\u002Ftemplates\u002F` - `AeonFee.sol` (the mandatory 10 bps protocol-fee base every hook inherits), `DynamicFeeHook.sol`, `NoOpHook.sol`, `HookFeeHook.sol` (pre-audited), `Hook.sol` + `Hook.t.sol` + `hook.env.example` (freeform scaffold, behavioral-test gate, manifest), plus `DeployHook.s.sol`, `MockERC20.sol`, `foundry.toml`, `chains.tsv`.\n- **Chain config:** `skills\u002Fdeploy-uni-hook\u002Ftemplates\u002Fchains.tsv` is the single source of truth — TAB-separated `name  chainId  testnet  poolManager  stateView  rpc  explorer  alchemy`, one row per Uniswap v4 chain (staged next to `hook-deploy.sh`, which reads it). `memory\u002Funi-deployments.md` mirrors it for humans. To add a chain, append a row to `chains.tsv`.\n- **Authenticated RPC:** the `rpc` column is a public endpoint. When `ALCHEMY_API_KEY` is set and the row has an `alchemy` slug, `hook-deploy.sh` uses `https:\u002F\u002F\u003Cslug>.g.alchemy.com\u002Fv2\u002F$ALCHEMY_API_KEY` instead — a trusted RPC matters for the mainnet sim + broadcast (a lying public RPC can fake a clean sim). Precedence: `RPC_URL` (override, for testing) > Alchemy key + slug > public `rpc`. The RPC path (where the key lives) is never printed — logs show host only.\n- **Deploy helper:** `skills\u002Fdeploy-uni-hook\u002Fhook-deploy.sh` — the only sanctioned broadcast path (hides the key).\n- **State:** `memory\u002Fstate\u002Fhook-deploys.json` — idempotency + the deploy ledger.\n\n### Template picker (when `template:` is not given)\n\n| Brief mentions | Mode |\n|---|---|\n| fee, volatility, dynamic, surge | `dynamic` |\n| skim, hook fee, take a cut, revenue | `skim` |\n| \"minimal\" \u002F \"starter\" \u002F \"empty\" | `noop` |\n| game, leaderboard, points, crown, loyalty | `freeform` (game rules in Labs routing) |\n| anything else (novel logic the templates don't cover) | `freeform` |\n\n## Mandatory AeonFee (every hook)\n\nEvery hook this skill deploys inherits `AeonFee` (`templates\u002FAeonFee.sol`): a MANDATORY 10 bps (0.10%) protocol fee taken in `afterSwap` on the swap's unspecified (output) currency and routed to `AEON_FEE_RECIPIENT` (`0xF1E958db7D1e4C074377946018Ad645db4FB158e`). The rate and recipient are compile-time constants and `afterSwap` is NOT virtual, so no hook can lower, skip, or redirect it. A hook adds its own post-swap logic through `_afterSwapExtra` (which runs AFTER the fee), and any hook fee it charges stacks ON TOP of the 10 bps.\n\nBecause the fee is a return-delta `take()`, EVERY aeon hook's address carries `AFTER_SWAP + AFTER_SWAP_RETURNS_DELTA` (`0x44`) - so **no aeon hook is Uniswap Labs auto-routable**; every one needs the allowlist \u002F a UniswapX filler (see Labs routing below). This is the deliberate trade for a fee that can never be bypassed.\n\n## Labs routing\n\nUniswap Labs auto-routes a hooked pool unless the address starts with `0x91`, or the hook uses `beforeSwapReturnsDelta`, `afterSwapReturnsDelta`, or `dynamicFees`. Anything in that set needs the [allowlist form](https:\u002F\u002Fwww.notion.so\u002Funiswaplabs\u002F1aec52b2548b80f78dbef8d2f0d7183e) or a UniswapX filler. Because AeonFee makes every hook an `afterSwapReturnsDelta` take, **no template auto-routes** - all are allowlist.\n\n| Template | Flags | Labs classic router |\n|---|---|---|\n| `noop` | `0xC4` (beforeSwap + AeonFee `0x44`) | allowlist (`afterSwapReturnsDelta`) |\n| freeform default (`_afterSwapExtra`) | `0x44` (AeonFee) | allowlist (`afterSwapReturnsDelta`) |\n| `dynamic` | `0x10C4` (`0x10C0` + AeonFee `0x04`) + `DYNAMIC_FEE_FLAG` | allowlist (`dynamicFees` + `afterSwapReturnsDelta`) |\n| `skim` | `0x44` (AeonFee + own skim, same bits) | allowlist (`afterSwapReturnsDelta`) |\n\n**Game on a hook** (freeform): the 10 bps fee already runs in the base `afterSwap` via `take()` - a freeform body must NOT implement `afterSwap` (put extra logic in `_afterSwapExtra`).\n1. The mandatory fee is always taken; a hook's own extra fee also goes in `_afterSwapExtra` and stacks on top.\n2. Game runs only when `hookData` names a player. Empty `hookData` (Labs Universal Router) = paid swap, no game, no revert.\n3. Never encode the game in `amountSpecified`, block number, or a required swap direction. Those revert the router and collect nothing.\n4. `sender` is the router, not the user. Do not key game state off `sender`.\n\nDo not generate amount-suffix \u002F block-echo \u002F exact-out-only \u002F direction-gate hooks unless the brief explicitly asks for a revert-gate. The miner skips `0x91...` addresses.\n\n## Fleet audit rules (from aeon.fun hook audits)\n\nThese are standing defects measured on the live fleet. Freeform MUST NOT recreate them. The `skim` template is already patched.\n\n**Fee \u002F `take()`:**\n- Charge the MAGNITUDE of the unspecified delta. Exact-out makes that delta negative. `if (unspecifiedAmount \u003C= 0) return` silently skips the fee on every exact-output swap (shared-base F1).\n- Widen to `int256` before negating. `-type(int128).min` panics and bricks that swap.\n- `poolManager.take(..., feeRecipient, ...)` to an immutable recipient. NEVER `address(this)`. No `withdraw()`. Custody was the CrownClash\u002FLegacyLedger HIGH.\n- An extra skim helper must not copy a `\u003C= 0` early return (second copy of the sign guard).\n\n**Gates** (only if the brief demands a revert-gate):\n- 0. A revert-gate hook that rejects the pre-broadcast seed probe on purpose must declare `HOOK_REVERT_GATE=1` in `$HOOKBUILD_DIR\u002Fhook.env`. Without it, a skipped probe is treated as a bug and simulation exits `1` (`DEPLOY_HOOK_SIM_FAILED`). The flag's only effect is to permit that intentional `SEED_SWAP_SKIPPED` during simulate; it suppresses nothing else. During broadcast the condition only warns and continues (the hook, pool and liquidity are already onchain), so the receipt and explorer verification still run.\n- 1a. Value that moves on its own (`block.number`): a `view` helper answered at head N is wrong at execution N+1. Target the execution block.\n- 1b. Value that moves when someone swaps (price low byte): exact match + zero tolerance is a contention DoS. Need a band, or do not gate.\n- 1c. Shared counter an attacker can park, not advanced on failure: griefing primitive.\n- 2. A contract in the `unlock` frame can satisfy the predicate; a signed tx cannot. That binds the wrong party.\n- 5. Never compare raw `amountSpecified` to a token-denominated constant. The caller picks the specified currency via exact-in vs exact-out. Use a dimensionless bound (tick move \u002F liquidity fraction).\n- 6. A \"balance\" \u002F \"skew\" \u002F \"heavier-side\" gate on the two virtual reserves is a raw-PRICE gate in disguise. `StateLibrary` gives `amount0 = L*2^96\u002FsqrtP` and `amount1 = L*sqrtP\u002F2^96`, so `amount0\u002Famount1 = 1\u002Fprice` and the liquidity `L` cancels exactly. Any test on the two reserves (`b0 >= b1`, a skew band, \"which side is heavier\") therefore reduces to comparing the pool's RAW price to an implicit `1.0`, and raw price is `token1\u002Ftoken0` in smallest units, so it is ~1.0 only for a same-decimals pair near parity. A USDC(6d)\u002FWETH(18d) pool sits ~8 orders of magnitude off; two 18-dec tokens at price 2.0 are already outside a 10% band. Such a gate is permanently one-directional on every real pair: one whole leg reverts forever, and \"every trade rebalances toward 50\u002F50\" is false (a full-range position is already 50\u002F50 by value at any price). Fix: snapshot the pool's OWN reference (its `sqrtPriceX96` at `afterInitialize`, or an explicit target ratio from the brief) and gate the current price against THAT, never a hard-coded 1.0. This needs the `afterInitialize` callback (adds flag bit `0x1000`), so a price\u002Fbalance\u002Fskew hook must include it in the callback set or it cannot know its own starting price.\n- Never `balanceOf(poolManager)`: that is the v4 singleton's global inventory, not this pool. Use `StateLibrary`.\n- `sender` is the router. Do not treat it as the trader.\n\n**Tests:**\n- A fee hook must assert the take on exact-in AND exact-out.\n- A gate needs a hookless negative control (`hooks = address(0)`).\n- Do not cache `block.number` across `vm.roll` (via-ir folds it). Use `vm.getBlockNumber()`.\n- A price \u002F balance \u002F skew gate MUST be asserted at a price away from 1:1. The scaffold's `setUp()` pool starts at 1:1 (`sqrtPriceX96 = 2^96`), the single price where a raw-price-vs-1.0 gate looks correct no matter how it is written. Call `_freshPoolAt(\u003Cnon-1:1 sqrtPriceX96>)` (helper in `Hook.t.sol`) and assert BOTH legs there: the leg that must stay open is not rejected, the leg that must close reverts. A gate proven only at 1:1 is a false pass.\n\n\n\n## Steps\n\n1. **Parse `${var}`.** Extract the `arm:` flag, the optional `template:`, the optional `chain:`, and the free-text brief. Empty brief → exit `DEPLOY_HOOK_EMPTY` with the grammar.\n\n2. **Resolve the chain.** The chain name resolves in `chains.tsv` (default `base-sepolia`); `hook-deploy.sh` maps it to the official `PoolManager` + RPC, so you pass the NAME, not the address. Run `.\u002Fhook-deploy.sh chains` to see the list, or read `chains.tsv`. If the name is not in the registry, exit `DEPLOY_HOOK_BAD_CHAIN`. Look up the row's `testnet` column: if it is `false` (mainnet), enforce the double opt-in — require BOTH `arm:` and an explicit `chain:` in `${var}`, else exit `DEPLOY_HOOK_BAD_CHAIN`. Every Uniswap v4 chain is supported (Base, Ethereum, Unichain, Arbitrum, Optimism, Polygon, BNB, Avalanche, Robinhood, Worldchain, Ink, Soneium, Celo, X Layer + their testnets).\n\n3. **Confirm the staged toolchain + project.** The workflow pre-stages everything before this run (`scripts\u002Fstage-deploy-uni-hook.sh`): Foundry on `$PATH`, a pre-built v4 project at `$HOOKBUILD_DIR` (default `$HOME\u002Fhookbuild`) holding all three templates + `MockERC20.sol` + `DeployHook.s.sol` + the v4 libraries, and `.\u002Fhook-deploy.sh` copied to the repo root. Do **not** install Foundry or clone the libs in-run — the sandbox blocks that. Check `command -v forge` and that `$HOOKBUILD_DIR` exists; if either is missing, degrade to `DEPLOY_HOOK_NO_TOOLCHAIN` (emit the generated source + plan).\n\n4. **Build the hook (brief-driven).**\n   - **Template mode** (`dynamic` \u002F `noop` \u002F `skim`): in `$HOOKBUILD_DIR\u002Fsrc\u002F\u003CHook>.sol`, edit ONLY the region between `\u002F\u002F --- AEON:LOGIC START ---` and `\u002F\u002F --- AEON:LOGIC END ---`. Keep the callback signatures and flag set unchanged. If the default already fits the brief, leave it.\n   - **Freeform mode** (anything else): write the whole hook into `$HOOKBUILD_DIR\u002Fsrc\u002FHook.sol`, replacing the `\u002F\u002F --- AEON:BODY ... ---` region. Rules: keep the contract as `contract Hook is AeonFee` and the constructor as `constructor(IPoolManager _pm) AeonFee(_pm)`. Do NOT implement `afterSwap`, `poolManager`, `onlyPoolManager`, or `NotPoolManager` - they come from `AeonFee` and the mandatory 10 bps fee is taken automatically (the audit rejects a Hook that is not `is AeonFee`, and rejects a redeclared `afterSwap`). For post-swap logic override `_afterSwapExtra` (return 0, or an additional delta the hook itself `take`s). Implement any OTHER v4 callbacks the prompt needs, each with the EXACT `IHooks` signature, `onlyPoolManager`, and the right selector return (`SwapParams`\u002F`ModifyLiquidityParams` import from `@uniswap\u002Fv4-core\u002Fsrc\u002Ftypes\u002FPoolOperation.sol`, not nested in `IPoolManager` - that nesting was removed in v4-core's own PR #964). Do NOT hand-set flags - they are auto-derived from your callbacks (plus the always-on AeonFee `afterSwap`\u002F`afterSwapReturnsDelta` bits). If another callback returns a non-zero delta, set `HOOK_RETURNS_DELTA` in `$HOOKBUILD_DIR\u002Fhook.env`; for a fee-override hook set `HOOK_POOL_FEE=dynamic` there. Follow **Labs routing** and **Fleet audit rules**: empty `hookData` must succeed; a game must not revert a vanilla exact-in swap; an extra `take()` (in `_afterSwapExtra`) must charge magnitude (exact-in and exact-out) and never custody; a price\u002Fbalance\u002Fskew gate must add the `afterInitialize` callback and anchor to the pool's own start price (Gates rule 6), never an implicit 1.0.\n     - **Also write the behavioral test.** In `$HOOKBUILD_DIR\u002Ftest\u002FHook.t.sol`, replace the `\u002F\u002F --- AEON:ASSERT ... ---` region with `test_*` functions that assert the hook's SPECIFIC intended behavior — not just \"does not revert\". For every rule in the brief write at least one positive and one negative case: a swap the hook must REJECT as `_expectSwapRevert(zeroForOne, amount, Hook.SomeError.selector)` (this helper unwraps v4's `WrappedError` for you — do NOT use bare `vm.expectRevert`, it won't match the wrapper); a swap it must ALLOW as a plain `_swap(...)`; any getter\u002Faccounting as `assertEq(hook.someGetter(...), expected)`. For a gate whose decision depends on price or reserve balance, assert it through `_freshPoolAt(\u003Cnon-1:1 sqrtPriceX96>)` (both legs, off parity) - `setUp()`'s pool is at 1:1, where such a gate always looks correct. Do NOT edit `setUp()` or the helpers - only the `AEON:ASSERT` region. If the brief has no rejectable behavior, still assert the observable state the hook changes.\n\n5. **Simulate + audit (always).** Pass mode, kind, and chain (chain omitted = `base-sepolia`):\n   ```bash\n   .\u002Fhook-deploy.sh simulate \u003Ckind> \u003Cchain>\n   ```\n   For `freeform` this runs, in order, three gates before any deploy:\n   1. **Static audit** - derives the flags from the callbacks; checks the contract is named `Hook`, is `is AeonFee` (mandatory fee) and does not redeclare `afterSwap`, has ≥1 callback or `_afterSwapExtra`, every callback carries `onlyPoolManager`, `test\u002FHook.t.sol` has ≥1 `test_` function, and scans for dangerous patterns (`selfdestruct`\u002F`delegatecall` are hard fails; `tx.origin`\u002Fraw value-call\u002Finline `assembly` print a warning to review). A failure exits `DEPLOY_HOOK_AUDIT_FAILED` (never deploy).\n   2. **Behavioral test** — `forge test --fork-url \u003Cchain> --match-contract HookBehaviorTest` runs the agent-written assertions on a fork. A failing OR non-compiling test exits `DEPLOY_HOOK_TEST_FAILED` (never deploy). This proves the hook does what the prompt asked.\n   3. **Fork simulation** — `forge script` compiles, mines the salt, deploys in-memory, initializes the pool, adds liquidity, and runs one swap against a fork of the target chain.\n   On a compile error, fix and retry (max 3). On a sim revert, exit `DEPLOY_HOOK_SIM_FAILED`. Capture the mined hook address, the derived flags, and the `Estimated amount required`. On mainnet, compare that estimate to the deployer balance (`cast balance \u003Caddr> --rpc-url \u003Crpc>`) and exit `DEPLOY_HOOK_UNDERFUNDED` if it will not cover it.\n   For a freeform hook, also **read the generated `Hook.sol` and reason about safety** before arming: does any callback let a caller steal funds, brick the pool (unconditional revert), or reenter? If unsure, stop at the dry-run and report the concern.\n\n6. **Dry-run stop.** If `${var}` did NOT start with `arm:`, STOP here. Report: template, mined address (with its flag bits), the receipt `routing` line (auto-route vs allowlist + reason), the pool key, and the simulation result. Exit `DEPLOY_HOOK_DRY_RUN`.\n\n7. **Arm checks (only if `arm:`).**\n   - Confirm `HOOK_DEPLOYER_PRIVATE_KEY` is set (it is injected via `requires:`). If not, degrade to the dry-run report and exit `DEPLOY_HOOK_NO_KEY`.\n   - Read `memory\u002Fstate\u002Fhook-deploys.json`. If the same `(chain, template, brief)` deployed in the last hour, exit `DEPLOY_HOOK_IDEMPOTENT` with the prior address.\n\n8. **Broadcast.**\n   ```bash\n   .\u002Fhook-deploy.sh broadcast \u003Ckind> \u003Cchain>\n   ```\n   The runner prints a **deploy receipt** (hook address, decoded flag names, explorer deep-link, tx hashes) and, when `ETHERSCAN_API_KEY` is set on an Etherscan-family chain, **auto-verifies** the hook source on the explorer (best-effort — a failed verify never fails a completed deploy). If it printed `ALREADY_DEPLOYED`, treat the reported address as the result (no new deploy). Read the hook address and the transaction hashes from the receipt or `$HOOKBUILD_DIR\u002Fbroadcast\u002FDeployHook.s.sol\u002F\u003CchainId>\u002Frun-latest.json`.\n\n9. **Verify.** With `cast`, read the pool back through `StateView.getSlot0(poolId)` on the RPC. Confirm the pool exists and the hook address low bits equal the template's flags. Confirm the swap emitted the hook event.\n\n10. **Record the deploy.** The deploy already happened on-chain — this is append-only history, not a change to review, so DO NOT open a PR or a branch. Just write the record into the working tree on `main`; the workflow's post-run commit lands it. Write:\n    - `memory\u002Fstate\u002Fhook-deploys.json` — append this deploy (chain, template, brief, hook address, flags, tx hashes, timestamp, poolId, poolKey).\n    - `output\u002Fhooks\u002F\u003Chook-address>.sol` — copy the deployed source from `$HOOKBUILD_DIR\u002Fsrc\u002F\u003CHook>.sol`.\n    - For freeform, also `output\u002Fhooks\u002F\u003Chook-address>.t.sol` — copy `$HOOKBUILD_DIR\u002Ftest\u002FHook.t.sol` (the behavioral test that gated the deploy).\n\n    Do NOT stage the root `.\u002Fhook-deploy.sh` or `.\u002Fchains.tsv` (runtime copies; both gitignored).\n\n11. **Publish to the public hook list (live mainnet deploys only).** If this was a real broadcast (not a dry-run) to a mainnet chain the registry supports (`ethereum base robinhood monad bnb arbitrum unichain`), list the hook on `aeonfun\u002Funiv4-hooks` so it appears on the aeon hook marketplace. Reuse the `submit-hook` skill's helper - it decodes the flags from the address, formats the entry, regenerates the registry, and opens a PR (issue fallback when there is no push access):\n    ```bash\n    python3 skills\u002Fsubmit-hook\u002Fsubmit-univ4.py \\\n      --address \"$HOOK_ADDR\" --chain \"$CHAIN\" \\\n      --name \"$NAME\" --category \"$CATEGORY\" --klass \"$KLASS\" \\\n      --template \"$TEMPLATE\" --stage deployed --source aeon --verified \\\n      --date \"$(date -u +%F)\" \\\n      --mechanic \"$MECHANIC\" --plain \"$PLAIN\" --rule \"$RULE1\" --rule \"$RULE2\"\n    ```\n    Derive `name`\u002F`category`\u002F`klass`\u002F`mechanic`\u002F`plain`\u002F`rules` from the brief exactly as `skills\u002Fsubmit-hook\u002FSKILL.md` describes. This is best-effort: a submission failure must NEVER fail a completed deploy - log it and continue. Skip entirely on a dry-run, a testnet, or an unsupported chain.\n\n12. **Notify + exit.** Send a short notification (template, address, explorer link, `routing` class, dry-run vs live, and the hook-list PR URL when one was opened). Exit `DEPLOY_HOOK_OK` (or `DEPLOY_HOOK_DRY_RUN`).\n\n## Degrade rules\n\n- No key → dry-run report, `DEPLOY_HOOK_NO_KEY`. Never fail hard.\n- Foundry or the staged project missing (`command -v forge` fails or `$HOOKBUILD_DIR` absent) → emit the generated source + plan, `DEPLOY_HOOK_NO_TOOLCHAIN`. Do not try to install in-run (the sandbox blocks it).\n- Bad\u002Fmissing chain, or mainnet without the double opt-in → `DEPLOY_HOOK_BAD_CHAIN`.\n- Mainnet chain but the instance did not set `HOOK_MAINNET_OK=1` (`hook-deploy.sh` exit 7) → `DEPLOY_HOOK_MAINNET_NOT_AUTHORIZED` (never broadcast).\n- Mainnet balance below the simulation estimate, or the deployer is unfunded (`hook-deploy.sh` exit 8) → `DEPLOY_HOOK_UNDERFUNDED` (never broadcast).\n- Gas price above `MAX_GAS_GWEI` (`hook-deploy.sh` exit 9) → `DEPLOY_HOOK_GAS_TOO_HIGH` (never broadcast; retry when fees drop).\n- Freeform static audit fails (bad name \u002F no callback \u002F missing `onlyPoolManager` \u002F no `test_` \u002F `selfdestruct` \u002F `delegatecall`) → `DEPLOY_HOOK_AUDIT_FAILED` (never deploy).\n- Freeform behavioral test fails or does not compile → `DEPLOY_HOOK_TEST_FAILED` (never deploy).\n- Simulation revert → `DEPLOY_HOOK_SIM_FAILED` (never broadcast after a failed sim).\n- Seed probe skipped during simulation and not declared intentional (`hook-deploy.sh` exit 1, logs `SEED_SWAP_SKIPPED`) → `DEPLOY_HOOK_SIM_FAILED`. A revert-gate hook rejecting the probe on purpose must set `HOOK_REVERT_GATE=1` in `hook.env` to pass; the caught revert bytes are logged beside the marker so the operator can tell an intentional gate from a broken probe. During **broadcast** this same condition only warns and continues — the deploy is already onchain, so exiting would strand it with no receipt or explorer verification.\n\n## Notes\n\n- The three templates are pre-validated: each compiles and simulates a full deploy + swap on Base Sepolia. All inherit `AeonFee`, so all carry the return-delta bits and are allowlist (`dynamic` = 0x10C4; `noop` = 0xC4; `skim` = 0x44).\n- **Freeform** builds an arbitrary hook from the prompt into `src\u002FHook.sol` and its behavioral test into `test\u002FHook.t.sol`. Flags are auto-derived from the callbacks (never hand-set). Three gates run before any deploy: a static audit (name\u002Fcallbacks\u002F`onlyPoolManager`\u002Ftest-present\u002Fdangerous-pattern scan), the agent-written `forge test` behavioral assertions on a fork, then the fork simulation. The agent also reads the generated source for steal\u002Fbrick\u002Freentrancy risk before arming. Prefer a matching template when one fits (they are audited); use freeform for novel logic.\n- Every deploy — template or freeform — always simulates on the target chain's fork first, so \"does it work\" is checked before any broadcast.\n- **Any Uniswap v4 chain works.** `chains.tsv` carries every official v4 deployment (Base, Ethereum, Unichain, Arbitrum, Optimism, Polygon, BNB, Avalanche, Robinhood, Worldchain, Ink, Soneium, Celo, X Layer + the Sepolia testnets), each verified to hold the PoolManager. The same flow runs on all of them — only the `PoolManager`\u002FRPC differ, resolved by name. The CREATE2 deployer (`0x4e59…4956C`) is required for the mined address; if a chain lacks it the fork simulation fails closed before any broadcast.\n- **Mainnet is gas-only.** The deploy mints its own `MockERC20` tokens to itself (free) and seeds the demo pool with those mock tokens — a mainnet broadcast risks GAS ONLY, never real capital. The deployed pool is a MockA\u002FMockB demo; the reusable hook contract is the real deliverable. The deployer key must be a funded burner holding gas float only (the runner warns above `HOOK_MAX_FLOAT_ETH`); mainnet also needs the `HOOK_MAINNET_OK=1` operator lock. A future version can add the keyless Base MCP `send_calls` rail so no key sits in the runner.\n- **Authenticated RPC + receipt + verify.** On mainnet the runner prefers an Alchemy endpoint (`ALCHEMY_API_KEY` + the chain's `alchemy` slug) over the public RPC, so a lying public node can't fake a clean sim. After a broadcast it prints a receipt (address, decoded flags, explorer link, tx hashes) and, with `ETHERSCAN_API_KEY` on an Etherscan-family chain, auto-verifies the source (best-effort). All of this is opt-in: with no keys set the skill still runs on public RPCs, unverified.\n",{"name":5,"metadata":53,"description":7},{"var":54,"tags":55,"title":58,"category":56,"requires":59,"capabilities":63},"arm: to broadcast (default is a dry-run), template:dynamic|noop|skim to force a mode, chain:\u003Cname> to pick a chain (default base-sepolia), then the hook brief. Empty prints the grammar.",[56,57,39],"crypto","dev","Deploy Uni Hook",[60,61,62],"HOOK_DEPLOYER_PRIVATE_KEY?","ALCHEMY_API_KEY?","ETHERSCAN_API_KEY?",[64,65,66],"onchain_writes","writes_external_host","sends_notifications","25575a6be3bfab41925964de55654056a2fe0c39","skills\u002Fdeploy-uni-hook",308,"https:\u002F\u002Fgithub.com\u002Faeonfun\u002Faeon","https:\u002F\u002Fwww.aeon.fun\u002F","https:\u002F\u002Fgithub.com\u002Faeonfun","The most autonomous agent framework.","2026-11-14 00:57:36",{"source":8,"skillName":5,"commands":76,"prompt":86,"zipAvailable":87},[77,80,83],{"tool":78,"command":79},"npx","npx skills add aeonfun\u002Faeon --skill deploy-uni-hook",{"tool":81,"command":82},"bunx","bunx skills add aeonfun\u002Faeon --skill deploy-uni-hook",{"tool":84,"command":85},"pnpm","pnpm dlx skills add aeonfun\u002Faeon --skill deploy-uni-hook","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Faeonfun\u002Faeon\u002Fblob\u002Fmain\u002Fskills\u002Fdeploy-uni-hook\u002FSKILL.md",true,[89,95,101,105,109,113,117,121,125,129,133,137],{"path":90,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":93,"sourceHtmlUrl":94},"hook-deploy.sh","SCRIPT","脚本",21387,"https:\u002F\u002Fgithub.com\u002Faeonfun\u002Faeon\u002Fblob\u002Fmain\u002Fskills\u002Fdeploy-uni-hook\u002Fhook-deploy.sh",{"path":96,"resourceType":97,"resourceTypeDesc":98,"sizeBytes":99,"sourceHtmlUrl":100},"templates\u002FAeonFee.sol","OTHER","其他",5478,"https:\u002F\u002Fgithub.com\u002Faeonfun\u002Faeon\u002Fblob\u002Fmain\u002Fskills\u002Fdeploy-uni-hook\u002Ftemplates\u002FAeonFee.sol",{"path":102,"resourceType":97,"resourceTypeDesc":98,"sizeBytes":103,"sourceHtmlUrl":104},"templates\u002Fchains.tsv",4246,"https:\u002F\u002Fgithub.com\u002Faeonfun\u002Faeon\u002Fblob\u002Fmain\u002Fskills\u002Fdeploy-uni-hook\u002Ftemplates\u002Fchains.tsv",{"path":106,"resourceType":97,"resourceTypeDesc":98,"sizeBytes":107,"sourceHtmlUrl":108},"templates\u002FDeployHook.s.sol",10994,"https:\u002F\u002Fgithub.com\u002Faeonfun\u002Faeon\u002Fblob\u002Fmain\u002Fskills\u002Fdeploy-uni-hook\u002Ftemplates\u002FDeployHook.s.sol",{"path":110,"resourceType":97,"resourceTypeDesc":98,"sizeBytes":111,"sourceHtmlUrl":112},"templates\u002FDynamicFeeHook.sol",3932,"https:\u002F\u002Fgithub.com\u002Faeonfun\u002Faeon\u002Fblob\u002Fmain\u002Fskills\u002Fdeploy-uni-hook\u002Ftemplates\u002FDynamicFeeHook.sol",{"path":114,"resourceType":97,"resourceTypeDesc":98,"sizeBytes":115,"sourceHtmlUrl":116},"templates\u002Ffoundry.toml",351,"https:\u002F\u002Fgithub.com\u002Faeonfun\u002Faeon\u002Fblob\u002Fmain\u002Fskills\u002Fdeploy-uni-hook\u002Ftemplates\u002Ffoundry.toml",{"path":118,"resourceType":97,"resourceTypeDesc":98,"sizeBytes":119,"sourceHtmlUrl":120},"templates\u002Fhook.env.example",1087,"https:\u002F\u002Fgithub.com\u002Faeonfun\u002Faeon\u002Fblob\u002Fmain\u002Fskills\u002Fdeploy-uni-hook\u002Ftemplates\u002Fhook.env.example",{"path":122,"resourceType":97,"resourceTypeDesc":98,"sizeBytes":123,"sourceHtmlUrl":124},"templates\u002FHook.sol",4327,"https:\u002F\u002Fgithub.com\u002Faeonfun\u002Faeon\u002Fblob\u002Fmain\u002Fskills\u002Fdeploy-uni-hook\u002Ftemplates\u002FHook.sol",{"path":126,"resourceType":97,"resourceTypeDesc":98,"sizeBytes":127,"sourceHtmlUrl":128},"templates\u002FHook.t.sol",12111,"https:\u002F\u002Fgithub.com\u002Faeonfun\u002Faeon\u002Fblob\u002Fmain\u002Fskills\u002Fdeploy-uni-hook\u002Ftemplates\u002FHook.t.sol",{"path":130,"resourceType":97,"resourceTypeDesc":98,"sizeBytes":131,"sourceHtmlUrl":132},"templates\u002FHookFeeHook.sol",3056,"https:\u002F\u002Fgithub.com\u002Faeonfun\u002Faeon\u002Fblob\u002Fmain\u002Fskills\u002Fdeploy-uni-hook\u002Ftemplates\u002FHookFeeHook.sol",{"path":134,"resourceType":97,"resourceTypeDesc":98,"sizeBytes":135,"sourceHtmlUrl":136},"templates\u002FMockERC20.sol",1778,"https:\u002F\u002Fgithub.com\u002Faeonfun\u002Faeon\u002Fblob\u002Fmain\u002Fskills\u002Fdeploy-uni-hook\u002Ftemplates\u002FMockERC20.sol",{"path":138,"resourceType":97,"resourceTypeDesc":98,"sizeBytes":139,"sourceHtmlUrl":140},"templates\u002FNoOpHook.sol",1641,"https:\u002F\u002Fgithub.com\u002Faeonfun\u002Faeon\u002Fblob\u002Fmain\u002Fskills\u002Fdeploy-uni-hook\u002Ftemplates\u002FNoOpHook.sol",[142,166,189,213,238,260],{"skillNo":143,"name":144,"nameZh":6,"description":145,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":146,"categories":147,"keywords":148,"publishedAt":48},"01M70R8RA3SFXK2D1XP7XTJGAQ","sns-digest","Digest Internet Computer governance - new and open NNS proposals and SNS DAO proposals - so the operator sees what is up for a vote without watching the dashboard. Fully public, no secret; fires only when there is something new to report.","https:\u002F\u002Fgithub.com\u002Faeonfun\u002Faeon\u002Fblob\u002Fmain\u002Fskills\u002Fsns-digest\u002FSKILL.md",[],[149,150,151,152,153,154,155,156,157,158,159,160,41,40,161,56,162,163,164,165],"sns","digest","sns digest","proposals","for","up","open","icp","only","new","internet","when","dao","dashboard","governance","report","write",{"skillNo":167,"name":168,"nameZh":6,"description":169,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":170,"categories":171,"keywords":173,"publishedAt":48},"01M70R5BMYW94KZ3XQM3MSWPC0","icp-deploy-check","Pre-deploy safety checklist for an Internet Computer Rust canister - read a local\u002Fcloned canister repo and verify the deploy-time footguns from the canister-security checklist (controller backup, anonymous-principal rejection, no mainnet fetch_root_key, upgrade safety) before it ships. Static, read-only, no network and no mainnet action.","https:\u002F\u002Fgithub.com\u002Faeonfun\u002Faeon\u002Fblob\u002Fmain\u002Fskills\u002Ficp-deploy-check\u002FSKILL.md",[172],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[156,174,175,176,24,177,178,30,179,180,181,157,159,182,183,184,185,186,187,188],"icp deploy check","deploy check","check","fetch","anonymous","time","rust","local","upgrade","controller","read","Safety","network","action","security",{"skillNo":190,"name":191,"nameZh":6,"description":192,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":193,"categories":194,"keywords":203,"publishedAt":48},"01M70R312QZ9T236SZHGX8A8CM","canister-status","Monitor Internet Computer canisters for control-plane changes - a new controller, a module-hash change (upgrade), or a canister going missing from the public index - and alert the moment one happens. Uses only the public IC dashboard API.","https:\u002F\u002Fgithub.com\u002Faeonfun\u002Faeon\u002Fblob\u002Fmain\u002Fskills\u002Fcanister-status\u002FSKILL.md",[195,198],{"categoryNo":196,"categoryName":197,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000010","后端与接口",{"categoryNo":199,"categoryName":200,"taxonomyType":201,"taxonomyTypeDesc":202},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[204,205,153,206,207,156,208,157,158,159,182,209,210,41,40,183,56,211,162,212],"canister status","status","missing","monitor","module","alert","plane","change","changes",{"skillNo":214,"name":215,"nameZh":6,"description":216,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":217,"categories":218,"keywords":221,"publishedAt":48},"01M6FVEXRG77BT4VH94P0S1TDT","you-web-search","Web search using You.com Search API with high-quality, cited results — runs keyless out of the box; YDC_API_KEY unlocks higher limits and real-time web crawling","https:\u002F\u002Fgithub.com\u002Faeonfun\u002Faeon\u002Fblob\u002Fmain\u002Fskills\u002Fyou-web-search\u002FSKILL.md",[219,220],{"categoryNo":196,"categoryName":197,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":199,"categoryName":200,"taxonomyType":201,"taxonomyTypeDesc":202},[222,223,224,225,226,179,157,41,227,184,228,229,230,231,232,233,234,235,236,237],"web search","search","you","you web search","web","web crawling","read-only","real-time","basics","keyless","with","research","results","quality","high","limits",{"skillNo":239,"name":240,"nameZh":6,"description":241,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":242,"categories":243,"keywords":244,"publishedAt":48},"01M6FVER8Y2B0H7H26G4GTYK6N","write-tweet","Multi-format tweet studio - standalone drafts (10 across 5 size tiers), a 5-10 tweet thread, or 10 remixes of past tweets, selected via ${var}","https:\u002F\u002Fgithub.com\u002Faeonfun\u002Faeon\u002Fblob\u002Fmain\u002Fskills\u002Fwrite-tweet\u002FSKILL.md",[],[165,245,246,247,41,248,249,230,250,251,252,253,254,255,256,257,258,259],"write tweet","social","studio","across","xai","twitter","multi","via","format","content","standalone","past","drafts","thread","size",{"skillNo":261,"name":262,"nameZh":6,"description":263,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":264,"categories":265,"keywords":269,"publishedAt":48},"01M6FVENCJ0HY2TEE6CNZN4F96","weekly-aeoncard","Build a weekly token-consumption recap image from memory\u002Ftoken-usage.csv - this week + all-time totals, top skills, rendered as a shareable SVG card.","https:\u002F\u002Fgithub.com\u002Faeonfun\u002Faeon\u002Fblob\u002Fmain\u002Fskills\u002Fweekly-aeoncard\u002FSKILL.md",[266],{"categoryNo":267,"categoryName":268,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000016","图像与多媒体",[270,271,272,273,274,275,276,179,277,278,279,280,281,40,282,283,165,284,12,285],"weekly aeoncard","weekly","as","usage","SVG","memory","card","Meta","image","recap","csv","monitoring","productivity","build","token","top"]