EasyApi Rule Authoring Assistant
This skill is the external mirror of EasyApi's built-in rule-authoring
agent. It helps you write or modify EasyApi rule files (.rules /
.properties files in .easyapi/) that the EasyApi IntelliJ plugin reads to
customise API export (Postman/Markdown/cURL/Hoppscotch), 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 EasyApi context.
- The user mentions
easy.api,EasyApi, 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-api 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'sget_plugin_doctool. Kept in sync by thesyncKnowledgeBaseGradle task.ai/detection/+ai/key-guides/— the per-detection / per-key guide catalog the in-plugin agent loads viaPromptCatalog(the same filesget_detection_promptandget_rule_detailread at runtime). Kept in sync by thesyncAgentCatalogGradle task.rule-keys.json+rule-keys.md— the auto-generated rule-key scheme catalog.RuleKeySchemeExporterreflects every*RuleKeysobject (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 itslist_rule_keystool. Regenerated by thesyncRuleKeySchemesGradle task, so any key added to a*RuleKeysobject is picked up automatically (a brand-new channel/framework must be registered inRuleKeyCatalog.SOURCES).rule-contexts.json+rule-contexts.md— the auto-generated script-context mirror of the in-pluginget_rule_contexttool.RuleContextExporterreuses the exact same key assembly (so it covers rule keys and the implicit keys read viaconfigReader.getFirst— one interface, the same one the built-in agent sees) and, per key, reflects the runtime bindings + script-object method signatures. Regenerated by thesyncRuleContextsGradle 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 get_plugin_doc 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 EasyApi 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 list_rule_keys 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 get_rule_context tool) |
Per-key script-context (bindings + callable script-object method signatures), auto-generated by reflecting the same rule keys. Fetch one key with scripts/get_key_context.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.
EasyApi-domain tools (bundled as scripts/)
These mirror the EasyApi-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 |
|---|---|---|
list_rule_keys |
Read bundled rule-keys.json / rule-keys.md |
Lists every supported rule key with its full self-describing scheme (auto-generated). |
get_plugin_doc |
Read the bundled *.md pages above |
Reads a knowledge-base page. |
read_rule_file |
scripts/read_rule_file.sh <name> |
Reads a rule file by name. Supports global: / project: scope prefixes. Resolves against tracked .easyapi/ dirs — never guesses home paths. |
get_existing_rules_for_key |
scripts/get_existing_rules_for_key.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. |
scripts/list_rule_files.shis also bundled — it lists every.properties/.rulesfile in<project>/.easyapi/and~/.easyapi/, labeled[global]/[project](ambient equivalent ofRuleFileResolver.listRuleFiles).
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 method.doc method.additional.header
Catalog recipe tools (mirrors of in-plugin get_detection_prompt / get_rule_detail)
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-api 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 list_rule_keys 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 get_key_guide.sh --list.
| Built-in tool | Your equivalent | What it does |
|---|---|---|
get_detection_prompt |
scripts/get_detection_prompt.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. |
get_rule_detail (by-key path) |
scripts/get_key_guide.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. |
list_rule_keys |
rule-keys.md / rule-keys.json |
Lists every supported rule key with its full self-describing scheme (auto-generated). |
get_rule_context |
scripts/get_key_context.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/get_key_guide.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/get_detection_prompt.sh <id>; for a per-key guide
question, the preferred first stop is scripts/get_key_guide.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 |
|---|---|---|
get_psi_class_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. |
get_psi_method_info |
Read the method in the class source file | For overloads, disambiguate by parameter count when you read it. |
find_classes_by_annotation |
rg -t java -t kt "<@AnnotationFqn or @Simple>" then resolve imports |
Always confirm the FQN from the import / package — @Simple names collide. |
find_classes_by_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. |
list_project_endpoints |
(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.
list_project_endpoints 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 find_classes_by_*, get_psi_class_info, and
get_existing_rules_for_key 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
get_existing_rules_for_key.sh method.doc field.name field.ignore 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, …):
scripts/list_detections.sh # discover the families scripts/get_detection_prompt.sh spring-filters-interceptors # fetch one recipe - For a per-key guide (a specific rule key like
postman.testormethod.additional.header, or a key with noRuleKeyconstant likemarkdown.curl.host):scripts/get_key_guide.sh --list # discover the keys with guides scripts/get_key_guide.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/get_key_guide.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/get_key_context.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 — EasyApi walks up the tree for backwards compatibility).
scripts/list_rule_files.sh
scripts/read_rule_file.sh security.properties
scripts/get_existing_rules_for_key.sh method.doc field.name
EasyApi 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. EasyApi 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/list_detections.sh has a full recipe in
ai/detection/<id>.md (read via scripts/get_detection_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 —
find_classes_by_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 — EasyApi rules
affect API export across the whole project, so the user must confirm the
change. This mirrors the built-in agent's propose_rule_content →
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.nameread directly from the app'sapplication.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.
method.doc[$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 usegroovy:(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, whiledefineClass()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.
method.doc[@java.lang.Deprecated]=deprecatedis 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 → EasyApi → Rules → Chat / Magic)** — In
IntelliJ with EasyApi installed, open Settings → EasyApi → 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 → EasyApi → AI.
- It does not modify the EasyApi 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
"EasyApi-domain tools" and "Catalog recipe tools" above).
Plugin home: https://github.com/tangcent/easy-api
## 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"}
- 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=valueform, the~regex prefix, or the bareclass:prefix — they are invalid. Usekey[filter]=value,#regex:, and$class:respectively. - Do not use the non-existent keys
api.header,api.header.additional, orpath.prefix— usemethod.additional.header/class.prefix.path/endpoint.prefix.path. - Do not generate blanket
field.ignorerules 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/*.configfiles. Those are the plugin's own; user rules go in.easyapi/or~/.easyapi/.