一键导入
add-api-resource
Declare new API resource(s) in an existing API service. Use whenever the app needs to call an endpoint that has no `service:name` resource yet.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Declare new API resource(s) in an existing API service. Use whenever the app needs to call an endpoint that has no `service:name` resource yet.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Create or finalize a pull request — three modes: placeholder draft PR at spec time, finalize a draft into ready-for-review, or a regular PR right away for work done outside the task workflow.
Grill a product task (GitHub issue) into an implementable spec — research first, then a one-question-at-a-time interview; also elaborates sub-specs for deferred subtasks of large tasks.
Execute a product-task spec one leaf subtask per run — [agent] subtasks via the project skills, [human] subtasks handed off to the developer.
Convert the current conversation into a product-task spec in .agents/tasks/, or update an existing spec — folding in new decisions, harvesting colleague replies from Slack threads, and sending open questions to their owners. Use at the end of a grilling session, when the user wants to capture any conversation as a spec, or to sync a spec's open questions with Slack.
Scaffold a new page (index / detail / general) and optionally wire it to API data. Use when adding any new route to the app, or when wiring API data into an already-scaffolded page (one with `TODO (api-data):` markers).
Publish a beta version of a `@blockscout/*-types` npm package and pin it here. Use when a needed response type isn't in any published package version yet.
| name | add-api-resource |
| description | Declare new API resource(s) in an existing API service. Use whenever the app needs to call an endpoint that has no `service:name` resource yet. |
Every request the app makes goes through a resource: an entry in the per-service registry
under src/api/resources/services/** that maps a service:name key (e.g. core:token,
stats:lines) to a path template and, via a sibling conditional type, to its response type.
This skill declares new resource(s) in an existing service.
Out of scope — brand-new service. That also touches src/api/resources/index.ts
(registration + dispatch-type branches) and a src/api/config.ts block; not covered here.
Out of scope — consuming the resource. Wiring it into UI (useApiQuery /
useQueryWithPages, stubs) is the caller's job; this skill only makes the resource exist and
be correctly typed.
Background reading: Where a resource's response types come from in
src/api/CONTEXT.md — read it before Step 3.
Rule of thumb: never guess. Whenever information is missing or required to proceed, pause and ask the user, or confirm your findings, before writing files.
Collect for each resource, and confirm with the user:
service:name key — follow the naming
of the sibling entries in the service's registry file.tools/dev-server/registry.json or a full instance URL. A brand-new endpoint may exist
only on a staging instance; ask which. This powers Step 1.publish-beta-types Step 0 inputs now (most importantly the API source-repo branch to
publish from), so the publish can run later without another interview. If the user already
knows publishing is impossible, settle the fallback choice now too — see Worst case
in Step 3.Resolve each resource's real URL with the resolve-api-url skill, then make one GET
per resource and save each body to the scratchpad. This sample is load-bearing three
times over:
next_page_params field (Step 2);If the endpoint needs auth or params you can't supply, show the user the resolved URL and ask them for a sample body instead.
All edits for an existing service live in its registry file — Core API:
src/api/resources/services/core/<group>.ts (e.g. token.ts); micro-service:
src/api/resources/services/<name>.ts. Add the entry to the *_API_RESOURCES object — shape is
ApiResource (src/api/resources/types.ts): { path, pathParams?, filterFields?, paginated?, headers? }.
path uses :param placeholders; list each one in pathParams.paginated: true only if the Step 1 sample has next_page_params.No src/api/resources/index.ts edit is needed — the ResourceName union and the dispatch types
aggregate per-service keys automatically.
Add a matching branch to the sibling *ResourcePayload<R> conditional type in the same
file. Miss this and ResourcePayload<'service:new'> silently resolves to never — no
error at the declaration, just untyped data downstream. Where the response type comes from
depends on the API:
@blockscout/api-types package; its README Usage
section (node_modules/@blockscout/api-types/README.md) is the reference for how to name
a response type (schemas[…], operations[…], paths[…]['get']).types/api.ts rather
than generated; see Where a resource's response types come from in src/api/CONTEXT.md.Type not published yet? If Step 0 established the interface isn't in any published
package version, don't hand-type a stopgap: invoke the publish-beta-types skill with
the inputs already collected in Step 0, then continue with this step. Same move if you only
discover the gap here (the interface missing from node_modules even at latest despite
the interview answer) — in that case the publish inputs still need collecting.
Worst case — no published types and no publish possible (no access to the API repo, publish workflow broken, or the API branch doesn't generate types for the endpoint yet, so there's nothing to publish). Confirm the blocker, then the user picks one of two paths — never pick silently:
types/api.ts (the usual home for local types — see Where a resource's response types
come from in src/api/CONTEXT.md; some core:* payloads already live this way), derived
from the Step 1 sample body, and reference it from the payload branch. Mark it
// TODO (api-types): replace with the generated @blockscout/<pkg> type once published so
the swap can be found with a grep later. Caveat: one sample can't reveal optional/nullable fields —
confirm optionality with the user instead of inferring it from a single body.TODO (api-data):
markers stay in place).Not every paginated resource has them. Add filterFields and branches to the service's
*PaginationFilters<R> / *PaginationSorting<R> types only for the filters/sorts named
in the task description or conversation — never infer them from the API. Define the
filter/sort types themselves in the owning slice/feature types/api.ts (kept local by
design).
Run pnpm run lint:tsc. To catch a missed Step 3 branch (the silent never), use the inline
type-assertion pattern already present in src/api/resources/index.ts (e.g. the
ResourcePayload<'core:api_keys'> / ResourcePathParams<'bens:address_domain'> checks) as a
temporary probe for your new key — or hover/tsc-check a ResourcePayload<'service:new'>
usage and confirm it is not never.
Report back, per resource: the service:name key, the payload type (and its origin —
package or local), whether it's paginated, and the scratchpad path of the sample body —
everything a follow-up consumption task needs.