SKILL.md
EasyYapi Rule Authoring Assistant
This skill is the external mirror of EasyYapi's built-in rule-authoring agent. It helps you write or modify EasyYapi rule files (.rules / .properties files in .easyapi/) that the EasyYapi IntelliJ plugin reads to customise API export (YApi/Postman/Markdown), field naming, annotations, and more.
It runs the same perceive → reason → act loop as the built-in agent and exposes the same capability surface: the same rule guide and key catalog, and CLI equivalents of every built-in perception tool. The only difference is how each capability is delivered — the built-in agent calls IntelliJ PSI tools; you read files and search the codebase directly.
When to Use
Invoke this skill when:
- The user opens or edits any file in the project's
.easyapi/folder or
the global ~/.easyapi/ folder.
- The user asks to "add a rule", "rename a field", "ignore a class", "add a
header to every POST", etc. in the EasyYapi context.
- The user mentions
easy.api,EasyApi,EasyYapi, oreasyapiin a request about
config or rule authoring.
Bundled Knowledge Base (read these first — they ARE the built-in agent's docs)
This skill ships mirrors of the in-plugin agent's authoritative sources, kept in sync by Gradle tasks in the easy-yapi repo. Run ./gradlew syncSkill to refresh all four mirrors in one command (it aggregates syncKnowledgeBase, syncAgentCatalog, syncRuleKeySchemes, and syncRuleContexts):
docs/— the long-form knowledge-base pages the plugin bundles for its
built-in agent's getplugindoc tool. Kept in sync by the syncKnowledgeBase Gradle task.
ai/detection/+ai/key-guides/— the per-detection / per-key guide
catalog the in-plugin agent loads via PromptCatalog (the same files getdetectionprompt and getruledetail read at runtime). Kept in sync by the syncAgentCatalog Gradle task.
rule-keys.json+rule-keys.md— the auto-generated rule-key
scheme catalog. RuleKeySchemeExporter reflects every RuleKeys object (general + channel + framework) and the implicit keys, and emits the full self-describing scheme* of each key — the same information the in-plugin agent gets from its listrulekeys tool. Regenerated by the syncRuleKeySchemes Gradle task, so **any key added to a *RuleKeys object is picked up automatically** (a brand-new channel/framework must be registered in RuleKeyCatalog.SOURCES).
rule-contexts.json+rule-contexts.md— the auto-generated
script-context mirror of the in-plugin getrulecontext tool. RuleContextExporter reuses the exact same key assembly (so it covers rule keys and the implicit keys read via configReader.getFirst — one interface, the same one the built-in agent sees) and, per key, reflects the runtime bindings + script-object method signatures. Regenerated by the syncRuleContexts Gradle task.
All mirrors are content-equality-checked and idempotent, so the rule content the built-in and external agents produce is identical. Always read the relevant page first — do not rely on memory or guess syntax.
| Bundled file | Built-in getplugindoc name |
What it covers |
|---|---|---|
docs/rule-guide.md |
rule-guide |
The source of truth. Rule file format, filter syntax, expression prefixes, Groovy binding reference, recipes, the Custom-Pattern Catalog, and the Workflow-Pattern Catalog (cross-endpoint auth/signing/refresh recipes). |
docs/index.md |
index |
Knowledge-base index / topic map. |
docs/README.md |
overview |
Overview of EasyYapi concepts. |
docs/settings-guide.md |
settings-guide |
Plugin settings reference. |
docs/usage-guide.md |
usage-guide |
Usage guidance. |
docs/postman-script-reference.md |
postman-script-reference |
Postman-compatible pm.* Groovy scripting (pre-request / post-response only). |
rule-keys.md |
(built-in listrulekeys tool) |
Complete rule-key catalog, auto-generated from every key's self-describing scheme (full scheme in rule-keys.json). |
rule-contexts.md |
(built-in getrulecontext tool) |
Per-key script-context (bindings + callable script-object method signatures), auto-generated by reflecting the same rule keys. Fetch one key with scripts/getkeycontext.sh. |
Toolset — CLI mirrors of the built-in agent tools
The built-in agent has a fixed set of perception/action tools. You provide equivalent capability by reading files and searching the codebase. Use the mapping below so your workflow tracks the built-in agent's.
EasyYapi-domain tools (bundled as scripts/)
These mirror the EasyYapi-specific perception tools. Run them from the project root (the CWD when the assistant is invoked). They auto-detect the project root and ~/.easyapi/ so you never hard-code paths.
| Built-in tool | Your equivalent | What it does |
|---|---|---|
listrulekeys |
Read bundled rule-keys.json / rule-keys.md |
Lists every supported rule key with its full self-describing scheme (auto-generated). |
getplugindoc |
Read the bundled *.md pages above |
Reads a knowledge-base page. |
readrulefile |
scripts/readrulefile.sh <name> |
Reads a rule file by name. Supports global: / project: scope prefixes. Resolves against tracked .easyapi/ dirs — never guesses home paths. |
getexistingrulesforkey |
scripts/getexistingrulesforkey.sh <key> [<key>...] |
Finds all configured values for a key across project + global rule files. Prints file:line: <line content> so you can reason about precedence. |
Usage examples:
# List all rule files the plugin will load
scripts/list_rule_files.sh
# Read a rule file by name (scope-prefixed or bare)
scripts/read_rule_file.sh security.properties
scripts/read_rule_file.sh global:jwt.rules
scripts/read_rule_file.sh project:custom.rules
# Check if a key is already configured (avoid duplicates — Quality Rule 1)
scripts/get_existing_rules_for_key.sh field.name
scripts/get_existing_rules_for_key.sh api.tag method.additional.header
Catalog recipe tools (mirrors of in-plugin getdetectionprompt / getruledetail)
The built-in agent's decomposed prompt catalog (Phase A of the in-plugin agent) lives under src/main/resources/ai/{detection,key-guides}/ in the easy-yapi repo. This skill ships a verbatim copy under ai/{detection,key-guides}/ next to SKILL.md, kept in sync by the syncAgentCatalog Gradle task. CLI scripts mirror the in-plugin perception tools that read that catalog — same id space, same body content, same error shape — so your workflow tracks the in-plugin agent's exactly.
Key discovery now goes through rule-keys.md (the auto-generated full catalog, mirror of the in-plugin listrulekeys tool): it lists every supported rule key — including the implicit keys with no RuleKey constant — with its full self-describing scheme. The key-guide index (which keys carry a per-key guide file) is folded into getkeyguide.sh --list.
| Built-in tool | Your equivalent | What it does |
|---|---|---|
getdetectionprompt |
scripts/getdetectionprompt.sh <id> |
Fetches the full detection recipe for one detection family by id (e.g. spring-filters-interceptors, static-auth). Strips the YAML front-matter; prints the markdown body. Unknown id → error: unknown detection id: <id> on stderr, exit 1. |
getruledetail (by-key path) |
scripts/getkeyguide.sh <key> |
Fetches the full per-key guide by rule key (e.g. postman.test, method.additional.header). Strips the YAML front-matter; prints the body. --list lists every key that has a guide. Unknown key → error: unknown rule key: <key> on stderr, exit 1. |
listrulekeys |
rule-keys.md / rule-keys.json |
Lists every supported rule key with its full self-describing scheme (auto-generated). |
getrulecontext |
scripts/getkeycontext.sh <key> |
Fetches the runtime script-context for one rule key (auto-generated mirror): the key's execution mode, per-key bindings, and the full callable script-object method signatures (it/request/response/api/…). Unknown key → error: unknown rule key: <key> on stderr, exit 1. |
SystemPromptBuilder.indexMessage("detection") |
scripts/list_detections.sh |
Lists every detection family: id — title: cue per file (lexicographic by filename). |
SystemPromptBuilder.indexMessage("key-guides") |
scripts/getkeyguide.sh --list |
Lists every per-key guide: key — title: cue per file. Complements (does NOT replace) rule-keys.md, which lists every supported rule key including those without a per-key guide file. |
Usage examples:
# Discover which detection families exist before proposing rules
scripts/list_detections.sh
# Fetch the recipe for one detection family
scripts/get_detection_prompt.sh spring-filters-interceptors
scripts/get_detection_prompt.sh static-auth
# Discover which per-key guides exist
scripts/get_key_guide.sh --list
# Fetch the guide for one rule key (before drafting a rule for that key)
scripts/get_key_guide.sh postman.test
scripts/get_key_guide.sh method.additional.header
scripts/get_key_guide.sh markdown.curl.host
# Fetch the runtime script-context of a key when authoring a script value
scripts/get_key_context.sh postman.test
scripts/get_key_context.sh api.class.parse.after
Catalog recipe access priority (mirrors the in-plugin agent's agent-base.md): for a detection-family question, the preferred first stop is scripts/getdetectionprompt.sh <id>; for a per-key guide question, the preferred first stop is scripts/getkeyguide.sh <key>. The long-form docs/rule-guide.md stays the reference for cross-cutting context (Workflow Patterns, Multi-Application Namespace, the full filter-prefix table). Memory is never a substitute for the catalog — always read the guide before drafting.
General codebase-perception tools (your file/grep capabilities)
The built-in agent has PSI tools to inspect source. You use file reads + rg/grep instead. rg is assumed available (it ships with most AI coding assistants); fall back to grep -rn if it isn't.
| Built-in tool | Your equivalent | Notes | |
|---|---|---|---|
getpsiclass_info |
Read the class source file; or rg for its fields/methods |
Find the file by simple name first (below), then read it. Resolve the FQN from the package + import. | |
getpsimethod_info |
Read the method in the class source file | For overloads, disambiguate by parameter count when you read it. | |
findclassesby_annotation |
rg -t java -t kt "<@AnnotationFqn or @Simple>" then resolve imports |
Always confirm the FQN from the import / package — @Simple names collide. |
|
findclassesby_supertype |
`rg -t java -t kt "extends\\s+<Type>\\ | implements\\s+.*<Type>"` then resolve imports | The most common blind spot — annotation-only scans miss inheritance-declared components (filters extending OncePerRequestFilter). Use BOTH this and the annotation scan. |
listprojectendpoints |
(no CLI equivalent — see below) | Needs IntelliJ's ApiIndex cache, which is unavailable outside the IDE. |
Standard discovery patterns (the Custom-Pattern Catalog signals to look for — full recipes are in bundled docs/rule-guide.md):
# Find servlet filters (extends OncePerRequestFilter, implements Filter)
rg -t java -t kt "extends\s+OncePerRequestFilter|implements\s+.*Filter"
# Find interceptors
rg -t java -t kt "implements\s+HandlerInterceptor"
# Find response wrappers (ResponseBodyAdvice)
rg -t java -t kt "implements\s+ResponseBodyAdvice"
# Find argument resolvers
rg -t java -t kt "implements\s+HandlerMethodArgumentResolver"
# Find annotated controllers (resolve imports to confirm the FQN)
rg -t java -t kt "@RestController"
Always resolve imports / same-package usage to confirm the FQN, and exclude the supertype itself from results — these are the same nuances the built-in agent's PSI tools handle automatically.
listprojectendpoints has no CLI equivalent — it needs the plugin's ApiIndex cache, which only exists inside a running IntelliJ. You do not need the endpoint list to author rules: rules are about the request/response contract (headers, param injection, response unwrapping), which you detect from source via the discovery patterns above. If the user references a specific endpoint, read the controller method's source directly.
Batch mode (mirror the built-in agent's batching)
The built-in agent's findclassesby, getpsiclassinfo, and getexistingrulesforkey accept arrays to probe multiple items in one request. Mirror this by batching your searches — e.g. one rg -t java -t kt "extends\s+OncePerRequestFilter|implements\s+.Filter|implements\s+HandlerInterceptor" covers filters + interceptors in one pass instead of three, and getexistingrulesforkey.sh field.name field.ignore api.tag checks three keys at once. Prefer the combined form.
Workflow
Work in a perceive → reason → act loop, mirroring the built-in agent.
Step 1: Perceive — fetch the per-recipe catalog entry, then the long-form guide
The in-plugin agent's decomposed prompt catalog is the preferred first stop for any detection-family or per-key recipe question. This skill mirrors that catalog and exposes it via CLI scripts — use them before opening the long-form guide.
- For a detection family (filters, interceptors, response wrappers,
argument resolvers, custom frameworks, auth chaining, HMAC signing, …): ``bash scripts/listdetections.sh # discover the families scripts/getdetection_prompt.sh spring-filters-interceptors # fetch one recipe ``
- For a per-key guide (a specific rule key like
postman.testor
method.additional.header, or a key with no RuleKey constant like markdown.curl.host): ``bash scripts/getkeyguide.sh --list # discover the keys with guides scripts/getkeyguide.sh postman.test # fetch one guide ``
The long-form docs/rule-guide.md is the reference for cross-cutting context: the full rule file format, the full rule-key catalog, the complete filter-prefix table, the Workflow-Pattern Catalog (cross-endpoint auth/signing/refresh recipes), and the Multi-Application Namespace section. Read it after the per-recipe entry when you need that broader context — not instead of it.
If the topic is settings/usage/scripting rather than rules, read the corresponding bundled docs/ page instead (no per-recipe catalog exists for those topics).
Step 2: Perceive — find the right rule key
If the rule key isn't obvious from the catalog or guide, scan the bundled rule-keys.md catalog (the auto-generated scheme catalog; full scheme in rule-keys.json). Cross-check with scripts/getkeyguide.sh --list to see whether a per-key guide file exists for it. Never invent keys not in the rule-keys.md catalog — unknown keys are silently ignored by the plugin's config loader.
If your value is a script (or embeds Groovy), fetch the key's runtime script-context first — scripts/getkeycontext.sh <key> — so you author the Groovy against the real callable script-object API (it/request/response/ api/endpoint/…) rather than guessing from memory.
Step 3: Perceive — inspect existing rules
Before proposing changes, read any existing rule files in:
<project>/.easyapi/(project-scoped rules — the 3.0 model).~/.easyapi/(global rules — applied to every project on the machine).- Legacy
.easy.api.config*files in the project root (and parent
directories — EasyYapi walks up the tree for backwards compatibility).
Use the bundled scripts to inspect rules without guessing paths:
# List all rule files the plugin will load
scripts/list_rule_files.sh
# Read a specific rule file by name
scripts/read_rule_file.sh security.properties
# Check if a key is already configured (avoid duplicates — Quality Rule 1)
scripts/get_existing_rules_for_key.sh field.name api.tag
EasyYapi merges rules in priority order; the project folder overrides the global folder, which overrides the built-in rules.
Step 4: Perceive — detect custom framework patterns
Most projects do not need custom rules. EasyYapi understands standard HTTP frameworks (Spring MVC, WebFlux, JAX-RS, Feign) out of the box. Before proposing a rule, scan the project for the detection catalog signals — each detection family in scripts/listdetections.sh has a full recipe in ai/detection/<id>.md (read via scripts/getdetection_prompt.sh <id>) that lists the exact signals to look for.
# Discover every detection family the in-plugin agent knows
scripts/list_detections.sh
# Fetch the recipe for one family before scanning the codebase
scripts/get_detection_prompt.sh spring-filters-interceptors
scripts/get_detection_prompt.sh custom-framework
Use the discovery patterns under "General codebase-perception tools" above — findclassesby_supertype (your extends/implements scan) is the most common blind spot, since annotation-only scans miss inheritance-declared components. For each candidate, ask: does it change the request/response contract invisibly? If yes, fetch the matching detection recipe and apply its rule(s). If no, no rule is needed.
Step 5: Reason — is a rule actually needed?
Confirm a rule is required before drafting. Standard framework behaviour is already handled automatically — do not re-declare defaults such as @Deprecated status, @RequestMapping paths, or @RequestParam names. Only write rules for invisible contracts the plugin cannot detect (custom filters, interceptors, argument resolvers, response wrappers, non-standard annotations).
If the request is ambiguous, ask the user a short clarifying question with concrete options (single/multi choice) so they can answer quickly — mirroring the built-in agent's ask_clarification. Fall back to a plain-text question only when you can't enumerate options.
Step 6: Act — draft the new rule content
Propose new rule content in the rule file format documented in the guide:
<key>[<filter>]=<value>(one rule per line; filter optional).- Groovy scripts for advanced cases (
groovy:prefix filter, or a multi-line
groovy value-block — see Critical Quality Rule 2).
Step 7: Act — insert and show the diff
Insert the new rules into a file in .easyapi/ (project) or ~/.easyapi/ (global). Always show the user the diff before applying — EasyYapi rules affect API export across the whole project, so the user must confirm the change. This mirrors the built-in agent's proposerulecontent → user-confirmed "Save…" flow; the only difference is you write the file directly instead of staging it through a UI.
Multi-app namespacing
When a workspace hosts more than one app (each IntelliJ Module / spring.application.name is a candidate app — detect by scanning the project's module structure and application.yml files), namespace every per-app env var by a resolved key so exports don't collide. Apply this even for a single-app workspace — a single app today doesn't mean a single app forever, and bare {{host}} / ${Authorization} would collide if the user exports a different app later into the same Postman environment.
- Resolve the namespace key in order: (1) Module name (inferred from
the source file's IntelliJ module / directory), normalized lower-case with spaces/underscores → hyphens, characters outside [a-z0-9-] stripped, capped at 40 chars; (2) spring.application.name read directly from the app's application.yml/application-*.yml/ application.properties (fall through if absent); (3) ask the user a short clarifying question on collision or unresolved ambiguity.
- Namespace every env var: host
{{<key>}}, bearer{{<key>-token}},
login {{<key>-username}}/{{<key>-password}} (lower-case by default; UPPER when an existing rule already uses it — reuse the existing casing rather than renaming). The producer's stored name and the consumer's referenced name MUST be identical (bundle integrity still holds).
- Split bundles per app: propose one bundle per app, each complete on
its own (producer script + consumer header + host + env var, all sharing the same key); for consumers you can't confidently assign to an app (shared/common modules), ask the user with concrete app options.
- Record the resolution branch (module name /
spring.application.name/
user-clarified) and the resulting key in the proposal shown to the user, so they can correct a wrong guess before saving.
- Fetch the full recipe from the bundled
docs/rule-guide.md(the
"Multi-Application Namespace" section) — don't reproduce it from memory. Note: the v1 runtime converts unresolved ${...} placeholders in header values only; do not promise body-level namespacing.
Critical Rule File Format (follow exactly — inlined from the agent preamble)
Each line is <key>[<filter>]=<value> or <key>=<value> (no filter). The filter goes INSIDE [...] AFTER the key — NEVER before it. There is no filter?key=value form.
api.tag[$class:com.example.UserController]=user
method.additional.header={"name":"Authorization","value":"Bearer ${token}","desc":"","required":true}
Valid filter prefixes (and ONLY these):
$class:<FQN>— exact class-name match. Wildcards are NOT supported.
For package/pattern matching use groovy: (e.g. groovy: it.containingClass()?.qualifiedName()?.startsWith("com.example.web.")).
@<AnnotationFqn>— annotation presence.#regex:<pattern>— regex match; captured groups available as${1},
${2} in the value.
#<tag>— JavaDoc/KDoc tag.!<expr>— negation.groovy:<script>— truthy script result = match.
Class identity in Groovy is context-sensitive:
name()on a class context returns only the simple name.qualifiedName()returns the fully-qualified class name and is required for
FQN equality and package-prefix comparisons.
- For inherited members,
containingClass()is the class currently being
exported, while defineClass() is the original declaring class.
There is no ~ prefix and no bare class: prefix — the older class:com.example.Foo and ~regex forms are invalid; use $class: and #regex: respectively.
Critical Quality Rules (follow exactly — inlined from the agent preamble)
These mirror the rules the built-in agent enforces via its system prompt.
1. Check existing rules before writing (avoid duplicates)
Before proposing any rule for a key, read the existing rule files and check whether an equivalent rule already exists in any source — project (.easyapi/), global (~/.easyapi/), or bundled extension (Swagger / Jackson / etc.).
- If an equivalent rule already exists, do NOT write a duplicate. Tell the
user where it already lives and skip it.
- If a broader rule already covers your case (e.g. a
groovy:filter matching
a package prefix, and you were about to add one for a sub-package), do NOT add a narrower duplicate unless it overrides with a different value.
- Extension-source rules (Swagger annotations, Jackson modules, etc.) are
already in effect. Never re-declare what the extension already provides (e.g. api.status[@java.lang.Deprecated]=deprecated is handled by the built-in extension — do not write it).
2. Prefer groovy value-blocks for complex conditional logic
When a filter expression grows long — multiple &&/||, multiple exclusions, or nested method calls — the key[groovy:…]=value form becomes unreadable on a single line. Switch to the groovy value-block form: the value itself is a multi-line groovy script that returns the value when the condition holds, or null when it doesn't. See the rule guide's Groovy Binding Reference for the it object API.
Bad (unreadable single-line filter):
method.additional.header[groovy: it.containingClass()?.qualifiedName()?.startsWith("com.example.merchant.") && it.containingClass()?.qualifiedName() != "com.example.merchant.AuthController"]={"name":"Authorization","value":"Bearer ${token}","desc":"JWT","required":true}
Good (multi-line groovy value-block):
method.additional.header=groovy:```
def cls = it.containingClass()?.qualifiedName()
if (cls?.startsWith("com.example.merchant.")
&& cls != "com.example.merchant.AuthController") {
return '{"name":"Authorization","value":"Bearer ${token}","desc":"JWT","required":true}'
}
return null
Rules of thumb:
- **≤ 1 condition** → inline `<key>[<filter>]=<value>` is fine.
- **≥ 2 conditions or exclusions** → use a groovy value-block.
- The script must `return` the value (string) or `return null` to skip.
### 3. Never generate blanket field-ignore rules
Do NOT generate `field.ignore` rules based on field-name patterns like
`.*password.*`, `.*secret.*`, `.*token.*`. These fields are often a
**legitimate part of the API definition** — a login endpoint requires
`password`, an OAuth endpoint requires `clientSecret`, a token-refresh
endpoint requires `refreshToken`. Stripping them silently breaks the exported
documentation.
Sensitive-field handling is a **project policy** decision, not a
code-detection decision. If the user explicitly asks for it, you may add it
— but never invent it on your own, and always warn the user that it may hide
fields that some endpoints legitimately require.
### 4. Don't re-declare framework defaults
Standard Spring MVC / WebFlux / JAX-RS / Feign endpoints need no rules —
the plugin detects them out of the box. `@Deprecated` status, `@RequestMapping`
paths, `@RequestParam` names, etc. are all handled automatically. Only write
rules for **invisible contracts** the plugin cannot detect (custom filters,
interceptors, argument resolvers, response wrappers, non-standard annotations).
## Common Key-Name Mistakes (do not use these)
These keys do **not** exist — use the correct alternative:
| Does NOT exist | Use instead |
|----------------|-------------|
| `api.header` | `method.additional.header` |
| `api.header.additional` | `method.additional.header` |
| `path.prefix` | `class.prefix.path` / `endpoint.prefix.path` |
`method.additional.header` and `method.additional.param` values are **JSON
objects** (one per line):
`{"name":"…","value":"…","desc":"…","required":…}`, not `Name:Value`.
## Two-Approach Note for the User
If the user is unsure how to invoke this skill versus the plugin's built-in
AI assistant, briefly explain:
- **Built-in AI assistant (Settings → EasyYapi → Rules → Chat / Magic)** — In
IntelliJ with EasyYapi installed, open Settings → EasyYapi → Rules, edit a
rule file, and click **Chat** (reveals the inline AI panel) or **Magic**
(runs a built-in review-and-detect instruction). The plugin's agent runs a
perceive→reason→act loop, calls its PSI perception tools to inspect the
project, and stages a proposal the user reviews and saves. Best for users
who want everything inside IntelliJ.
- **This skill (external assistant)** — Use your existing AI coding assistant
(Trae, Cursor, Cline, Continue, etc.) which already has access to the
project's files. The skill bundles the **same** knowledge-base pages and
gives the assistant the same workflow, mapping each built-in PSI tool to a
CLI equivalent. Best for users already invested in an external AI workflow.
Both approaches share the same knowledge base and recipe catalog: the
built-in agent reads them from the plugin JAR (`get_plugin_doc` for the
long-form pages, `get_detection_prompt` / `get_rule_detail` for the
per-recipe catalog); this skill ships verbatim copies of both, kept in sync
by the `syncKnowledgeBase` and `syncAgentCatalog` Gradle tasks. So the rule
content they produce is consistent.
## What This Skill Does NOT Do
- It cannot call the plugin's runtime AI tools directly. You — the external
assistant — provide equivalent capability via the bundled scripts (rule
files + existing keys) and your own file/grep access (PSI inspection +
class discovery).
- It cannot enumerate the project's cached HTTP endpoints
(`list_project_endpoints`) — that requires the plugin's `ApiIndex` cache,
which only exists inside a running IntelliJ. You don't need it: rules are
about contracts detectable from source.
- It does not configure or test AI providers. The built-in assistant's
configuration lives in IntelliJ Settings → EasyYapi → AI.
- It does not modify the EasyYapi plugin itself or its bundled config.
## Reference Pointers
**Bundled with this skill (available after `npx skills add` — read these):**
- `docs/rule-guide.md` — rule file format, filter syntax, recipes, Custom-Pattern
Catalog, Workflow-Pattern Catalog, Groovy binding reference.
- `rule-keys.json` / `rule-keys.md` — complete rule-key catalog with every key's
full self-describing scheme (auto-generated; regen with `syncRuleKeySchemes`).
- `rule-contexts.json` / `rule-contexts.md` — per-key runtime script-context
(bindings + script-object method signatures), a mirror of the in-plugin
`get_rule_context` tool (auto-generated; regen with `syncRuleContexts`).
- `docs/index.md`, `docs/README.md`, `docs/settings-guide.md`, `docs/usage-guide.md`,
`docs/postman-script-reference.md` — the rest of the knowledge base.
- `ai/detection/*.md` — per-detection-family recipe catalog (verbatim mirror of
the in-plugin agent's `src/main/resources/ai/detection/`). Read via
`scripts/get_detection_prompt.sh <id>`; listed by `scripts/list_detections.sh`.
- `ai/key-guides/*.md` — per-key guide catalog (verbatim mirror of the in-plugin
agent's `src/main/resources/ai/key-guides/`). Read via `scripts/get_key_guide.sh <key>`;
listed by `scripts/get_key_guide.sh --list`.
- `scripts/` — CLI tools mirroring the built-in AI perception tools (see
"EasyYapi-domain tools" and "Catalog recipe tools" above).
Plugin home: https://github.com/tangcent/easy-yapi
## Correct Example
User asks: "Add a rule that renames the `createTime` field to `created_at`
in all exported APIs."
Workflow:
1. Check whether a per-key guide exists for `field.name`:
```bash
scripts/get_key_guide.sh field.name # → "error: unknown rule key" (no guide file)
```
No per-key guide — fall back to the long-form guide.
2. Read the bundled `docs/rule-guide.md` — find the field-rename section / the
`field.name` key.
3. Check the bundled `rule-keys.md` — confirm the key is `field.name` (alias
`json.rule.field.name`), mode `replace`.
4. **Run `scripts/get_existing_rules_for_key.sh field.name`** — confirm no
`field.name` rule already covers this.
5. Open (or create) `<project>/.easyapi/field.rules`.
6. Draft (using the correct `key[filter]=value` format; a field rename map
is a JSON object value with no filter):
```
field.name={"createTime":"created_at"}
```
7. Show the user the diff and apply on confirmation.
## Forbidden Patterns
- **Do not** invent rule keys not present in the bundled `rule-keys.md`.
Unknown keys are silently ignored by the plugin's config loader.
- **Do not** use the `filter?key=value` form, the `~` regex prefix, or the
bare `class:` prefix — they are invalid. Use `key[filter]=value`,
`#regex:`, and `$class:` respectively.
- **Do not** use the non-existent keys `api.header`, `api.header.additional`,
or `path.prefix` — use `method.additional.header` / `class.prefix.path` /
`endpoint.prefix.path`.
- **Do not** generate blanket `field.ignore` rules from field-name patterns
(password / secret / token) — see Quality Rule 3.
- **Do not** re-declare framework defaults (Spring MVC / JAX-RS / Feign
behaviour is handled automatically).
- **Do not** write Groovy scripts that touch the filesystem or network —
rule scripts run in a sandboxed Groovy shell with restricted access.
- **Do not** modify the plugin's bundled `src/main/resources/extensions/*.config`
files. Those are the plugin's own; user rules go in `.easyapi/` or
`~/.easyapi/`.