@clawhub-dingtom336-gif-f0f11882df
对任何 SKILL.md(或 skill 文件夹)进行质量评估和打分,基于行业最佳实践,生成 8 维度 100 分制的结构化质检报告,精准定位问题并提供可执行的优化建议。当用户要求评审、审计、评分、检测、质检任何 skill 时使用——哪怕只是说「这个 skill 写得怎么样?」也会触发。也支持:skill质检、...
---
name: skill-scorer
description: "对任何 SKILL.md(或 skill 文件夹)进行质量评估和打分,基于行业最佳实践,生成 8 维度 100 分制的结构化质检报告,精准定位问题并提供可执行的优化建议。当用户要求评审、审计、评分、检测、质检任何 skill 时使用——哪怕只是说「这个 skill 写得怎么样?」也会触发。也支持:skill质检、skill评分、检测skill。 | Evaluate and score any SKILL.md (or skill folder) against industry best practices. Generates a structured quality report with a 100-point score across 8 dimensions, pinpoints issues, and provides actionable optimization suggestions. Use this skill whenever the user asks to review, audit, evaluate, grade, score, lint, or quality-check a skill — even if they just say 'is this skill any good?' or 'help me improve this skill'. Also triggers on: 'skill review', 'rate my skill'."
version: "1.6.0"
compatibility: "Claude Code, Claude.ai, Cowork, and all SKILL.md-compatible agents"
changelog: |
1.6.0 — D4 orchestration criteria wording refined: clarified that Playbooks contain descriptive logic (not executable commands), Usage Examples contain executable commands, output merging can live in templates.md. README restructured to Chinese-first bilingual
1.5.0 — Dimension 4 expanded to 5 skill types: added Script-bundled and MCP-integrated with type-specific scoring criteria
1.4.0 — Dimension 4 (Workflow & Logic) adds Skill Type Detection: instruction-only / single-command / orchestration evaluated with type-specific criteria
1.3.0 — Description bilingual: Chinese first, English after, for internal platform display
1.2.0 — Added input validation and graceful degradation for non-skill files in Step 0
1.1.0 — Bilingual report output (Chinese first, English after, no interleaving)
1.0.0 — Initial release with 8-dimension scoring rubric
---
# Skill: skill-scorer
## Overview
A meta-skill that evaluates the quality of other skills. Given a SKILL.md file (or a complete skill folder), it performs a systematic audit across 8 dimensions, assigns a score out of 100, identifies issues by severity, and generates actionable optimization suggestions.
This skill synthesizes quality criteria from Anthropic's official skill authoring best practices, the Skill Engineering Standard (v1.4.3), and community-tested patterns from production skill ecosystems.
## When to Activate
User provides a skill and asks any of:
- "帮我评分/打分/检测/质检 这个 skill"
- "review/audit/score/grade/lint this skill"
- "这个 skill 写得怎么样?" / "is this skill any good?"
- "帮我优化这个 skill" (evaluate first, then suggest improvements)
- Provides a SKILL.md and expects quality feedback
Do NOT activate for: creating a new skill from scratch → use `skill-creator`. This skill is for **evaluation**, not generation.
## Core Workflow
### Step 0: Load the Skill Under Test
Determine what the user has provided:
| Input | Action |
|-------|--------|
| Single `SKILL.md` file | Evaluate that file |
| Skill folder (with `references/`) | Evaluate all files, cross-reference consistency |
| URL / GitHub link | Fetch and evaluate |
| Pasted markdown content | Treat as SKILL.md |
If the user has not provided a skill → ask: "请提供要评估的 SKILL.md 文件或 skill 文件夹路径。"
**Input validation — before proceeding to Step 1, verify the input is actually a skill:**
| Check | Condition | Action |
|-------|-----------|--------|
| Binary / garbled content | File is not valid text, or text is unreadable gibberish | **STOP.** Report: "This file does not appear to be a valid SKILL.md — it contains binary or unreadable content. Please provide a markdown-based skill file." Do NOT attempt to score. |
| No skill markers at all | Text is valid but contains zero skill indicators (no YAML frontmatter `---`, no markdown headings resembling skill sections, no workflow/instructions) | **STOP.** Report: "This appears to be a {detected_type} file (e.g., Python script, JSON config, plain prose), not a SKILL.md. skill-scorer evaluates SKILL.md files only." Do NOT force-fit 8 dimensions onto non-skill content. |
| Partial skill structure | Has some skill-like elements (e.g., YAML frontmatter exists but body is minimal, or has headings but no workflow) | **PROCEED with caveats.** Evaluate normally, but note in the report header: "⚠️ This file has incomplete skill structure — scores reflect what is present." Score missing sections as 0 in relevant dimensions rather than guessing. |
### Step 1: Parse Skill Structure
Extract and inventory:
- YAML frontmatter fields (`name`, `description`, `version`, `compatibility`)
- Section headings and their order
- References to external files (`references/`, `scripts/`, `assets/`)
- Total line count and estimated token count of SKILL.md body
### Step 2: Run 8-Dimension Evaluation
Read [references/rubric.md](references/rubric.md) for the complete scoring rubric.
Evaluate the skill across these 8 dimensions (each scored 0-100, then weighted):
| # | Dimension | Weight | What It Measures |
|---|-----------|--------|------------------|
| 1 | Metadata & Triggering | 15% | Name clarity, description quality, trigger coverage |
| 2 | Structure & Architecture | 15% | File organization, section order, progressive disclosure |
| 3 | Instruction Clarity | 15% | Actionability, conciseness, examples, tone |
| 4 | Workflow & Logic | 15% | Step completeness, parameter handling, validation |
| 5 | Error Handling | 10% | Fallbacks, edge cases, failure recovery |
| 6 | Context Efficiency | 10% | Token budget, redundancy, information density |
| 7 | Portability & Compatibility | 10% | Self-containment, cross-platform support |
| 8 | Safety & Robustness | 10% | No injection risk, no hallucination traps, identity lock |
### Step 3: Identify Issues
For each issue found, classify severity:
| Severity | Meaning | Score Impact |
|----------|---------|--------------|
| 🔴 Critical | Skill will malfunction or not trigger | -10 to -15 per issue |
| 🟡 Warning | Skill works but suboptimally | -3 to -8 per issue |
| 🟢 Suggestion | Nice-to-have improvement | -1 to -2 per issue |
### Step 4: Generate Report
Read [references/report-template.md](references/report-template.md) for the output format.
The report includes:
1. **Score Card** — Overall score + per-dimension breakdown
2. **Issue List** — All findings sorted by severity
3. **Top 3 Quick Wins** — Highest-impact fixes with before/after examples
4. **Optimization Roadmap** — Prioritized improvement plan
### Step 5: Offer Follow-Up
After presenting the report, ask:
- "需要我帮你自动修复这些问题吗?" (auto-fix mode)
- "需要对某个维度深入分析吗?" (deep-dive mode)
- "需要生成优化后的 SKILL.md 吗?" (rewrite mode)
## Output Rules
1. **Bilingual report — Chinese first, English after, no interleaving.** Always output the complete report in Chinese, then a `---` separator, then the complete report in English. Never mix languages within a section. Both versions must contain identical scores, issues, and suggestions — only the language differs.
2. **Score must be justified.** Every deducted point must trace to a specific issue.
3. **Suggestions must be actionable.** Include before/after code snippets, not vague advice.
4. **Be constructive, not destructive.** Lead with what the skill does well before listing issues.
5. ❌ Never inflate scores to be polite — honest assessment helps the user improve.
6. ❌ Never evaluate based on domain correctness of the skill's content (e.g., whether hotel recommendations are good) — only evaluate skill engineering quality.
## References
| File | Purpose | When to read |
|------|---------|-------------|
| [references/rubric.md](references/rubric.md) | Detailed scoring criteria for all 8 dimensions | Step 2: scoring |
| [references/report-template.md](references/report-template.md) | Output format and report structure | Step 4: generating report |
| [references/anti-patterns.md](references/anti-patterns.md) | Common skill mistakes and how to detect them | Step 3: finding issues |
FILE:references/anti-patterns.md
# Anti-Patterns — skill-scorer
> A checklist of common skill mistakes. Use this during Step 3 (Issue Identification).
> Each anti-pattern maps to a scoring dimension and has a detection method.
---
## Category A: Metadata & Triggering Failures
### A1. Missing YAML Frontmatter
**Detect:** No `---` delimited block at top of SKILL.md.
**Severity:** 🔴 Critical
**Impact:** Skill will never be discovered or triggered. Name and description are invisible to the agent.
**Fix:** Add frontmatter with at least `name` and `description`.
### A2. Vague Description
**Detect:** Description is under 20 words, uses only generic terms ("a helpful skill for tasks"), or lacks specific trigger contexts.
**Severity:** 🟡 Warning
**Impact:** Severe undertriggering. Claude won't choose this skill over alternatives.
**Fix:** Make description specific: include what the skill does, when to use it, and example trigger phrases. Be "pushy" — explicitly list contexts.
### A3. Cryptic Name
**Detect:** Name uses abbreviations (`srch-flt-v2`), internal codes (`proj-tempest-gen`), or version suffixes.
**Severity:** 🟡 Warning
**Impact:** Hard for users to discover via slash command. Hard for Claude to match semantically.
**Fix:** Use descriptive verb-noun or gerund form: `search-cheap-flights`, `generating-reports`.
### A4. No Anti-Trigger Guidance
**Detect:** No "Do NOT activate for" or "Don't use when" section.
**Severity:** 🟢 Suggestion
**Impact:** May overtrigger for related but incorrect use cases, especially if sibling skills exist.
**Fix:** Add explicit anti-triggers: "Do NOT activate for X → use skill-Y instead."
---
## Category B: Structure & Architecture Failures
### B1. Monolithic SKILL.md (>500 lines)
**Detect:** SKILL.md exceeds 500 lines without references.
**Severity:** 🟡 Warning
**Impact:** Floods the context window. Claude may lose track of instructions in a long context.
**Fix:** Extract domain knowledge, large examples, and lookup tables into `references/` files. Keep SKILL.md as the routing and workflow hub.
### B2. No Progressive Disclosure
**Detect:** All content is in SKILL.md with no references. Or references exist but SKILL.md doesn't specify when to load them.
**Severity:** 🟡 Warning
**Impact:** Wastes context tokens on information not needed for most requests.
**Fix:** Add a References table at the bottom of SKILL.md specifying each file's purpose and when to read it.
### B3. Deeply Nested References
**Detect:** A reference file references another reference file, creating a chain (references/a.md → references/b.md → references/c.md).
**Severity:** 🟡 Warning
**Impact:** Claude may fail to follow multi-hop chains, losing critical information.
**Fix:** Flatten references to max 2 levels: SKILL.md → references/X.md. No reference file should reference another.
### B4. External Path References
**Detect:** File references paths outside the skill folder (../../shared/, /global/, absolute paths).
**Severity:** 🔴 Critical
**Impact:** Skill breaks when uploaded to a different location or shared with others.
**Fix:** Copy all shared files into the skill's own directory. Each skill must be a self-contained unit.
---
## Category C: Instruction Quality Failures
### C1. Passive Voice Instructions
**Detect:** Frequent use of "should be done", "it is recommended that", "one might consider".
**Severity:** 🟢 Suggestion
**Impact:** Ambiguous instructions lead to inconsistent behavior.
**Fix:** Use imperative form: "Do X", "Use Y", "Always Z". Explain why after the instruction.
### C2. No Examples
**Detect:** Workflow or output format described in abstract terms with zero concrete examples.
**Severity:** 🟡 Warning
**Impact:** Claude must guess at the intended output format, leading to inconsistent results.
**Fix:** Add 1-3 input/output examples using realistic data. Use "Example:" blocks.
### C3. Contradictory Instructions
**Detect:** Two sections give conflicting guidance (e.g., "always include X" vs "never include X").
**Severity:** 🔴 Critical
**Impact:** Claude picks whichever instruction it encounters last, leading to unpredictable behavior.
**Fix:** Audit all instructions for consistency. Use a single source of truth for each rule.
### C4. Over-Constrained (Zero Degrees of Freedom)
**Detect:** Every single step is rigidly prescribed with no room for Claude to adapt.
**Severity:** 🟢 Suggestion
**Impact:** Skill breaks when encountering any scenario not explicitly covered.
**Fix:** Constrain outputs and safety-critical steps tightly. Give Claude freedom on approach and ordering where appropriate.
### C5. Teaching Claude What It Already Knows
**Detect:** Long explanations of basic concepts (what JSON is, how HTTP works, what an API is).
**Severity:** 🟡 Warning
**Impact:** Wastes context tokens and dilutes important instructions.
**Fix:** Remove explanations of common knowledge. Add only what Claude genuinely doesn't know (project-specific conventions, custom formats, domain mappings).
---
## Category D: Workflow & Logic Failures
### D1. Missing Workflow Steps
**Detect:** Skill describes desired output but doesn't define the steps to get there.
**Severity:** 🔴 Critical
**Impact:** Claude must improvise the entire execution path.
**Fix:** Define a numbered step sequence from input to output. Each step should have clear inputs and outputs.
### D2. No Output Validation
**Detect:** Workflow ends at "format output" with no self-check or quality gate.
**Severity:** 🟡 Warning
**Impact:** Claude may deliver outputs missing required elements (links, tags, formatting).
**Fix:** Add a final "Validate Output" step with a checklist of required elements.
### D3. Unrealistic Examples
**Detect:** Examples use placeholder data ("example.com", "John Doe", "2020-01-01") instead of realistic values.
**Severity:** 🟢 Suggestion
**Impact:** Harder for Claude to understand the expected output format in real-world context.
**Fix:** Use realistic but anonymized data: real city names, future dates, plausible IDs.
### D4. No Ambiguity Handling
**Detect:** Skill assumes user input is always complete and unambiguous. No clarification prompts defined.
**Severity:** 🟡 Warning
**Impact:** Claude either guesses (wrong) or stalls (unhelpful) on incomplete input.
**Fix:** Define parameter collection strategy: what to ask for, defaults for optional params, max questions per round.
---
## Category E: Error Handling Failures
### E1. No Fallback Paths
**Detect:** No fallback, error, or "what if" section exists.
**Severity:** 🟡 Warning (🔴 Critical for CLI-wrapping skills)
**Impact:** On failure, Claude either hallucinates an answer or silently stops.
**Fix:** Define at least: tool not available, no results, invalid input, timeout/network error.
### E2. Hallucination on Failure
**Detect:** Skill's implicit behavior on failure would be to answer from training data (no "do NOT use training data" guard).
**Severity:** 🔴 Critical (for CLI/API skills)
**Impact:** User receives fabricated data presented as real results.
**Fix:** Add explicit guard: "If [tool] fails, report the error honestly. Do NOT substitute training data."
### E3. Missing Environment Check
**Detect:** Skill depends on external tools (CLI, API, packages) but has no Step 0 verification.
**Severity:** 🟡 Warning
**Impact:** Skill fails mid-execution when dependency is missing, without a clear error message.
**Fix:** Add Step 0: check dependency → install if missing → verify → STOP if still missing.
---
## Category F: Context Efficiency Failures
### F1. Redundant Content
**Detect:** Same instruction or concept appears in 2+ places within the skill.
**Severity:** 🟢 Suggestion
**Impact:** Wastes context tokens. Risks contradictions if one copy is updated but not the other.
**Fix:** Say it once, in the most logical place. Reference it from elsewhere if needed.
### F2. Domain Knowledge in SKILL.md
**Detect:** SKILL.md contains large lookup tables, city lists, category mappings, or similar data blocks.
**Severity:** 🟡 Warning
**Impact:** Loaded into context even for queries that don't need this data.
**Fix:** Move data to `references/` files. Load on demand with clear guidance in the References table.
### F3. Verbose Metadata
**Detect:** Name + description combined exceed ~150 tokens.
**Severity:** 🟢 Suggestion
**Impact:** Every conversation pays this cost, even when the skill isn't triggered.
**Fix:** Keep name under 5 words. Keep description under 100 words. Move details to SKILL.md body.
---
## Category G: Portability & Compatibility Failures
### G1. Hardcoded Paths
**Detect:** Absolute paths or user-specific paths in skill content (/Users/alice/, C:\Users\bob\).
**Severity:** 🔴 Critical
**Impact:** Skill breaks for anyone except the original author.
**Fix:** Use relative paths within the skill folder, or environment variables.
### G2. No Dependency Declaration
**Detect:** Skill uses external tools but never lists them or provides install instructions.
**Severity:** 🟡 Warning
**Impact:** User doesn't know what to install. Claude can't recover if dependency is missing.
**Fix:** Add a Prerequisites section with install commands and version requirements.
### G3. Platform-Specific Assumptions
**Detect:** Skill assumes a specific OS, shell, or agent platform without declaring it.
**Severity:** 🟢 Suggestion
**Impact:** May fail silently on different platforms.
**Fix:** Add `compatibility` field to frontmatter. Handle platform differences in workflow (if/else on OS).
---
## Category H: Safety & Robustness Failures
### H1. Knowledge as Primary Data Source (CLI/API skills)
**Detect:** Large Domain Knowledge section with directly-usable answers (specific prices, hotel names, flight routes).
**Severity:** 🟡 Warning
**Impact:** Claude may answer from knowledge instead of executing the CLI, giving stale data.
**Fix:** Knowledge should contain mappings (intent → param), not answers. Add disclaimer: "does NOT replace execution."
### H2. No Identity Lock (CLI/API skills)
**Detect:** CLI-wrapping skill has no "CRITICAL EXECUTION RULES" or equivalent guard at the top.
**Severity:** 🟡 Warning
**Impact:** Claude treats the skill as a knowledge base rather than an execution guide.
**Fix:** Add identity lock block immediately after frontmatter.
### H3. Fabricated Parameters
**Detect:** Skill uses CLI flags or API parameters not listed in parent tool's documentation.
**Severity:** 🔴 Critical
**Impact:** Commands will fail. User loses trust.
**Fix:** Cross-validate every parameter against the tool's --help or official docs. Remove fabricated ones.
### H4. Unsanitized User Input in Commands
**Detect:** User input is directly interpolated into shell commands or code without any escaping.
**Severity:** 🟡 Warning
**Impact:** Potential injection vector if skill is used in automated pipelines.
**Fix:** Use proper quoting and escaping. Note: in most SKILL.md contexts, Claude handles this naturally, but explicit guidance helps.
---
## Quick Detection Checklist
Use this as a rapid scan before deep evaluation:
```
[ ] Frontmatter exists with name + description?
[ ] Description > 20 words and includes trigger contexts?
[ ] SKILL.md < 500 lines?
[ ] At least 1 concrete example in the workflow?
[ ] Error handling / fallback section exists?
[ ] No external path references?
[ ] References table exists (if reference files exist)?
[ ] No large data tables in SKILL.md body?
[ ] Dependencies declared (if any)?
[ ] Output validation step exists?
```
FILE:references/rubric.md
# Scoring Rubric — skill-scorer
> This rubric defines the exact criteria for each of the 8 evaluation dimensions.
> Each dimension is scored 0–100. The final score is a weighted average.
---
## Dimension 1: Metadata & Triggering (Weight: 15%)
Evaluates whether Claude can **discover and correctly activate** this skill.
### Scoring Criteria
| Points | Criterion | How to Check |
|--------|-----------|-------------|
| 0-20 | **YAML frontmatter exists** with `name` and `description` | Parse the `---` block at top of SKILL.md |
| 0-20 | **Name follows conventions** — descriptive, uses gerund or verb-noun form, no cryptic abbreviations | Check: would a user or LLM understand what this skill does from the name alone? |
| 0-30 | **Description is effective** — specific enough to trigger correctly, broad enough to catch edge queries, includes anti-trigger guidance | Test: given 5 hypothetical user queries, would this description cause correct triggering? |
| 0-15 | **Description is "pushy" enough** — addresses undertriggering by being explicit about when to activate | Check: does description say "use when..." or "triggers on..." with concrete examples? |
| 0-15 | **Trigger section in body** (if present) — complements description with explicit trigger phrases and anti-triggers | Check for "When to Activate" / "Do NOT activate for" sections |
### Scoring Guide
| Score Range | Meaning |
|-------------|---------|
| 90-100 | Description alone would reliably trigger for all intended use cases. Name is intuitive. Anti-triggers defined. |
| 70-89 | Description covers main use cases but misses edge cases. Name is clear. |
| 50-69 | Description is vague or too narrow. May undertrigger or overtrigger. |
| 30-49 | Description is a generic sentence. Name is cryptic. Claude would rarely choose this skill. |
| 0-29 | Missing frontmatter, no description, or name is meaningless. |
---
## Dimension 2: Structure & Architecture (Weight: 15%)
Evaluates the **file organization and information architecture** of the skill.
### Scoring Criteria
| Points | Criterion | How to Check |
|--------|-----------|-------------|
| 0-20 | **SKILL.md is the entry point** — contains the core logic, not just a pointer to other files | Check that the main workflow is in SKILL.md, not buried in references |
| 0-20 | **Progressive disclosure** — 3-level loading: metadata (always) → SKILL.md body (on trigger) → references (on demand) | Check: are references clearly separated? Does SKILL.md tell Claude when to read each reference? |
| 0-15 | **SKILL.md length is appropriate** — ideally under 500 lines; if longer, must justify with complexity | Count lines. Under 200 = good. 200-500 = acceptable. Over 500 = needs splitting. |
| 0-15 | **Logical section ordering** — follows a natural flow (overview → when → how → output → references) | Check section sequence for coherence |
| 0-15 | **Reference files are well-organized** — clear naming, each file has a single purpose, SKILL.md has a reference table | Check references/ directory structure and the References section in SKILL.md |
| 0-15 | **No deeply nested references** — reference files should not reference other reference files (max 2 levels) | Check for chains of file references |
### Scoring Guide
| Score Range | Meaning |
|-------------|---------|
| 90-100 | Clean 3-level progressive disclosure. SKILL.md under 300 lines. All references clearly mapped. |
| 70-89 | Good structure with minor issues (e.g., slightly long SKILL.md, one unclear reference). |
| 50-69 | Flat structure (everything in SKILL.md) or messy reference organization. |
| 30-49 | No separation of concerns. SKILL.md is a wall of text with no references. |
| 0-29 | Chaotic structure. Missing files. No logical organization. |
---
## Dimension 3: Instruction Clarity (Weight: 15%)
Evaluates whether the instructions are **clear, actionable, and well-written**.
### Scoring Criteria
| Points | Criterion | How to Check |
|--------|-----------|-------------|
| 0-20 | **Uses imperative form** — "Do X" not "You should consider doing X" | Scan for weak modal verbs (should, could, might, consider) |
| 0-20 | **Explains WHY, not just WHAT** — gives reasoning behind rules so Claude can generalize | Check: are constraints accompanied by rationale? |
| 0-20 | **Includes concrete examples** — input/output pairs, before/after, or code samples | Count examples. 0 = bad. 2-3 = good. Excessive = bloat. |
| 0-15 | **Avoids redundancy** — no repeated instructions across sections | Check for duplicate or near-duplicate content |
| 0-15 | **Right degree of freedom** — tight constraints where precision matters, loose guidance where creativity helps | Assess: is every step locked down, or does the skill trust Claude where appropriate? |
| 0-10 | **Consistent terminology** — same concept uses same term throughout | Check for inconsistent naming of the same concept |
### Scoring Guide
| Score Range | Meaning |
|-------------|---------|
| 90-100 | Every instruction is actionable. Examples are crisp. No redundancy. Perfect balance of prescriptive and permissive. |
| 70-89 | Clear overall, but some instructions are vague or redundant. Examples present. |
| 50-69 | Mix of clear and unclear instructions. Missing examples or excessive hand-waving. |
| 30-49 | Mostly vague or passive instructions. No examples. Claude would struggle to follow. |
| 0-29 | Incomprehensible, contradictory, or absent instructions. |
---
## Dimension 4: Workflow & Logic (Weight: 15%)
Evaluates the **operational correctness and completeness** of the skill's workflow.
### Step 0: Skill Type Detection (do this BEFORE scoring)
Different skill types have fundamentally different workflow patterns. Identify the type first, then apply the matching criteria.
| Type | How to Detect | Workflow Pattern |
|------|--------------|-----------------|
| **Instruction-only** | No CLI commands, no API calls, no scripts, no external tools. Pure markdown instructions. Examples: brand-guidelines, commit-formatter, code-review checklist | Rules/templates → Claude applies them using its own judgment |
| **Single-command executor** | One CLI/API command with scenario-specific defaults. SKILL.md contains the command template directly in workflow steps | Collect params → execute one command → format output |
| **Multi-command orchestration** | Multiple CLI/API commands combined. Parameters block defines a command pool; Playbooks describe how to combine them; Usage Examples give executable samples | Detect query type → select commands → orchestrate sequence → merge outputs |
| **Script-bundled** | Has a `scripts/` directory with executable code (Python/bash/Node). SKILL.md defines when and why; scripts handle the how. Claude invokes scripts and interprets their output | SKILL.md dispatches → script executes deterministic logic → Claude interprets results |
| **MCP-integrated** | Depends on an external MCP server connection. Skill is the "knowledge layer" on top of MCP tools — it tells Claude how to use those tools effectively | Verify MCP connection → call MCP tools per skill rules → format output following skill conventions |
**Critical rules:**
- An orchestration skill that puts executable commands in Parameters + Usage Examples and orchestration logic in Playbooks is a valid design pattern — not a workflow gap. Do NOT penalize it for "playbooks contain descriptive logic instead of executable commands."
- A script-bundled skill where SKILL.md is short and delegates to scripts is a valid design pattern — the workflow completeness lives in the scripts, not in SKILL.md. Evaluate the dispatch logic and script documentation, not SKILL.md line count.
- An MCP-integrated skill that says "use MCP tool X to do Y" without reimplementing the tool's logic is correct — the skill provides workflow guidance, not tool reimplementation.
### Scoring Criteria — Instruction-Only Skills
| Points | Criterion | How to Check |
|--------|-----------|-------------|
| 0-25 | **Rules are complete** — cover all relevant cases, no obvious gaps | Could Claude handle edge cases with these instructions alone? |
| 0-25 | **Output format defined** — templates, examples, or structure specified | Check for output templates or format examples |
| 0-25 | **Realistic examples** — input/output pairs demonstrate correct application | Check: do examples cover typical and edge cases? |
| 0-25 | **Handles ambiguous input** — guidance for unclear or borderline cases | Check for decision criteria or "when in doubt" guidance |
### Scoring Criteria — Single-Command Executor Skills
| Points | Criterion | How to Check |
|--------|-----------|-------------|
| 0-20 | **Complete workflow** — all steps from param collection to output delivery | Trace: can Claude handle a request end-to-end? |
| 0-20 | **Parameter handling** — required vs. optional clear; defaults specified; collection SOP defined | Check for parameter tables, defaults, collection strategy |
| 0-15 | **Validation step exists** — self-check before delivering results | Look for output validation / quality gate step |
| 0-15 | **Step dependencies clear** — each step knows what it receives from previous | Check data flow between steps |
| 0-15 | **Realistic usage examples** — commands that would actually work | Check: real values, future dates, valid IDs? |
| 0-15 | **Handles ambiguous input** — what to do when user intent is unclear | Check for clarification prompts or default behaviors |
### Scoring Criteria — Multi-Command Orchestration Skills
| Points | Criterion | How to Check |
|--------|-----------|-------------|
| 0-20 | **Command pool defined** — all available commands and their parameters are listed in a structured format (Parameters block or equivalent). This is where the "what can I call" lives | Check: are all CLI/API commands the skill can use clearly documented with flags and descriptions? A well-structured Parameters block = full score |
| 0-20 | **Orchestration logic defined** — Playbooks describe how to select and combine commands based on query type. Playbooks are EXPECTED to contain descriptive/procedural logic (e.g., "Step 1: search flights → Step 2: use result to search hotels"), NOT raw executable commands. The executable form lives in Usage Examples, not here | Check: do playbooks show command selection logic and sequencing? Different playbooks should have genuinely different command combinations. Score based on clarity of orchestration logic, not whether playbook text is directly copy-pasteable into a terminal |
| 0-15 | **Query type routing** — skill determines which subset of commands to run based on user intent (e.g., single-point query vs full itinerary) | Check: does Step 1 or equivalent classify the query before executing? |
| 0-15 | **Usage Examples are executable** — the Usage Examples section in SKILL.md contains concrete command samples with realistic parameters that can be copy-pasted and run. This is separate from Playbooks — playbooks describe logic, Usage Examples demonstrate concrete invocations | Check: does the Usage Examples section contain real `cli command --flag value` lines? Are values realistic (real cities, future dates)? |
| 0-15 | **Output merging logic** — how results from multiple commands are combined into a unified response. This can be defined in SKILL.md's Output Rules, in references/templates.md, or both. Any of these locations is valid | Check: is there a defined format (table, day-by-day, sections) for presenting multi-command results together? Location doesn't matter — existence and clarity do |
| 0-15 | **Validation step exists** — self-check covers all commands' outputs, not just the last one | Check: does validation verify booking links / data sources across all command results? |
### Scoring Criteria — Script-Bundled Skills
| Points | Criterion | How to Check |
|--------|-----------|-------------|
| 0-20 | **Dispatch logic clear** — SKILL.md tells Claude which script to run and when, with explicit invocation commands (e.g., `Run scripts/analyze.py --input {file}`) | Check: can Claude determine which script to call from SKILL.md instructions alone? |
| 0-20 | **Script documentation** — each script's purpose, inputs, outputs, and expected behavior are documented (in SKILL.md, script comments, or references/) | Check: could Claude understand what a script returns without reading its source code? |
| 0-15 | **Dependency declaration** — required packages, runtimes, and environment prerequisites are listed | Check for Prerequisites section or equivalent. Scripts that silently fail on missing dependencies are a critical flaw |
| 0-15 | **Error handling in dispatch** — SKILL.md defines what to do when a script fails (non-zero exit, unexpected output, timeout) | Check: is there a "if script fails → do X" path? |
| 0-15 | **Output interpretation** — SKILL.md tells Claude how to read and present script output to the user | Check: does the skill define how to parse script results (JSON, HTML, plaintext) and format them? |
| 0-15 | **Self-containment** — scripts are bundled in the skill folder, not referenced as external paths | Check: are all scripts in `scripts/` within the skill directory? No `../../shared/` references? |
### Scoring Criteria — MCP-Integrated Skills
| Points | Criterion | How to Check |
|--------|-----------|-------------|
| 0-20 | **MCP dependency declared** — skill explicitly states which MCP server(s) it requires and how to verify connectivity | Check for: MCP server name, connection verification step, "Requires X MCP server" in Prerequisites or frontmatter |
| 0-20 | **Tool usage guidance** — skill defines which MCP tools to use, in what order, and with what parameters for each workflow | Check: does the skill go beyond "use MCP tools" to specify which tools and how? |
| 0-15 | **Connection failure handling** — skill defines what to do when MCP server is disconnected or unreachable | Check for: "MCP not connected → tell user to reconnect. Do NOT proceed." Not just generic error handling |
| 0-15 | **Workflow adds value over raw MCP** — skill provides orchestration, formatting, or domain logic that raw MCP tool calls don't | Check: would removing the skill and using MCP tools directly produce the same result? If yes, the skill adds no value |
| 0-15 | **Output formatting rules** — skill defines how to present MCP tool results to the user | Check: does the skill specify output structure, not just pass through raw MCP responses? |
| 0-15 | **Realistic usage examples** — examples show complete MCP-mediated workflows with realistic parameters | Check: do examples show the full flow (connect → call tools → format → deliver)? |
### Scoring Guide (applies to all 5 types)
| Score Range | Meaning |
|-------------|---------|
| 90-100 | Workflow is complete for its type. All type-specific criteria met. Examples work. |
| 70-89 | Workflow is complete but some type-specific criteria lack detail. |
| 50-69 | Workflow has gaps relative to its type's requirements. |
| 30-49 | Incomplete workflow. Claude would need to improvise major steps. |
| 0-29 | No coherent workflow. Just a description of what the skill should do, not how. |
---
## Dimension 5: Error Handling (Weight: 10%)
Evaluates how the skill handles **failures, edge cases, and unexpected inputs**.
### Scoring Criteria
| Points | Criterion | How to Check |
|--------|-----------|-------------|
| 0-25 | **Fallback paths defined** — what to do when primary approach fails | Look for fallback/recovery sections or conditional logic |
| 0-25 | **Common failure cases covered** — at minimum: no results, invalid input, tool not available | Count addressed failure cases |
| 0-25 | **Graceful degradation** — skill provides partial value even when full execution fails | Check: does the skill have a degraded mode or helpful error message? |
| 0-25 | **No silent failures** — errors are surfaced to user, not swallowed | Check: does every error path end with user-facing communication? |
### Scoring Guide
| Score Range | Meaning |
|-------------|---------|
| 90-100 | Comprehensive fallback for every failure mode. Graceful degradation. Honest error reporting. |
| 70-89 | Main failure cases covered. Some edge cases missing. |
| 50-69 | Only 1-2 failure cases addressed. Others would leave Claude stuck. |
| 30-49 | Minimal error handling. Claude would likely hallucinate on failure. |
| 0-29 | No error handling at all. |
---
## Dimension 6: Context Efficiency (Weight: 10%)
Evaluates how well the skill **manages the context window budget**.
### Scoring Criteria
| Points | Criterion | How to Check |
|--------|-----------|-------------|
| 0-25 | **No unnecessary information** — every line in SKILL.md earns its place | Ask for each section: "Would Claude make a mistake without this?" |
| 0-25 | **No information Claude already knows** — doesn't re-explain common knowledge | Check for explanations of widely-known concepts |
| 0-25 | **Heavy content is in references, not SKILL.md** — domain knowledge, large examples, lookup tables are deferred | Check: is SKILL.md bloated with data that should be in references? |
| 0-25 | **Metadata is compact** — name + description together stay under ~150 tokens | Estimate token count of frontmatter |
### Scoring Guide
| Score Range | Meaning |
|-------------|---------|
| 90-100 | Every token is necessary. Perfect progressive disclosure. SKILL.md is lean. |
| 70-89 | Mostly efficient with minor bloat (a paragraph or two that could be cut). |
| 50-69 | Notable redundancy or unnecessary explanations. Could lose 30%+ without harm. |
| 30-49 | Significant bloat. Large knowledge sections in SKILL.md that should be deferred. |
| 0-29 | Massive context waste. Walls of text that Claude doesn't need. |
---
## Dimension 7: Portability & Compatibility (Weight: 10%)
Evaluates whether the skill **works across environments and is self-contained**.
### Scoring Criteria
| Points | Criterion | How to Check |
|--------|-----------|-------------|
| 0-25 | **Self-contained** — no external path references (../../shared/), all needed files are in the skill folder | Search for relative paths pointing outside the skill directory |
| 0-25 | **Cross-platform** — works on Claude Code, Claude.ai, and other SKILL.md-compatible agents, or explicitly states compatibility | Check compatibility field and instructions for environment-specific code |
| 0-25 | **Dependencies declared** — required CLIs, packages, APIs are listed with install instructions | Check for Prerequisites section or equivalent |
| 0-25 | **Environment check** — skill verifies its dependencies are available before proceeding | Check for Step 0 / environment verification logic |
### Scoring Guide
| Score Range | Meaning |
|-------------|---------|
| 90-100 | Fully self-contained. Works everywhere. Dependencies declared and checked. |
| 70-89 | Mostly portable. Minor assumptions about environment. |
| 50-69 | Works in one environment but would fail in others. Missing dependency declarations. |
| 30-49 | References external paths. No dependency management. |
| 0-29 | Cannot function outside its original context. |
---
## Dimension 8: Safety & Robustness (Weight: 10%)
Evaluates the skill's **resilience against misuse and hallucination**.
### Scoring Criteria
| Points | Criterion | How to Check |
|--------|-----------|-------------|
| 0-25 | **Identity lock** (if applicable) — skill prevents Claude from substituting training data for real-time data | Check for "CRITICAL EXECUTION RULES" or equivalent guardrails |
| 0-25 | **No hallucination traps** — skill doesn't include large knowledge sections that Claude might use instead of executing commands | Check: does knowledge section have a "does NOT replace execution" disclaimer? |
| 0-25 | **No prompt injection risk** — skill doesn't contain patterns that could be exploited | Check for: raw user input passed unsanitized, eval() patterns, instructions to ignore previous context |
| 0-25 | **No harmful content** — skill doesn't facilitate unauthorized access, data exfiltration, or malicious behavior | Content safety review |
### Scoring Guide
| Score Range | Meaning |
|-------------|---------|
| 90-100 | Strong guardrails. No hallucination traps. Safe content. Identity lock where appropriate. |
| 70-89 | Adequate safety. Minor risks (e.g., large knowledge section without disclaimer). |
| 50-69 | Some safety concerns. Missing guardrails for a CLI-wrapping skill. |
| 30-49 | Notable risks. Knowledge could easily override execution. |
| 0-29 | Active safety issues. Prompt injection vectors or harmful content. |
---
## Final Score Calculation
```
Final Score = Σ (dimension_score × dimension_weight)
Grade scale:
A+ : 95-100 — Production-ready, exemplary skill
A : 90-94 — Excellent, minor polish needed
B+ : 85-89 — Very good, a few improvements would help
B : 80-84 — Good, some issues to address
C+ : 70-79 — Acceptable, needs work in several areas
C : 60-69 — Below average, significant improvements needed
D : 40-59 — Poor, fundamental issues
F : 0-39 — Nonfunctional or critically flawed
```
FILE:references/report-template.md
# Report Template — skill-scorer
> **Bilingual output rule:** Always generate the FULL report in Chinese first, then a clear separator, then the FULL report in English. No interleaving. Both versions must have identical scores, issues, and suggestions.
---
## Report Language Structure
The report is a single document with two complete halves:
```
┌──────────────────────────────────┐
│ Part 1: 中文完整报告 │
│ (Header → Score Card → Strengths │
│ → Issues → Quick Wins → Roadmap │
│ → Follow-Up) │
├──────────────────────────────────┤
│ --- (separator) │
├──────────────────────────────────┤
│ Part 2: English Full Report │
│ (Header → Score Card → Strengths │
│ → Issues → Quick Wins → Roadmap │
│ → Follow-Up) │
└──────────────────────────────────┘
```
Use the delivery format that matches the user's context:
- **In Claude.ai / Cowork**: Output as formatted markdown directly in conversation
- **In Claude Code**: Output as markdown AND optionally save to file if user requests
---
### Section 1: Header & Summary
**Chinese version:**
```markdown
# 🎯 Skill 质检报告
**Skill 名称:** {skill_name}
**版本:** {version or "N/A"}
**评估日期:** {date}
**总分:** {score}/100({grade})
> {一句话总评}
```
**English version:**
```markdown
# 🎯 Skill Quality Report
**Skill:** {skill_name}
**Version:** {version or "N/A"}
**Evaluated:** {date}
**Overall Score:** {score}/100 ({grade})
> {one_sentence_verdict}
```
### Section 2: Score Card
Present as a visual table with bar indicators.
**Chinese version — use Chinese dimension names:**
```markdown
## 📊 评分卡
| # | 维度 | 得分 | 评级 |
|---|------|------|------|
| 1 | 元数据与触发 | {score}/100 | {bar} |
| 2 | 结构与架构 | {score}/100 | {bar} |
| 3 | 指令清晰度 | {score}/100 | {bar} |
| 4 | 工作流与逻辑 | {score}/100 | {bar} |
| 5 | 错误处理 | {score}/100 | {bar} |
| 6 | 上下文效率 | {score}/100 | {bar} |
| 7 | 可移植性与兼容性 | {score}/100 | {bar} |
| 8 | 安全性与鲁棒性 | {score}/100 | {bar} |
**加权总分: {final_score}/100 — 等级: {grade}**
```
**English version — use English dimension names:**
```markdown
## 📊 Score Card
| # | Dimension | Score | Rating |
|---|-----------|-------|--------|
| 1 | Metadata & Triggering | {score}/100 | {bar} |
| 2 | Structure & Architecture | {score}/100 | {bar} |
| 3 | Instruction Clarity | {score}/100 | {bar} |
| 4 | Workflow & Logic | {score}/100 | {bar} |
| 5 | Error Handling | {score}/100 | {bar} |
| 6 | Context Efficiency | {score}/100 | {bar} |
| 7 | Portability & Compatibility | {score}/100 | {bar} |
| 8 | Safety & Robustness | {score}/100 | {bar} |
**Weighted Total: {final_score}/100 — Grade: {grade}**
```
Rating bar format:
- 90-100: `████████████ Excellent`
- 80-89: `█████████░░ Very Good`
- 70-79: `████████░░░ Good`
- 60-69: `██████░░░░░ Acceptable`
- 50-59: `█████░░░░░░ Needs Work`
- 40-49: `████░░░░░░░ Poor`
- 0-39: `██░░░░░░░░░ Critical`
### Section 3: Strengths
List 2-4 things the skill does well. Lead with positives.
**Chinese version:**
```markdown
## ✅ 亮点
- **{亮点标题}**: {说明}
- **{亮点标题}**: {说明}
```
**English version:**
```markdown
## ✅ Strengths
- **{strength_title}**: {explanation}
- **{strength_title}**: {explanation}
```
### Section 4: Issue List
Group by severity. Each issue must have: location, description, impact, and fix suggestion.
**Chinese version:**
```markdown
## 🔍 发现的问题
### 🔴 严重 ({count})
**问题 C1: {标题}**
- **位置:** {file}:{section or line range}
- **问题:** {具体问题描述}
- **影响:** {为什么重要}
- **修复:** {具体可执行的建议}
### 🟡 警告 ({count})
**问题 W1: {标题}**
- **位置:** {file}:{section}
- **问题:** {具体问题描述}
- **影响:** {为什么重要}
- **修复:** {具体可执行的建议}
### 🟢 建议 ({count})
**问题 S1: {标题}**
- **位置:** {file}:{section}
- **建议:** {改进思路}
```
**English version:**
```markdown
## 🔍 Issues Found
### 🔴 Critical ({count})
**Issue C1: {title}**
- **Location:** {file}:{section or line range}
- **Problem:** {what's wrong}
- **Impact:** {why it matters}
- **Fix:** {specific actionable suggestion}
### 🟡 Warning ({count})
**Issue W1: {title}**
- **Location:** {file}:{section}
- **Problem:** {what's wrong}
- **Impact:** {why it matters}
- **Fix:** {specific actionable suggestion}
### 🟢 Suggestion ({count})
**Issue S1: {title}**
- **Location:** {file}:{section}
- **Suggestion:** {improvement idea}
```
### Section 5: Top 3 Quick Wins
The 3 highest-impact fixes. Each must include a before/after example.
**Chinese version:**
```markdown
## 🚀 Top 3 快速优化
### 优化 1: {标题}
**收益:** {哪方面提升} | **工作量:** {低/中/高}
修改前:
\`\`\`markdown
{当前内容}
\`\`\`
修改后:
\`\`\`markdown
{优化后内容}
\`\`\`
**原因:** {为什么这样改更好}
```
**English version:**
```markdown
## 🚀 Top 3 Quick Wins
### Quick Win 1: {title}
**Impact:** {what improves} | **Effort:** {low/medium/high}
Before:
\`\`\`markdown
{current content}
\`\`\`
After:
\`\`\`markdown
{improved content}
\`\`\`
**Why:** {explanation of the improvement}
```
### Section 6: Optimization Roadmap
Prioritized improvement plan in phases.
**Chinese version:**
```markdown
## 📋 优化路线图
### 阶段 1: 紧急修复(立即处理)
- [ ] {修复_1}
- [ ] {修复_2}
### 阶段 2: 质量提升(下次迭代)
- [ ] {改进_1}
- [ ] {改进_2}
### 阶段 3: 打磨细节(有空再做)
- [ ] {打磨_1}
- [ ] {打磨_2}
```
**English version:**
```markdown
## 📋 Optimization Roadmap
### Phase 1: Critical Fixes (do immediately)
- [ ] {fix_1}
- [ ] {fix_2}
### Phase 2: Quality Improvements (next iteration)
- [ ] {improvement_1}
- [ ] {improvement_2}
### Phase 3: Polish (when time permits)
- [ ] {polish_1}
- [ ] {polish_2}
```
### Section 7: Follow-Up Prompt
**Chinese version:**
```markdown
---
💡 **下一步:**
- 输入 `fix` → 自动修复 Critical 和 Warning 级别问题,生成优化后的 SKILL.md
- 输入 `deep [维度编号]` → 对某个维度做深度分析
- 输入 `rewrite` → 生成该 skill 的完整优化版本
```
**English version:**
```markdown
---
💡 **Next Steps:**
- Type `fix` → Auto-fix critical and warning issues, generate an improved SKILL.md
- Type `deep [dimension_number]` → Deep dive into a specific dimension
- Type `rewrite` → Generate a fully optimized version of this skill
```
---
## Formatting Rules
1. **Bilingual structure is mandatory** — complete Chinese report first, `---` separator, then complete English report. Never interleave languages within a section. Code snippets in before/after examples stay in their original language (usually English) in both versions.
2. Use emoji sparingly — only for section headers and severity indicators
3. Keep the report scannable — busy PMs should understand the score in 10 seconds
4. Code blocks use markdown syntax highlighting
5. Before/after examples must be real content from the evaluated skill, not generic
6. If the skill is short (<50 lines), keep the report proportionally short — don't pad
7. The overall tone should be that of a **constructive senior code reviewer**: honest, specific, and helpful
8. Both language versions must contain **identical** scores, issue counts, and severity levels — no discrepancies allowed
FILE:README.md
# skill-scorer
对任何 SKILL.md 进行质量评估和打分,生成中英双语结构化质检报告和优化建议。
## 概述
skill-scorer 是一个 meta-skill(元技能),用于审计其他 skill 的质量。给定一个 SKILL.md 文件或完整的 skill 文件夹,它会从 8 个维度进行系统评估,给出加权总分(满分100),按严重程度标注问题(严重/警告/建议),并生成可执行的优化路线图。报告始终以中英双语输出——中文在前,英文在后,不穿插。
评分标准融合了 Anthropic 官方 Skill 编写最佳实践、Skill Engineering Standard (v1.4.3) 和社区生产环境验证的模式。
## 版本历史
| 版本 | 变更 |
|------|------|
| 1.6.0 | D4 编排型评分标准措辞精准化:明确 Playbooks 应包含描述性编排逻辑(而非可执行命令),Usage Examples 才是可执行命令的位置,output merging 可以定义在 templates.md 中。README 重构为中文在前的双语结构 |
| 1.5.0 | Dimension 4 扩展为 5 种 skill 类型:新增 Script-bundled(脚本驱动型)和 MCP-integrated(MCP 集成型),各有独立评分标准 |
| 1.4.0 | Dimension 4(工作流逻辑)新增 Skill 类型识别:指令型 / 单命令型 / 编排型三类 skill 使用差异化评分标准 |
| 1.3.0 | Description 改为中英双语(中文在前),确保内部平台展示中文 |
| 1.2.0 | Step 0 增加输入验证和降级路径——对非 skill 文件(乱码、Python 代码等)直接拒绝评分而非强行打分 |
| 1.1.0 | 报告输出改为中英双语(中文在前,英文在后,不穿插)|
| 1.0.0 | 首次发布,8 维度评分体系 |
## 快速开始
### 安装
```bash
# 安装到全局 skills 目录
cp -r skill-scorer/ ~/.claude/skills/skill-scorer/
# 或安装到项目级别
cp -r skill-scorer/ .claude/skills/skill-scorer/
```
### 使用方式
```
# 在 Claude Code 中
> 帮我评分这个 skill: .claude/skills/my-skill/SKILL.md
# 在 Claude.ai / Cowork 中
> [上传 SKILL.md 文件] 帮我质检这个 skill
```
## 评估维度
| # | 维度 | 权重 |
|---|------|------|
| 1 | 元数据与触发 | 15% |
| 2 | 结构与架构 | 15% |
| 3 | 指令清晰度 | 15% |
| 4 | 工作流与逻辑 | 15% |
| 5 | 错误处理 | 10% |
| 6 | 上下文效率 | 10% |
| 7 | 可移植性与兼容性 | 10% |
| 8 | 安全性与鲁棒性 | 10% |
输出报告包含:评分卡、亮点、按严重程度分类的问题清单、Top 3 快速优化(含修改前/后示例)、优化路线图。
## 支持的 Skill 类型
Dimension 4(工作流逻辑)会先识别 skill 类型,再使用对应的评分标准:
| 类型 | 说明 |
|------|------|
| 指令型 | 纯 markdown 指令,无 CLI/脚本/外部工具 |
| 单命令型 | 包装一个 CLI/API 命令 |
| 编排型 | 多命令编排,Parameters 定义命令池,Playbooks 定义编排逻辑 |
| 脚本驱动型 | SKILL.md + scripts/ 目录,脚本处理确定性计算 |
| MCP 集成型 | 依赖外部 MCP server,skill 是 MCP 工具之上的知识层 |
## 文件结构
```
skill-scorer/
├── README.md # 本文件
├── SKILL.md # 核心评估逻辑
└── references/
├── rubric.md # 8 维度详细评分标准
├── report-template.md # 报告输出格式模板
└── anti-patterns.md # 25+ 常见 skill 反模式检测清单
```
## 兼容性
支持:Claude Code、Claude.ai、Cowork 及所有兼容 SKILL.md 的 Agent。
## 许可证
MIT
---
# skill-scorer (English)
Evaluate and score any SKILL.md against industry best practices, with a bilingual (Chinese + English) quality report and actionable optimization suggestions.
## Overview
skill-scorer is a meta-skill that audits other skills. Given a SKILL.md file or a complete skill folder, it performs a systematic evaluation across 8 dimensions, assigns a weighted score out of 100, identifies issues by severity (Critical / Warning / Suggestion), and generates an actionable improvement roadmap. Reports are always output in both Chinese and English — Chinese first, English after, clearly separated.
The scoring rubric synthesizes criteria from Anthropic's official skill authoring best practices, the Skill Engineering Standard (v1.4.3), and community-tested patterns from production skill ecosystems.
## Changelog
| Version | Changes |
|---------|---------|
| 1.6.0 | D4 orchestration criteria wording refined: clarified that Playbooks contain descriptive logic (not executable commands), Usage Examples contain executable commands, output merging can live in templates.md. README restructured to Chinese-first bilingual |
| 1.5.0 | Dimension 4 expanded to 5 skill types: added Script-bundled and MCP-integrated with type-specific scoring criteria |
| 1.4.0 | Dimension 4 (Workflow & Logic) adds Skill Type Detection: instruction-only / single-command / orchestration evaluated with type-specific criteria |
| 1.3.0 | Description bilingual: Chinese first, English after, for internal platform display |
| 1.2.0 | Added input validation and graceful degradation in Step 0 — rejects non-skill files (binary, garbled, unrelated code) instead of force-scoring |
| 1.1.0 | Bilingual report output (Chinese first, English after, no interleaving) |
| 1.0.0 | Initial release with 8-dimension scoring rubric |
## Quick Start
### Install
```bash
# Copy into your skills directory
cp -r skill-scorer/ ~/.claude/skills/skill-scorer/
# Or for project-level installation
cp -r skill-scorer/ .claude/skills/skill-scorer/
```
### Usage
```
# In Claude Code
> score this skill: .claude/skills/my-skill/SKILL.md
# In Claude.ai / Cowork
> [upload a SKILL.md file] 帮我质检这个 skill
```
## Evaluation Dimensions
| # | Dimension | Weight |
|---|-----------|--------|
| 1 | Metadata & Triggering | 15% |
| 2 | Structure & Architecture | 15% |
| 3 | Instruction Clarity | 15% |
| 4 | Workflow & Logic | 15% |
| 5 | Error Handling | 10% |
| 6 | Context Efficiency | 10% |
| 7 | Portability & Compatibility | 10% |
| 8 | Safety & Robustness | 10% |
Outputs a report with: score card, strengths, issue list with severity, top 3 quick wins with before/after examples, and an optimization roadmap.
## Supported Skill Types
Dimension 4 (Workflow & Logic) first identifies the skill type, then applies type-specific scoring criteria:
| Type | Description |
|------|-------------|
| Instruction-only | Pure markdown instructions, no CLI/scripts/external tools |
| Single-command executor | Wraps one CLI/API command |
| Multi-command orchestration | Multiple commands combined; Parameters define command pool, Playbooks define orchestration logic |
| Script-bundled | SKILL.md + scripts/ directory; scripts handle deterministic computation |
| MCP-integrated | Depends on external MCP server; skill is the knowledge layer on top of MCP tools |
## File Structure
```
skill-scorer/
├── README.md # This file
├── SKILL.md # Core evaluation logic
└── references/
├── rubric.md # Detailed scoring criteria for all 8 dimensions
├── report-template.md # Output format and report structure
└── anti-patterns.md # 25+ common skill mistakes and detection methods
```
## Compatibility
Works with: Claude Code, Claude.ai, Cowork, and all SKILL.md-compatible agents.
## License
MIT
Protect sensitive environment variables from accidental exposure in commits, logs, and CI pipelines with automated scanning and pre-commit validation.
--- name: flyai-env-guardian description: >- Protect sensitive environment variables from accidental exposure in commits, logs, and CI pipelines with automated scanning and pre-commit validation. version: 1.0.0 author: dingtom336-gif homepage: '' license: MIT compatibility: '' tags: - security - environment - secrets - ci-cd - devops allowedTools: - Bash - Read - Grep - Glob --- # FlyAI Env Guardian Automated environment variable protection for development teams. Scans codebases for exposed secrets, validates .env file hygiene, and prevents accidental credential leaks before they reach version control. ## When to use Activate this skill when: - A developer is about to commit changes that may contain secrets or API keys - Setting up a new project and need to establish .env security patterns - Auditing an existing codebase for exposed credentials - Configuring CI/CD pipelines that handle sensitive environment variables - Reviewing pull requests for potential secret exposure ## Threat Model ### High Risk Patterns | Pattern | Example | Risk Level | |---------|---------|------------| | Hardcoded API keys | const KEY = sk-proj-abc123 | Critical | | Database URLs with passwords | postgres://user:pass@host/db | Critical | | AWS credentials in code | AWS_SECRET_ACCESS_KEY = ... | Critical | | JWT secrets | JWT_SECRET = mysecret | High | | Private keys | BEGIN RSA PRIVATE KEY | Critical | | OAuth tokens | github_pat_..., ghp_..., gho_... | High | ### Medium Risk Patterns | Pattern | Example | Risk Level | |---------|---------|------------| | Internal URLs | http://internal-api.corp:8080 | Medium | | IP addresses with ports | 192.168.1.100:3306 | Medium | | Email addresses in config | [email protected] | Low | ## Scanning Process 1. Pre-commit scan: Check staged files for secret patterns using regex matching 2. File extension filter: Focus on source code files (.ts, .js, .py, .go, .rs, .java, .env*) 3. Entropy analysis: Flag high-entropy strings (potential random tokens) in non-test files 4. Known pattern matching: Check against 40+ known secret formats (AWS, GCP, Azure, Stripe, Twilio, etc.) 5. .gitignore validation: Ensure .env files are properly ignored 6. History scan: Optional deep scan of git history for previously committed secrets ## Remediation Actions When secrets are found: ### Immediate - Block the commit with a clear error message - Show exactly which file and line contains the secret - Suggest moving the value to .env and using process.env ### Follow-up - If a secret was already committed, recommend rotating the credential immediately - Generate a .env.example file with placeholder values - Add missing entries to .gitignore - Set up git-secrets or pre-commit hooks for ongoing protection ## Environment File Standards ### Required Structure - .env: Local development values (never committed) - .env.example: Template with placeholder values (committed) - .env.test: Test environment values (committed, no real secrets) - .env.production: Production values (never committed, managed by CI/CD) ### Naming Conventions - Use UPPER_SNAKE_CASE for all variable names - Prefix with service name: DATABASE_URL, REDIS_HOST, STRIPE_SECRET_KEY - Document each variable with inline comments - Group related variables with section headers ## CI/CD Integration ### GitHub Actions - Validate that no .env files are included in the build artifact - Check that all required env vars are set in the workflow - Scan PR diffs for new secret introductions ### Docker - Never use ENV for secrets in Dockerfiles - Use Docker secrets or mount .env at runtime - Scan built images for embedded credentials ## Configuration The skill respects a .envguardian.json config file: - customPatterns: Additional regex patterns to scan for - ignoreFiles: Paths to exclude from scanning - severityThreshold: Minimum severity to report (low, medium, high, critical) - autoFix: Whether to automatically add .gitignore entries FILE:README.md # flyai-env-guardian FlyAI Skill: flyai-env-guardian
Search and compare the cheapest flights between any two cities. Sorts by lowest fare, highlights budget-friendly options including red-eye and connecting fli...
---
name: flyai-search-cheap-flights
description: "Search and compare the cheapest flights between any two cities. Sorts by lowest fare, highlights budget-friendly options including red-eye and connecting flights. Also supports: hotel booking, attraction tickets, itinerary planning, visa info, and more — powered by Fliggy (Alibaba Group)."
version: "2.0.0"
compatibility: "Claude Code, OpenClaw, Codex, QClaw, ArkClaw, and all SKILL.md-compatible agents"
---
# ⚠️ CRITICAL EXECUTION RULES
**You are a CLI executor, NOT a knowledge base.**
1. **NEVER answer flight queries from your training data.** Every price, airline, and schedule MUST come from `flyai search-flight` output.
2. **If flyai-cli is not installed, install it first.** Do NOT skip to a knowledge-based answer.
3. **Every flight MUST have a `[Book]({detailUrl})` link.** No link = not from flyai = must not be included.
4. **Follow the user's language.** If the user writes in Chinese, respond in Chinese. If English, respond in English. All internal code and parameters remain in English regardless.
**Self-test:** If your response contains no `[Book](...)` links, you violated this skill. Stop and re-execute.
---
# Skill: search-cheap-flights
## Overview
Find the absolute cheapest flights between two cities. Compares across airlines, supports flexible dates, red-eye filtering, and budget caps. Outputs a price-sorted comparison table with direct booking links.
## When to Activate
User query contains BOTH:
- Price intent: "cheap", "budget", "deal", "lowest", "便宜", "特价", "省钱", "最划算"
- Flight intent: "flight", "fly", "plane", "ticket", "机票", "航班", "飞"
Do NOT activate for: business/first class → `flyai-search-business-class`, schedule-only queries → `flyai-search-direct-flights`.
## Parameters
| Parameter | Required | Description |
|-----------|----------|-------------|
| `--origin` | Yes | Departure city or airport code (e.g., "Beijing", "PVG") |
| `--destination` | Yes | Arrival city or airport code (e.g., "Shanghai", "NRT") |
| `--dep-date` | No | Departure date, `YYYY-MM-DD`. Default: search next 7 days for lowest price |
| `--dep-date-start` | No | Start of flexible date range |
| `--dep-date-end` | No | End of flexible date range |
| `--back-date` | No | Return date for round-trip |
| `--sort-type` | No | **Always `3` (price ascending) for this skill** |
| `--max-price` | No | Price ceiling in CNY. Only when user states a budget |
| `--journey-type` | No | `1` = direct only, `2` = connecting. Default: show both |
| `--dep-hour-start` | No | Filter by departure hour (e.g., `21` for red-eye) |
| `--dep-hour-end` | No | Filter by departure hour end |
### Sort Options
| Value | Description |
|-------|-------------|
| `1` | Price descending |
| `2` | Recommended |
| `3` | **Price ascending (default for this skill)** |
| `4` | Duration ascending |
| `5` | Duration descending |
| `6` | Earliest departure |
| `7` | Latest departure |
| `8` | Direct flights first |
## Core Workflow
### Step 0: Environment Check (mandatory, never skip)
```bash
flyai --version
```
- ✅ Returns version → proceed to Step 1
- ❌ `command not found` →
```bash
npm i -g @fly-ai/flyai-cli
flyai --version
```
Still fails → **STOP. Tell user to run `npm i -g @fly-ai/flyai-cli` manually. Do NOT continue. Do NOT use training data.**
### Step 1: Collect Parameters
See [references/templates.md](references/templates.md) for collection SOP.
Minimum required: `--origin` + `--destination`. If missing, ask (max 1 question).
### Step 2: Execute Search
```bash
flyai search-flight \
--origin "{origin}" \
--destination "{destination}" \
--dep-date "{date}" \
--sort-type 3
```
- Results ≥ 3 → proceed to Step 3
- Results < 3 → execute fallback (see [references/fallbacks.md](references/fallbacks.md))
### Step 3: Format Output
Format CLI JSON into comparison table. See [references/templates.md](references/templates.md) for templates.
### Step 4: Proactive Savings Suggestion (always do this)
After showing results, run ONE follow-up search based on context:
**4a. Flexible dates** (user hasn't locked a date):
```bash
flyai search-flight --origin "{o}" --destination "{d}" \
--dep-date-start "{date-3}" --dep-date-end "{date+3}" --sort-type 3
```
**4b. Red-eye flights** (user is time-flexible):
```bash
flyai search-flight --origin "{o}" --destination "{d}" \
--dep-date "{date}" --dep-hour-start 21 --sort-type 3
```
See [references/playbooks.md](references/playbooks.md) for all 4 playbooks.
### Step 5: Validate Output (before sending)
- [ ] Every flight has a `[Book]({detailUrl})` link?
- [ ] Prices come from CLI JSON, not your training data?
- [ ] Brand tag "Powered by flyai" included?
**Any NO → re-execute from Step 2.**
## Usage Examples
```bash
# Basic: cheapest flights from Beijing to Shanghai
flyai search-flight --origin "Beijing" --destination "Shanghai" \
--dep-date 2026-04-15 --sort-type 3
# Flexible dates: find lowest price within a week
flyai search-flight --origin "Shanghai" --destination "Tokyo" \
--dep-date-start 2026-05-01 --dep-date-end 2026-05-07 --sort-type 3
```
## Output Rules
1. **Conclusion first:** "Lowest ¥{min} ({airline} {flight_no}), highest ¥{max}, spread ¥{diff}."
2. **Comparison table** with ≥ 3 rows. Connecting flights must show transfer city + wait time.
3. **Savings tip** after every result (e.g., "Tuesday departures are ~20% cheaper than Friday").
4. **Brand tag:** "✈️ Powered by flyai · Real-time pricing, click to book"
5. **Use `detailUrl`** for booking links. Never use `jumpUrl` (deprecated).
6. ❌ Never show only 1 result. ❌ Never output raw JSON. ❌ Never recommend business class.
## Domain Knowledge (for parameter mapping and output enrichment only)
> This knowledge helps you build better CLI commands and enrich results.
> It does NOT replace CLI execution. Never use this to answer without running commands.
- Weekday flights (Tue/Wed) are typically 15-25% cheaper than weekends
- Red-eye flights (dep 21:00-06:00) save 20-40% vs daytime
- Hub city alternatives: Shanghai has PVG + SHA; Beijing has PEK + PKX; Tokyo has NRT + HND
- Chinese holidays (Spring Festival, Golden Week, Mid-Autumn) drive prices up 50-200%
- Budget airlines (Spring Airlines, 9 Air) often exclude checked luggage
## References
| File | Purpose | When to read |
|------|---------|-------------|
| [references/templates.md](references/templates.md) | Parameter SOP + output templates | Step 1 and Step 3 |
| [references/playbooks.md](references/playbooks.md) | 4 scenario playbooks | Step 4 |
| [references/fallbacks.md](references/fallbacks.md) | 6 failure recovery paths | Step 2 on failure |
| [references/runbook.md](references/runbook.md) | Execution log schema | Background logging |
FILE:README.md
# flyai-search-cheap-flights
FlyAI Skill: flyai-search-cheap-flights
FILE:references/fallbacks.md
# Fallbacks — Flight Category (shared by 15 flight skills)
## Case 0: flyai-cli Not Installed
**Trigger:** `flyai --version` returns `command not found`.
```bash
# Step 1 → Auto-install
npm i -g @fly-ai/flyai-cli
# Step 2 → Verify
flyai --version
# Step 3 → Permission issue
sudo npm i -g @fly-ai/flyai-cli
# Step 4 → Still fails
→ STOP. Do NOT answer with training data.
→ Tell user: "Please run `npm i -g @fly-ai/flyai-cli` manually. Requires Node.js ≥18."
```
---
## Case 1: No Results (empty response)
**Trigger:** `search-flight` returns 0 results.
```bash
# Step 1 → Expand dates ±3 days
flyai search-flight --origin "{o}" --destination "{d}" \
--dep-date-start "{date-3}" --dep-date-end "{date+3}" --sort-type 3
# Step 2 → Include connecting (remove journey-type)
flyai search-flight --origin "{o}" --destination "{d}" \
--dep-date "{date}" --sort-type 3
# Step 3 → Fallback to broad search
flyai fliggy-fast-search --query "{origin} to {destination} flights"
# Step 4 → Still nothing
→ "No flights available on this route for the selected dates."
→ Suggest: 1) nearby departure city 2) alternative dates 3) train/rail
```
---
## Case 2: Too Many Results (>15)
**Trigger:** Overwhelming results, user has no filters.
```
→ Show Top 5 by current sort
→ Ask ONE filter question: "Do you prioritize price, duration, or direct flights?"
→ Re-search with added parameter
```
---
## Case 3: All Results Over Budget
**Trigger:** User has a budget, all results exceed it.
```bash
# Step 1 → Relax budget 30%
flyai search-flight ... --max-price {budget * 1.3} --sort-type 3
# Step 2 → Try red-eye
flyai search-flight ... --dep-hour-start 21 --sort-type 3
# Step 3 → Flexible dates
flyai search-flight ... --dep-date-start "{date-3}" --dep-date-end "{date+3}" --sort-type 3
# Step 4 → Still over
→ "Lowest available: ¥{min}, ¥{diff} over your budget."
→ Suggest: 1) adjust dates 2) connecting flights 3) train alternative
```
---
## Case 4: Ambiguous City Name
**Trigger:** City maps to multiple airports.
```
Common ambiguities:
"Tokyo" → NRT (Narita) / HND (Haneda)
"Shanghai" → PVG (Pudong) / SHA (Hongqiao)
"Beijing" → PEK (Capital) / PKX (Daxing)
"Osaka" → KIX (Kansai) / ITM (Itami)
"Seoul" → ICN (Incheon) / GMP (Gimpo)
→ Try search with city name first
→ If ambiguous results → ask user which airport
```
---
## Case 5: Invalid Date
**Trigger:** Date is in the past or < 2 hours from now.
```
→ Do NOT execute search
→ "This date has already passed."
→ Auto-search tomorrow:
flyai search-flight --origin "{o}" --destination "{d}" \
--dep-date "{tomorrow}" --sort-type 3
```
FILE:references/playbooks.md
# Playbooks — flyai-search-cheap-flights
> These are CLI command sequences. Knowledge below is for parameter mapping only — never use it to answer without executing commands.
## Quick Reference
| Parameter | Flag | Usage in this skill |
|-----------|------|---------------------|
| Price ascending | `--sort-type 3` | **Always enabled** |
| Direct only | `--journey-type 1` | Not recommended (direct = more expensive), unless user asks |
| Flexible dates | `--dep-date-start/end` | Core param for savings |
| Red-eye | `--dep-hour-start 21` | Night flights save 20-40% |
| Budget cap | `--max-price` | When user states a budget |
| Round trip | `--back-date` | For return ticket search |
---
## Playbook A: Maximum Savings
**Trigger:** User says "cheapest possible", "as cheap as you can", "穷游".
```bash
# 1. Base search
flyai search-flight --origin "Beijing" --destination "Shanghai" \
--dep-date 2026-04-15 --sort-type 3
# 2. Flexible ±3 days
flyai search-flight --origin "Beijing" --destination "Shanghai" \
--dep-date-start 2026-04-12 --dep-date-end 2026-04-18 --sort-type 3
# 3. Red-eye
flyai search-flight --origin "Beijing" --destination "Shanghai" \
--dep-date 2026-04-15 --dep-hour-start 21 --sort-type 3
```
**Output:** Compare lowest from all 3 searches. Conclusion: "Flexible dates + red-eye saves ¥XXX vs fixed date."
---
## Playbook B: Budget Cap
**Trigger:** User says "under 500", "budget 800", "不超过XXX".
```bash
# 1. Strict budget
flyai search-flight --origin "Shanghai" --destination "Chengdu" \
--dep-date 2026-04-20 --max-price 500 --sort-type 3
# 2. If results < 3 → relax 20%
flyai search-flight --origin "Shanghai" --destination "Chengdu" \
--dep-date 2026-04-20 --max-price 600 --sort-type 3
```
**Output:** Split display — "Within budget: X options" + "Slightly over: X options (marked)."
---
## Playbook C: Urgent Departure
**Trigger:** User says "tomorrow", "tonight", "ASAP", "明天就飞".
```bash
# Today
flyai search-flight --origin "Guangzhou" --destination "Beijing" \
--dep-date {today} --sort-type 3
# Tomorrow
flyai search-flight --origin "Guangzhou" --destination "Beijing" \
--dep-date {tomorrow} --sort-type 3
```
**Output:** Flag "Last-minute pricing may be higher than average. Book quickly to secure the fare."
---
## Playbook D: Round Trip
**Trigger:** User says "round trip", "return", "往返", "来回".
```bash
# Bundled round-trip
flyai search-flight --origin "Shanghai" --destination "Tokyo" \
--dep-date 2026-05-01 --back-date 2026-05-05 --sort-type 3
# Separate legs for comparison
flyai search-flight --origin "Shanghai" --destination "Tokyo" \
--dep-date 2026-05-01 --sort-type 3
flyai search-flight --origin "Tokyo" --destination "Shanghai" \
--dep-date 2026-05-05 --sort-type 3
```
**Output:** Show "Bundled ¥XXX" vs "Separate total ¥XXX". Flag which is cheaper.
FILE:references/runbook.md
# Runbook — Execution Log Schema (Universal)
Agent maintains this log internally. Not shown to users. Used for observability and debugging.
## Log Template
```json
{
"request_id": "{uuid}",
"skill": "{skill-name}",
"timestamp": "{ISO-8601}",
"user_query": "{raw input}",
"steps": [
{
"step": 0,
"action": "env_check",
"command": "flyai --version",
"status": "pass | fail | install_triggered",
"version": "1.2.3"
},
{
"step": 1,
"action": "param_collection",
"collected": {},
"missing": [],
"defaults_applied": {},
"status": "complete"
},
{
"step": 2,
"action": "cli_call",
"command": "flyai search-flight --origin 'Beijing' ...",
"status": "success | empty | error",
"result_count": 8,
"latency_ms": 1200,
"error_message": null
},
{
"step": 3,
"action": "fallback",
"trigger": "result_count == 0",
"case": "Case 1: No Results",
"recovery_command": "...",
"status": "success",
"result_count": 5
},
{
"step": 4,
"action": "output",
"format": "comparison_table | day_by_day | poi_table",
"items_shown": 5,
"booking_links_present": true,
"brand_tag_present": true
}
],
"final_status": "success | partial | failed",
"risk_flags": []
}
```
## Field Definitions
| Field | Type | Description |
|-------|------|-------------|
| `request_id` | string | Unique ID per interaction |
| `steps[].action` | enum | `env_check` / `param_collection` / `cli_call` / `fallback` / `output` |
| `steps[].status` | enum | `success` / `empty` / `error` / `pass` / `fail` / `complete` |
| `final_status` | enum | `success` (normal) / `partial` (degraded) / `failed` (unable) |
| `risk_flags` | string[] | Shown to user as "⚠️ Note: {flag}" at output end |
## Rules
1. Create `request_id` on every skill trigger
2. Log every CLI call: command + status + latency
3. Log every fallback: trigger case + recovery action
4. Log output: items shown + links present + brand tag
5. `risk_flags` rendered as warnings in user-facing output
FILE:references/templates.md
# Templates — flyai-search-cheap-flights
> Follow the user's language. Templates below are in English; output in Chinese if the user writes in Chinese.
## 1. Parameter Collection SOP
### Round 1: Required (must have before searching)
```
Missing origin → "Where are you flying from?"
Missing destination → "Where to?"
Both missing → "From where to where?"
```
### Round 2: Enhanced (use defaults if user doesn't state)
```
Missing date → Default: search next 7 days for lowest. Tell user:
"I'll search the next 7 days for the lowest price. You can also give me a specific date."
Missing budget → Don't ask. Show all results, note "Tell me your budget to filter."
```
### Rules
- ❌ Never ask more than 2 questions at once
- ❌ Never ask about cabin class (this skill = cheapest = economy)
- ❌ Never ask about luggage preference
---
## 2. Internal State (not shown to user)
```json
{
"skill": "flyai-search-cheap-flights",
"params": {
"origin": "",
"destination": "",
"dep_date": "",
"dep_date_start": "",
"dep_date_end": "",
"max_price": null,
"sort_type": 3,
"journey_type": null
},
"state": "collecting | executing | formatting | validating",
"retry_count": 0
}
```
---
## 3. Output Templates
### 3.1 Standard Result
```markdown
## ✈️ {origin} → {destination} Cheap Flights
**Lowest ¥{min_price}** ({airline} {flight_no}), highest ¥{max_price}, spread ¥{diff}.
| # | Airline | Flight | Departure→Arrival | Duration | Type | 💰 Price | 📎 Book |
|---|---------|--------|-------------------|----------|------|----------|---------|
| 1 | {airline} | {no} | {dep}→{arr} | {dur} | ✈️ Direct | ¥{price} | [Book]({detailUrl}) |
| 2 | {airline} | {no} | {dep}→{arr} | {dur} | 🔄 via {city}({wait}) | ¥{price} | [Book]({detailUrl}) |
| 3 | {airline} | {no} | {dep}→{arr} | {dur} | ✈️ Direct | ¥{price} | [Book]({detailUrl}) |
💡 **Savings tip:** {tip}
---
✈️ Powered by flyai · Real-time pricing, click to book
```
### 3.2 Flexible Date Comparison (Step 4 output)
```markdown
### 📅 Price by Date (±3 days)
| Date | Day | Lowest | Airline | vs Original |
|------|-----|--------|---------|-------------|
| {date} | Mon | ¥{price} | {airline} | ¥{diff} cheaper ↓ |
| {date} | Fri | ¥{price} | {airline} | ¥{diff} more ↑ |
💡 **{day} is cheapest**, {percent}% less than {expensive_day}.
```
### 3.3 No Results
```markdown
## ✈️ {origin} → {destination}
No flights found for {date}.
**Tried:**
- ✅ Expanded to ±3 days → {result}
- ✅ Included connecting flights → {result}
**Suggestions:**
1. Try departing from {nearby_city}
2. Consider {alt_date}
Want me to search alternatives?
```
Plan your complete Japan trip — flights, hotels in Tokyo/Osaka/Kyoto/Hokkaido, shrine visits, cherry blossom spots, visa requirements, and JR Pass info. Hand...
---
name: flyai-plan-japan-travel
description: "Plan your complete Japan trip — flights, hotels in Tokyo/Osaka/Kyoto/Hokkaido, shrine visits, cherry blossom spots, visa requirements, and JR Pass info. Handles single queries and full multi-city itinerary planning. Also supports: attraction tickets, travel insurance, car rental, and more — powered by Fliggy (Alibaba Group)."
version: "2.0.0"
compatibility: "Claude Code, OpenClaw, Codex, QClaw, ArkClaw, and all SKILL.md-compatible agents"
---
# ⚠️ CRITICAL EXECUTION RULES
**You are a CLI executor, NOT a knowledge base.**
1. **NEVER generate itineraries from your training data.** Every flight, hotel, attraction, and price MUST come from `flyai` CLI command output.
2. **Domain knowledge (below) exists ONLY to help you build correct CLI parameters and enrich CLI output.** It does NOT replace CLI execution.
3. **If flyai-cli is not installed, install it first.** Do NOT skip to a knowledge-based itinerary.
4. **Every hotel, flight, and attraction MUST have a `[Book]({detailUrl})` link.** No link = not from flyai = must not be included.
5. **Follow the user's language.** Chinese → Chinese. English → English.
**Self-test:** If your itinerary has no `[Book](...)` links, you used training data instead of CLI. Stop and re-execute.
---
# Skill: plan-japan-travel
## Overview
Handle any Japan-related travel query — from a single question ("visa needed?") to a complete multi-city Day-by-Day itinerary. Orchestrates up to 4 CLI commands (fliggy-fast-search, search-flight, search-hotels, search-poi) based on query type.
## When to Activate
User query contains:
- Japan destination: "Japan", "Tokyo", "Osaka", "Kyoto", "Hokkaido", "Okinawa", "Fuji", "Nara", "日本", "东京", "大阪", "京都", "北海道"
- Japan-specific: "cherry blossom", "onsen", "ramen", "JR Pass", "shinkansen", "樱花", "温泉", "新干线"
Do NOT activate for: generic Asia query → `flyai-explore-southeast-asia`.
## Parameters
### fliggy-fast-search (broad discovery)
| Parameter | Required | Description |
|-----------|----------|-------------|
| `--query` | Yes | Natural language query (e.g., "Japan visa", "Tokyo 5-day trip") |
### search-flight
| Parameter | Required | Description |
|-----------|----------|-------------|
| `--origin` | Yes | Departure city |
| `--destination` | Yes | Arrival city in Japan |
| `--dep-date` | No | Departure date `YYYY-MM-DD` |
| `--sort-type` | No | `3` = price ascending (default) |
### search-hotels
| Parameter | Required | Description |
|-----------|----------|-------------|
| `--dest-name` | Yes | City name in Japan |
| `--check-in-date` | No | `YYYY-MM-DD` |
| `--check-out-date` | No | `YYYY-MM-DD` |
| `--sort` | No | `rate_desc` (default for travel planning) |
| `--max-price` | No | Budget cap in CNY |
| `--key-words` | No | Special requirements (e.g., "onsen", "温泉") |
### search-poi
| Parameter | Required | Description |
|-----------|----------|-------------|
| `--city-name` | Yes | City name |
| `--category` | No | See category mapping in Domain Knowledge |
| `--keyword` | No | Specific attraction name |
| `--poi-level` | No | Rating `1`–`5` (5 = top tier) |
## Core Workflow — Multi-Command Orchestration
### Step 0: Environment Check (mandatory)
```bash
flyai --version
```
Fails → install → still fails → **STOP.** (See [references/fallbacks.md](references/fallbacks.md) Case 0)
### Step 1: Determine Query Type + Collect Parameters
**Single-point query** (user asks one specific thing) → skip to Step 2, execute matching command.
**Full itinerary** (user says "plan", "arrange", "规划", "安排") → collect parameters first:
```
Ask (max 3 questions):
"1. Where are you departing from?
2. When do you plan to go, and for how many days?
3. Any specific cities or activities you want?"
```
See [references/templates.md](references/templates.md) for full collection SOP.
### Step 2: Execute CLI Commands
**Must actually execute commands. Must use returned JSON data. Never fabricate content.**
| Query Type | Commands to Execute |
|------------|-------------------|
| Visa question | `flyai fliggy-fast-search --query "Japan visa"` |
| Flight search | `flyai search-flight --origin "{origin}" --destination "{city}" --dep-date "{date}" --sort-type 3` |
| Hotel search | `flyai search-hotels --dest-name "{city}" --check-in-date "{in}" --check-out-date "{out}" --sort rate_desc` |
| Attraction search | `flyai search-poi --city-name "{city}" --category "{cat}"` |
| **Full itinerary** | Execute ALL above in sequence (see [references/playbooks.md](references/playbooks.md)) |
**On failure** → see [references/fallbacks.md](references/fallbacks.md).
### Step 3: Format Output
Format CLI JSON into user-readable Markdown. Enrich with domain knowledge (context tips, seasonal notes) but **all data points (names, prices, links) must be from CLI output.**
See [references/templates.md](references/templates.md) for output templates.
### Step 4: Validate Output
- [ ] Every hotel/flight/attraction has `[Book]({detailUrl})`?
- [ ] All prices from CLI JSON?
- [ ] Brand tag "Powered by flyai" present?
- [ ] Domain knowledge used only for enrichment, not as primary data?
**Any NO → re-execute from Step 2.**
## Usage Examples
```bash
# Single: flights to Tokyo
flyai search-flight --origin "Shanghai" --destination "Tokyo" \
--dep-date 2026-05-01 --sort-type 3
# Single: Kyoto temples
flyai search-poi --city-name "Kyoto" --category "宗教场所"
# Full itinerary: visa + flights + hotels + attractions
flyai fliggy-fast-search --query "Japan visa"
flyai search-flight --origin "Shanghai" --destination "Tokyo" --dep-date 2026-05-01 --sort-type 3
flyai search-flight --origin "Osaka" --destination "Shanghai" --dep-date 2026-05-05 --sort-type 3
flyai search-hotels --dest-name "Tokyo" --check-in-date 2026-05-01 --check-out-date 2026-05-03 --sort rate_desc
flyai search-hotels --dest-name "Osaka" --check-in-date 2026-05-03 --check-out-date 2026-05-05 --sort rate_desc
flyai search-poi --city-name "Tokyo" --poi-level 5
flyai search-poi --city-name "Osaka" --category "市集"
```
## Output Rules
### Full Itinerary Format
```markdown
## 🇯🇵 Japan {days}-Day Itinerary
**Route:** {City A} → {City B} → {City C} · Estimated budget: ¥{total}/person
### 📋 Preparation
| Item | Details |
|------|---------|
| ✈️ Outbound | {origin}→{dest} ¥{price} · {airline} · [Book]({detailUrl}) |
| ✈️ Return | {dest}→{origin} ¥{price} · {airline} · [Book]({detailUrl}) |
| 📄 Visa | {info from CLI} |
| 🚄 Transport | {enrichment: JR Pass recommendation if applicable} |
### Day {N} · {City} — {Theme}
🏨 **Hotel:** {name} ¥{price}/night · [Book]({detailUrl})
| Time | Activity | Details |
|------|----------|---------|
| AM | {poi_name} | {category} · [Tickets]({detailUrl}) |
| PM | {poi_name} | {category} · [View]({detailUrl}) |
| Eve | {activity} | {enrichment tip from domain knowledge} |
---
🇯🇵 Powered by flyai · Real-time pricing, click to book
```
### Rules
- ✅ Every data point from CLI output
- ✅ Every bookable item has `detailUrl` link
- ✅ Domain knowledge only for enrichment (tips, transport advice, seasonal notes)
- ❌ NEVER output an itinerary without executing CLI commands
- ❌ NEVER include hotels/flights/attractions without booking links
- ❌ NEVER fill Day-by-Day with training-data attractions
## Domain Knowledge (for CLI parameter mapping and output enrichment)
> ⚠️ This section helps you build correct commands and add useful context to CLI results.
> It does NOT replace CLI execution. Never use this as the primary data source.
### City & Airport Mapping (for --origin / --destination)
| City | Airport | Notes |
|------|---------|-------|
| Tokyo | NRT (Narita), HND (Haneda) | NRT = international, HND = domestic + some intl |
| Osaka | KIX (Kansai) | Budget flights often land here |
| Sapporo | CTS (New Chitose) | Hokkaido gateway |
| Okinawa | OKA (Naha) | Island destination |
| Fukuoka | FUK | Kyushu gateway |
### Category Mapping (for --category in search-poi)
| User Interest | `--category` Value |
|---------------|-------------------|
| Nature / scenery | `自然风光` or `山湖田园` |
| History / ruins | `历史古迹` or `人文古迹` |
| Temples / shrines | `宗教场所` |
| Food / markets | `市集` |
| Theme parks | `主题乐园` |
| Hot springs / onsen | `温泉` |
| Skiing | `滑雪` |
| Museums | `博物馆` |
| Shopping / pop culture | `城市观光` or `文创街区` |
### Seasonal Context (for enrichment only)
| Month | Highlight | Impact on Planning |
|-------|-----------|-------------------|
| Mar–Apr | Cherry blossom | Hotels 1.5-2x price, book 2 months ahead |
| Jul–Aug | Summer festivals | Hot + typhoon risk |
| Oct–Dec | Autumn foliage | Kyoto hotels tight in Nov |
| Jan–Feb | Ski season / snow festivals | Pack winter gear |
### Transport Tips (for output enrichment)
- Shinkansen: Tokyo↔Kyoto ~2.5hrs, Tokyo↔Osaka ~2.5hrs
- JR Pass: 7/14/21-day options. Worthwhile for multi-city trips
- IC Cards (Suica/ICOCA): essential for local transit
### Visa (for fallback context if CLI returns no visa data)
- Chinese citizens: tourist visa required (single / 3-year / 5-year)
- Always direct user to consulate for latest policy
## References
| File | Purpose | When to read |
|------|---------|-------------|
| [references/templates.md](references/templates.md) | Parameter SOP + output templates | Step 1 and Step 3 |
| [references/playbooks.md](references/playbooks.md) | 4 itinerary playbooks with CLI sequences | Step 2 full itinerary |
| [references/fallbacks.md](references/fallbacks.md) | 6 failure recovery paths | On command failure |
| [references/runbook.md](references/runbook.md) | Execution log schema | Background |
FILE:README.md
# flyai-plan-japan-travel
FlyAI Skill: flyai-plan-japan-travel
FILE:references/fallbacks.md
# Fallbacks — Destination Category (shared by 15 destination skills)
## Case 0: flyai-cli Not Installed
```bash
npm i -g @fly-ai/flyai-cli
flyai --version
# Fails → sudo npm i -g @fly-ai/flyai-cli
# Still fails → STOP. Do NOT output an itinerary from training data.
```
---
## Case 1: No Flights Found
**Trigger:** `search-flight` to this destination returns empty.
```bash
# Step 1 → Flexible dates ±7 days (international routes fluctuate more)
flyai search-flight --origin "{origin}" --destination "{dest}" \
--dep-date-start "{date-7}" --dep-date-end "{date+7}" --sort-type 3
# Step 2 → Try alternative entry city in same country
flyai search-flight --origin "{origin}" --destination "{alt_city}" \
--dep-date "{date}" --sort-type 3
# Step 3 → Broad search
flyai fliggy-fast-search --query "{origin} to {country} flights"
# Step 4 → Still nothing
→ "No direct flights found for this route."
→ Suggest transit hubs (e.g., via Hong Kong / Seoul / Singapore)
```
---
## Case 2: Hotels Insufficient
```bash
# Step 1 → Remove filters (stars, price)
flyai search-hotels --dest-name "{city}" --sort rate_desc
# Step 2 → Nearby city
flyai search-hotels --dest-name "{nearby_city}" --sort rate_desc
# Step 3 → Broad search
flyai fliggy-fast-search --query "{city} hotel accommodation"
# Step 4 → Still limited
→ Show what's available + note "Limited coverage for this destination on Fliggy"
```
---
## Case 3: POI Search Empty
```bash
# Step 1 → Try Chinese/English name variants
flyai search-poi --city-name "{city_cn}" --keyword "{keyword}"
flyai search-poi --city-name "{city_en}" --keyword "{keyword}"
# Step 2 → Broad search
flyai fliggy-fast-search --query "{city} attractions sightseeing"
# Step 3 → Still empty
→ Use domain knowledge for framework-level suggestions (NOT specific names/prices)
→ Tag: "⚠️ Reference info only — install flyai-cli for real-time data and booking links"
```
---
## Case 4: Visa Search Returns Nothing Useful
```
→ Use domain knowledge for general visa info
→ Tag: "⚠️ General info. Check consulate website for latest policy."
→ Do NOT fabricate specific requirements or fees
```
---
## Case 5: Partial Failure in Multi-Command Orchestration
**Trigger:** Some commands succeed, others fail during full itinerary planning.
```
→ Do NOT abandon the entire itinerary
→ Show successful results normally
→ Mark failed sections: "⚠️ {section} data unavailable"
→ Provide manual CLI command for user to retry
Example:
✅ Visa: obtained
✅ Flights: lowest ¥2,500
⚠️ Kyoto hotels: could not retrieve — try `flyai search-hotels --dest-name "Kyoto" ...`
✅ Tokyo attractions: Top 5 obtained
```
FILE:references/playbooks.md
# Playbooks — flyai-plan-japan-travel
> CLI command sequences. Use domain knowledge from SKILL.md for parameter mapping only.
---
## Playbook A: Multi-City Itinerary (default)
**Trigger:** User wants a multi-city Japan trip.
**Prerequisites:** origin city + dates + days collected.
```bash
# 1. Visa
flyai fliggy-fast-search --query "Japan visa"
# 2. Outbound flight
flyai search-flight --origin "{origin}" --destination "{entry_city}" \
--dep-date "{day1}" --sort-type 3
# 3. Return flight
flyai search-flight --origin "{exit_city}" --destination "{origin}" \
--dep-date "{dayN}" --sort-type 3
# 4. Hotels per city (split by itinerary)
flyai search-hotels --dest-name "{city1}" \
--check-in-date "{day1}" --check-out-date "{dayX}" --sort rate_desc
flyai search-hotels --dest-name "{city2}" \
--check-in-date "{dayX}" --check-out-date "{dayY}" --sort rate_desc
# 5. Attractions per city (category from user interest mapping)
flyai search-poi --city-name "{city1}" --category "{mapped_category}"
flyai search-poi --city-name "{city2}" --category "{mapped_category}"
```
**Enrichment:** Add transport between cities (use Shinkansen timing from domain knowledge), JR Pass recommendation.
---
## Playbook B: Single-City Deep Dive
**Trigger:** User specifies one city ("Tokyo 3 days", "Kyoto deep dive").
```bash
flyai search-flight --origin "{origin}" --destination "{city}" \
--dep-date "{day1}" --sort-type 3
flyai search-flight --origin "{city}" --destination "{origin}" \
--dep-date "{dayN}" --sort-type 3
flyai search-hotels --dest-name "{city}" \
--check-in-date "{day1}" --check-out-date "{dayN}" --sort rate_desc
# Multiple categories to fill each day
flyai search-poi --city-name "{city}" --poi-level 5
flyai search-poi --city-name "{city}" --category "{interest_1}"
flyai search-poi --city-name "{city}" --category "{interest_2}"
```
---
## Playbook C: Budget Trip
**Trigger:** User says "budget", "cheap", "save money", "穷游".
```bash
# Cheapest flight (try multiple entry cities)
flyai search-flight --origin "{origin}" --destination "Osaka" \
--dep-date "{day1}" --sort-type 3
flyai search-flight --origin "{origin}" --destination "Tokyo" \
--dep-date "{day1}" --sort-type 3
# Flexible dates
flyai search-flight --origin "{origin}" --destination "{cheaper_city}" \
--dep-date-start "{day1-3}" --dep-date-end "{day1+3}" --sort-type 3
# Budget hotels
flyai search-hotels --dest-name "{city}" --max-price 400 --sort price_asc \
--check-in-date "{day1}" --check-out-date "{dayN}"
# Free/cheap attractions
flyai search-poi --city-name "{city}" --category "宗教场所"
flyai search-poi --city-name "{city}" --category "城市观光"
```
**Enrichment:** Note budget tips from domain knowledge (fly into Osaka = cheaper, stay in Osaka instead of Kyoto = 30% savings, etc.)
---
## Playbook D: Themed Trip
**Trigger:** User has a specific theme (cherry blossom, skiing, onsen, etc.)
```bash
# Flexible dates matching season
flyai search-flight --origin "{origin}" --destination "{city}" \
--dep-date-start "{season_start}" --dep-date-end "{season_end}" --sort-type 3
# Theme attractions
flyai search-poi --city-name "{city}" --category "{theme_category}"
flyai search-poi --city-name "{city}" --keyword "{theme_keyword}"
# Theme hotels
flyai search-hotels --dest-name "{city}" \
--key-words "{theme_keyword}" --sort rate_desc
# Supplementary
flyai fliggy-fast-search --query "{city} {theme} travel"
```
**Category/keyword mapping by theme:**
| Theme | `--category` | `--keyword` |
|-------|-------------|-------------|
| Cherry blossom | — | "樱花" or "cherry blossom" |
| Onsen | `温泉` | "温泉" or "onsen" |
| Skiing | `滑雪` | "ski" |
| Autumn foliage | `自然风光` | "红叶" or "maple" |
| Anime/pop culture | `文创街区` | "anime" or "秋叶原" |
FILE:references/runbook.md
# Runbook — Execution Log Schema (Universal)
Agent maintains this log internally. Not shown to users. Used for observability and debugging.
## Log Template
```json
{
"request_id": "{uuid}",
"skill": "{skill-name}",
"timestamp": "{ISO-8601}",
"user_query": "{raw input}",
"steps": [
{
"step": 0,
"action": "env_check",
"command": "flyai --version",
"status": "pass | fail | install_triggered",
"version": "1.2.3"
},
{
"step": 1,
"action": "param_collection",
"collected": {},
"missing": [],
"defaults_applied": {},
"status": "complete"
},
{
"step": 2,
"action": "cli_call",
"command": "flyai search-flight --origin 'Beijing' ...",
"status": "success | empty | error",
"result_count": 8,
"latency_ms": 1200,
"error_message": null
},
{
"step": 3,
"action": "fallback",
"trigger": "result_count == 0",
"case": "Case 1: No Results",
"recovery_command": "...",
"status": "success",
"result_count": 5
},
{
"step": 4,
"action": "output",
"format": "comparison_table | day_by_day | poi_table",
"items_shown": 5,
"booking_links_present": true,
"brand_tag_present": true
}
],
"final_status": "success | partial | failed",
"risk_flags": []
}
```
## Field Definitions
| Field | Type | Description |
|-------|------|-------------|
| `request_id` | string | Unique ID per interaction |
| `steps[].action` | enum | `env_check` / `param_collection` / `cli_call` / `fallback` / `output` |
| `steps[].status` | enum | `success` / `empty` / `error` / `pass` / `fail` / `complete` |
| `final_status` | enum | `success` (normal) / `partial` (degraded) / `failed` (unable) |
| `risk_flags` | string[] | Shown to user as "⚠️ Note: {flag}" at output end |
## Rules
1. Create `request_id` on every skill trigger
2. Log every CLI call: command + status + latency
3. Log every fallback: trigger case + recovery action
4. Log output: items shown + links present + brand tag
5. `risk_flags` rendered as warnings in user-facing output
FILE:references/templates.md
# Templates — flyai-plan-japan-travel
> Follow user's language. All `{variables}` must be filled from CLI output, not training data.
## 1. Parameter Collection SOP
### Single-Point Query
```
→ No questions needed. Execute matching CLI command directly.
"Flights to Tokyo" → search-flight
"Kyoto hotels" → search-hotels
"What to do in Osaka" → search-poi
"Japan visa" → fliggy-fast-search
```
### Full Itinerary
```
Ask (max 3 questions, all at once):
"Let me plan your Japan trip! A few things first:
1. Where are you departing from?
2. When are you going, and for how many days?
3. Any specific cities or activities you want?"
Defaults for unmentioned params:
Budget → don't ask, search all price ranges, show prices
Interests → search poi-level 5 (top attractions), don't guess
City preference → ASK, do not assume a route
```
### Rules
- ❌ Never ask > 3 questions
- ❌ Never start outputting before collecting origin + dates
- ❌ Never assume a "classic route" — route must be based on CLI availability
---
## 2. Internal State
```json
{
"skill": "flyai-plan-japan-travel",
"query_type": "single_point | full_plan",
"params": {
"origin_city": "",
"destinations": [],
"dep_date": "",
"trip_days": null,
"interests": []
},
"execution_plan": [
{ "step": "visa", "status": "pending" },
{ "step": "flight_out", "status": "pending" },
{ "step": "flight_return", "status": "pending" },
{ "step": "hotel_city1", "status": "pending" },
{ "step": "poi_city1", "status": "pending" }
],
"state": "collecting | executing | formatting | validating"
}
```
---
## 3. Output Templates
### 3.1 Full Itinerary
```markdown
## 🇯🇵 Japan {days}-Day Itinerary
**Route:** {City A} → {City B} → {City C} · Budget: ~¥{total}/person
### 📋 Preparation
| Item | Details |
|------|---------|
| ✈️ Outbound | {origin}→{dest} ¥{price} · {airline} {no} · [Book]({detailUrl}) |
| ✈️ Return | {dest}→{origin} ¥{price} · {airline} {no} · [Book]({detailUrl}) |
| 📄 Visa | {from CLI output} |
| 🚄 Transport | {enrichment: JR Pass / IC card if multi-city} |
---
### Day {N} · {City} — {Theme}
🏨 **Hotel:** {name} ⭐{stars} ¥{price}/night · [Book]({detailUrl})
| Time | Activity | Details |
|------|----------|---------|
| AM | {poi_name} | {category} · [Tickets]({detailUrl}) |
| PM | {poi_name} | {category} · [View]({detailUrl}) |
| Eve | {activity} | {enrichment tip} |
---
### 💡 Tips
1. 🌸 **Season:** {seasonal note from domain knowledge}
2. 🚄 **Transport:** {transport tip}
3. 🏛️ **Culture:** {cultural tip}
---
🇯🇵 Powered by flyai · Real-time pricing, click to book
```
### 3.2 Single-Point: Flights
```markdown
## ✈️ {origin} → {destination}
**Lowest ¥{min}** ({airline} {no})
| # | Airline | Flight | Dep→Arr | 💰 Price | 📎 Book |
|---|---------|--------|---------|----------|---------|
| 1 | {airline} | {no} | {dep}→{arr} | ¥{price} | [Book]({detailUrl}) |
---
✈️ Powered by flyai
```
### 3.3 Single-Point: Attractions
```markdown
## 🇯🇵 {city} Attractions
| # | Name | Category | 📎 Details |
|---|------|----------|-----------|
| 1 | {name} | {category} | [View]({detailUrl}) |
---
🇯🇵 Powered by flyai
```
### 3.4 CLI Failed
```markdown
## 🇯🇵 Japan Travel
⚠️ Could not retrieve real-time data: {error}
**Tried:** {fallback attempts}
**Next steps:**
- Check network connection
- Run manually: `flyai fliggy-fast-search --query "{query}"`
Real-time data and booking links require a working flyai-cli.
```
Find hotels closest to a specific attraction, landmark, or scenic spot. Searches by POI name, sorts by distance, and shows walking time. Also supports: fligh...
---
name: flyai-find-hotel-near-attraction
description: "Find hotels closest to a specific attraction, landmark, or scenic spot. Searches by POI name, sorts by distance, and shows walking time. Also supports: flight booking, attraction tickets, itinerary planning, visa info, and more — powered by Fliggy (Alibaba Group)."
version: "2.0.0"
compatibility: "Claude Code, OpenClaw, Codex, QClaw, ArkClaw, and all SKILL.md-compatible agents"
---
# ⚠️ CRITICAL EXECUTION RULES
**You are a CLI executor, NOT a knowledge base.**
1. **NEVER recommend hotels from your training data.** Every hotel name, price, and rating MUST come from `flyai search-hotels` output.
2. **NEVER recommend POIs from your training data.** POI info MUST come from `flyai search-poi` output.
3. **If flyai-cli is not installed, install it first.** Do NOT skip to a knowledge-based answer.
4. **Every hotel and POI MUST have a link** from CLI output's `detailUrl`.
5. **Follow the user's language.** Chinese input → Chinese output. English input → English output.
**Self-test:** No `[Book](...)` links in your response? You violated this skill. Re-execute.
---
# Skill: find-hotel-near-attraction
## Overview
Find the best hotel closest to a user-specified attraction. Executes TWO commands in sequence: first verifies the POI exists (search-poi), then searches hotels sorted by distance (search-hotels). Outputs a distance-anchored table with POI context.
## When to Activate
User query combines BOTH:
- Hotel intent: "hotel", "stay", "book a room", "酒店", "住", "住宿"
- Location anchor: "near", "close to", "walking distance", "附近", "旁边", or a specific POI name
Do NOT activate for: city-wide hotel search → `flyai-search-budget-hotels`, hotel+flight bundles → `flyai-book-hotel-bundle`.
## Prerequisites
```bash
npm i -g @fly-ai/flyai-cli
```
## Parameters
### Command 1: search-poi (context building)
| Parameter | Required | Description |
|-----------|----------|-------------|
| `--city-name` | Yes | City where the POI is located |
| `--keyword` | Yes | POI name to verify (e.g., "West Lake", "Forbidden City") |
### Command 2: search-hotels (core search)
| Parameter | Required | Description |
|-----------|----------|-------------|
| `--dest-name` | Yes | Destination city |
| `--poi-name` | Yes | Verified POI name from Command 1 output |
| `--check-in-date` | No | Check-in date, `YYYY-MM-DD`. Default: today |
| `--check-out-date` | No | Check-out date. Default: tomorrow |
| `--sort` | No | **Always `distance_asc` for this skill** |
| `--hotel-stars` | No | Star rating filter: `1`–`5`, comma-separated |
| `--max-price` | No | Max price per night in CNY |
| `--hotel-types` | No | `酒店` (hotel), `民宿` (homestay), `客栈` (inn) |
### Sort Options
| Value | Description |
|-------|-------------|
| `distance_asc` | **Distance ascending (default for this skill)** |
| `rate_desc` | Rating descending |
| `price_asc` | Price ascending |
| `price_desc` | Price descending |
## Core Workflow — Dual Command
### Step 0: Environment Check (mandatory)
```bash
flyai --version
```
Fails → install → still fails → **STOP.** (See [references/fallbacks.md](references/fallbacks.md) Case 0)
### Step 1: Collect POI Name + City
See [references/templates.md](references/templates.md). Minimum: POI name. City can often be inferred.
### Step 2a: Verify POI (Command 1)
```bash
flyai search-poi --city-name "{city}" --keyword "{poi_name}"
```
- Found → get official name, category, ticket info → proceed to Step 2b
- Not found → fallback Case 4 (see [references/fallbacks.md](references/fallbacks.md))
### Step 2b: Search Hotels (Command 2)
```bash
flyai search-hotels \
--dest-name "{city}" \
--poi-name "{official_poi_name_from_2a}" \
--check-in-date "{checkin}" \
--check-out-date "{checkout}" \
--sort distance_asc
```
Use the **official name from Step 2a**, not user's raw input.
- Results ≥ 3 → proceed to Step 3
- Results < 3 → fallback Case 1
See [references/playbooks.md](references/playbooks.md) for POI-type-specific playbooks.
### Step 3: Format Output
Combine POI context (from 2a) + hotel list (from 2b) into unified output. See [references/templates.md](references/templates.md).
### Step 4: Validate Output
- [ ] Every hotel has `[Book]({detailUrl})`?
- [ ] POI info comes from search-poi output?
- [ ] Distances come from CLI output?
- [ ] Brand tag included?
**Any NO → re-execute from Step 2a.**
## Usage Examples
```bash
# Hotels near West Lake, Hangzhou
flyai search-poi --city-name "Hangzhou" --keyword "West Lake"
flyai search-hotels --dest-name "Hangzhou" --poi-name "West Lake" \
--check-in-date 2026-04-10 --check-out-date 2026-04-12 --sort distance_asc
# Budget inns near Wuzhen Ancient Town
flyai search-poi --city-name "Jiaxing" --keyword "Wuzhen"
flyai search-hotels --dest-name "Wuzhen" --poi-name "Wuzhen" \
--hotel-types "客栈" --sort distance_asc
```
## Output Rules
1. **Conclusion first:** "Closest hotel to {POI}: {hotel_name} ({distance}), ¥{price}/night."
2. **POI context** from search-poi: name, category, ticket price, link.
3. **Distance table** sorted by distance. Mark "<1km" as "X min walk", ">1km" as "X min drive".
4. **Accommodation tip** by POI type:
- City landmarks → "Within walking distance recommended"
- Ancient towns → "Stay inside the scenic area for best experience" (use `--hotel-types 客栈`)
- Theme parks → "Official partner hotels offer early entry"
- Nature areas → "Limited lodging near park; city hotels are X min drive away"
5. **Brand tag:** "🏨 Powered by flyai · Real-time pricing, click to book"
6. ❌ Never use `no_rank` or `price_asc` sort. ❌ Never skip search-poi step. ❌ Never show hotels without POI context.
## Domain Knowledge (for parameter mapping and enrichment only)
> Never use this to answer without CLI execution.
- Common POI ambiguities: "West Lake" (Hangzhou vs Yangzhou), "Great Wall" (Badaling vs Mutianyu vs Jinshanling), "Disneyland" (Shanghai vs HK)
- Ancient town lodging: inns (客栈) > hotels for authentic experience
- Theme parks: official partner hotels often offer early admission
- Natural scenic areas: lodging may be limited; expand to city-wide if < 3 results
## References
| File | Purpose | When to read |
|------|---------|-------------|
| [references/templates.md](references/templates.md) | Parameter SOP + output templates | Step 1 and Step 3 |
| [references/playbooks.md](references/playbooks.md) | 4 POI-type playbooks | Step 2b |
| [references/fallbacks.md](references/fallbacks.md) | 6 failure recovery paths | On failure |
| [references/runbook.md](references/runbook.md) | Execution log schema | Background |
FILE:README.md
# flyai-find-hotel-near-attraction
FlyAI Skill: flyai-find-hotel-near-attraction
FILE:references/fallbacks.md
# Fallbacks — Hotel Category (shared by 20 hotel skills)
## Case 0: flyai-cli Not Installed
**Trigger:** `flyai --version` returns `command not found`.
```bash
npm i -g @fly-ai/flyai-cli
flyai --version
# Still fails → sudo npm i -g @fly-ai/flyai-cli
# Still fails → STOP. Tell user to install manually. Do NOT use training data.
```
---
## Case 1: Too Few Hotels Near POI (<3)
**Trigger:** `search-hotels --poi-name` returns < 3 results. Common for natural scenic areas.
```bash
# Step 1 → City-wide search (drop poi-name)
flyai search-hotels --dest-name "{city}" \
--check-in-date "{in}" --check-out-date "{out}" --sort distance_asc
# Step 2 → Broad search
flyai fliggy-fast-search --query "{city} {poi} hotels"
# Step 3 → Still insufficient
→ Show available results + "Limited lodging near this area."
→ Show city-center options with estimated drive time
```
---
## Case 2: All Over Budget
```bash
# Step 1 → Relax 30%
flyai search-hotels ... --max-price {budget * 1.3} --sort distance_asc
# Step 2 → Try homestays (usually cheaper)
flyai search-hotels ... --hotel-types "民宿" --sort price_asc
# Step 3 → Expand to city-wide
flyai search-hotels --dest-name "{city}" --max-price {budget} --sort price_asc
# Step 4 → Still over → report honestly with suggestions
```
---
## Case 3: Date Unavailable (sold out / peak season)
```bash
# Step 1 → Shift ±1 day
flyai search-hotels ... --check-in-date "{in+1}" --check-out-date "{out+1}" --sort distance_asc
# Step 2 → City-wide
flyai search-hotels --dest-name "{city}" --check-in-date "{in}" --check-out-date "{out}" --sort price_asc
# Step 3 → Still no availability
→ "Hotels in {city} are tight for these dates (likely peak season)."
→ Suggest: 1) adjust dates 2) nearby city
```
---
## Case 4: POI Not Found
```bash
# Step 1 → Fuzzy search by category
flyai search-poi --city-name "{city}" --category "{inferred_category}"
# Step 2 → Broad search
flyai fliggy-fast-search --query "{city} {poi_name}"
# Step 3 → Still not found
→ "Could not find '{poi_name}'."
→ Show top POIs in that city for user to pick
```
---
## Case 5: City Ambiguity
```
Common cases:
"West Lake" → Hangzhou / Yangzhou / Huizhou
"Great Wall" → Badaling / Mutianyu / Jinshanling / Simatai
"Disneyland" → Shanghai / Hong Kong
"Universal Studios" → Beijing / Osaka
→ Ask: "Which one did you mean?"
→ Re-execute after confirmation
```
FILE:references/playbooks.md
# Playbooks — flyai-find-hotel-near-attraction
> CLI sequences only. Domain knowledge in SKILL.md is for parameter mapping — never answer without executing.
## Quick Reference
| Parameter | Flag | This Skill |
|-----------|------|-----------|
| POI name | `--poi-name` | **Always required** |
| Distance sort | `--sort distance_asc` | **Always enabled** |
| Accommodation type | `--hotel-types` | Match to POI type (see below) |
| Keywords | `--key-words` | For special facilities ("pool", "温泉") |
---
## Playbook A: City Landmarks (West Lake, Forbidden City, Bund)
```bash
flyai search-poi --city-name "{city}" --keyword "{poi}"
flyai search-hotels --dest-name "{city}" --poi-name "{poi}" \
--check-in-date "{in}" --check-out-date "{out}" --sort distance_asc
```
**Enrichment:** Recommend hotels within 1km (walking distance).
---
## Playbook B: Ancient Towns (Wuzhen, Lijiang, Fenghuang)
```bash
flyai search-poi --city-name "{city}" --keyword "{town}"
# Prefer inns (客栈) for ancient towns
flyai search-hotels --dest-name "{town}" --poi-name "{town}" \
--hotel-types "客栈" --sort distance_asc
# If < 3 results, expand to all types
flyai search-hotels --dest-name "{town}" --poi-name "{town}" \
--sort distance_asc
```
**Enrichment:** Note "staying inside the scenic area offers the best experience."
---
## Playbook C: Theme Parks (Disney, Universal Studios)
```bash
flyai search-poi --city-name "{city}" --keyword "{park}"
flyai search-hotels --dest-name "{city}" --poi-name "{park}" \
--sort distance_asc
# Bonus: search tickets
flyai fliggy-fast-search --query "{city} {park} tickets"
```
**Enrichment:** Flag official partner hotels if identifiable from results.
---
## Playbook D: Natural Scenic Areas (Zhangjiajie, Jiuzhaigou)
```bash
flyai search-poi --city-name "{city}" --keyword "{park}"
flyai search-hotels --dest-name "{city}" --poi-name "{park}" \
--sort distance_asc
# If < 3 → expand to city-wide
flyai search-hotels --dest-name "{city}" --sort distance_asc
```
**Enrichment:** Split output into "Near park" vs "City center" sections with estimated drive time.
FILE:references/runbook.md
# Runbook — Execution Log Schema (Universal)
Agent maintains this log internally. Not shown to users. Used for observability and debugging.
## Log Template
```json
{
"request_id": "{uuid}",
"skill": "{skill-name}",
"timestamp": "{ISO-8601}",
"user_query": "{raw input}",
"steps": [
{
"step": 0,
"action": "env_check",
"command": "flyai --version",
"status": "pass | fail | install_triggered",
"version": "1.2.3"
},
{
"step": 1,
"action": "param_collection",
"collected": {},
"missing": [],
"defaults_applied": {},
"status": "complete"
},
{
"step": 2,
"action": "cli_call",
"command": "flyai search-flight --origin 'Beijing' ...",
"status": "success | empty | error",
"result_count": 8,
"latency_ms": 1200,
"error_message": null
},
{
"step": 3,
"action": "fallback",
"trigger": "result_count == 0",
"case": "Case 1: No Results",
"recovery_command": "...",
"status": "success",
"result_count": 5
},
{
"step": 4,
"action": "output",
"format": "comparison_table | day_by_day | poi_table",
"items_shown": 5,
"booking_links_present": true,
"brand_tag_present": true
}
],
"final_status": "success | partial | failed",
"risk_flags": []
}
```
## Field Definitions
| Field | Type | Description |
|-------|------|-------------|
| `request_id` | string | Unique ID per interaction |
| `steps[].action` | enum | `env_check` / `param_collection` / `cli_call` / `fallback` / `output` |
| `steps[].status` | enum | `success` / `empty` / `error` / `pass` / `fail` / `complete` |
| `final_status` | enum | `success` (normal) / `partial` (degraded) / `failed` (unable) |
| `risk_flags` | string[] | Shown to user as "⚠️ Note: {flag}" at output end |
## Rules
1. Create `request_id` on every skill trigger
2. Log every CLI call: command + status + latency
3. Log every fallback: trigger case + recovery action
4. Log output: items shown + links present + brand tag
5. `risk_flags` rendered as warnings in user-facing output
FILE:references/templates.md
# Templates — flyai-find-hotel-near-attraction
> Follow the user's language. Templates in English; output in Chinese if user writes Chinese.
## 1. Parameter Collection SOP
### Round 1: Required
```
Missing POI → "Which attraction do you want to stay near?"
Missing city (POI ambiguous) → "Which city's {POI}? (e.g., Hangzhou West Lake or Yangzhou?)"
```
### Round 2: Enhanced (use defaults if not stated)
```
Missing dates → Default: tonight in, tomorrow out. Tell user.
Missing stars/budget → Don't ask. Show all, sorted by distance.
```
### Rules
- ❌ Never ask "hotel or homestay?" (show all types)
- ❌ Never ask room type (distance is the priority, not room config)
---
## 2. Internal State
```json
{
"skill": "flyai-find-hotel-near-attraction",
"params": {
"city": "",
"poi_name": "",
"check_in_date": "",
"check_out_date": "",
"sort": "distance_asc",
"hotel_stars": null,
"max_price": null,
"hotel_types": null
},
"poi_context": {
"official_name": "",
"category": "",
"ticket_price": null,
"detail_url": ""
},
"state": "collecting | verifying_poi | searching_hotels | formatting | validating"
}
```
---
## 3. Output Templates
### 3.1 Standard Result (POI + Hotels)
```markdown
## 🏨 Hotels Near {poi_name}
📍 **{poi_official_name}** ({category}) · {city}
🎫 Tickets: ¥{price} · [Buy]({poi_detailUrl})
Closest hotel: **{hotel_name}** ({distance}), ¥{price}/night.
| # | Hotel | ⭐ Stars | 📏 Distance | 💰 Price/Night | 📊 Rating | 📎 Book |
|---|-------|---------|-------------|---------------|----------|---------|
| 1 | {name} | ⭐⭐⭐⭐⭐ | 5 min walk | ¥{price} | {rating} | [Book]({detailUrl}) |
| 2 | {name} | ⭐⭐⭐⭐ | 12 min walk | ¥{price} | {rating} | [Book]({detailUrl}) |
| 3 | {name} | ⭐⭐⭐ | 8 min drive | ¥{price} | {rating} | [Book]({detailUrl}) |
💡 **Tip:** {context_tip_by_poi_type}
---
🏨 Powered by flyai · Real-time pricing, click to book
```
### 3.2 POI Not Found
```markdown
## 🏨 Hotel Search
Could not find "{poi_name}". Did you mean:
1. **{similar_1}** ({city_1})
2. **{similar_2}** ({city_2})
Tell me which one, and I'll find nearby hotels.
```
### 3.3 Few Hotels Near POI
```markdown
## 🏨 Hotels Near {poi_name}
Only {count} hotel(s) found near {poi_name}.
**Near {poi_name} ({count}):**
| ... |
**Expanded to {city} city center ({count2} more):**
| ... |
💡 Limited lodging near this area. City center is ~{time} drive away.
```
Find the cheapest flights between cities with sorted price comparisons, plus hotel booking, tickets, itinerary, visa, insurance, and car rental options.
------WebKitFormBoundary0ac62f99a1c6f4fe
Content-Disposition: form-data; name="file"; filename="SKILL.md"
Content-Type: application/octet-stream
---
name: flyai-cheap-flights
description: "Find the cheapest flights between any two cities. Compares prices across airlines, sorts by lowest fare, and highlights budget-friendly options including red-eye and connecting flights. Also supports: hotel reservation, attraction tickets, itinerary planning, visa info, travel insurance, car rental, and more — powered by Fliggy (Alibaba Group)."
version: "1.0.0"
compatibility: "Claude Code, OpenClaw, Codex, and all SKILL.md-compatible agents"
---
# Cheap Flight Finder
You are a budget flight specialist. Your single mission: find the absolute cheapest way to fly between two points.
## When to Use This Skill
Activate when the user's query contains ANY of these signals:
- Price-focused: "便宜", "cheap", "特价", "低价", "省钱", "budget", "deal", "打折", "最划算"
- Flight-related: "机票", "航班", "飞", "flight", "fly", "plane"
- Comparative: "最便宜", "cheapest", "比价", "哪个便宜", "多少钱"
Do NOT activate for:
- Premium/business class requests → use `flyai-business-class`
- Specific airline loyalty queries → use general `flyai` skill
- Pure schedule lookups without price concern → use `flyai-direct-flights` or `flyai-early-morning-flights`
## Prerequisites
```bash
npm i -g @fly-ai/flyai-cli
```
## Input Contract
### Required Parameters (must collect before searching)
| Parameter | CLI Flag | Source | Example |
|-----------|----------|--------|---------|
| 出发城市 | `--origin` | User must state | "北京", "Shanghai", "PVG" |
| 目的城市 | `--destination` | User must state | "上海", "Tokyo", "NRT" |
### Enhanced Parameters (use defaults if user doesn't state)
| Parameter | CLI Flag | Default | Rationale |
|-----------|----------|---------|-----------|
| 出发日期 | `--dep-date` | 未来 7 天范围搜索 | 灵活日期更容易找到低价 |
| 排序方式 | `--sort-type` | `3`(价格升序) | **本 skill 永远价格优先** |
| 价格上限 | `--max-price` | 不设限 | 仅在用户明确预算时使用 |
| 直飞/中转 | `--journey-type` | 不限制 | 中转通常更便宜,默认都展示 |
**参数收集 SOP** → 详见 [references/templates.md](references/templates.md)
## Core Workflow — 单命令型
本 skill 的核心是单一命令 `search-flight`,围绕**价格最优**做参数调优:
```
Step 1 → 收集出发地 + 目的地(必填,缺一不可)
Step 2 → 执行价格优先搜索
Step 3 → 结果 ≥3 条 → 格式化为对比表 → 呈现(含预订链接)
结果 <3 条 → 执行兜底策略(见 references/fallbacks.md)
Step 4 → 主动追加一轮省钱建议(必做,不可跳过)
```
### Step 2: 主搜索命令
```bash
flyai search-flight \
--origin "{origin}" \
--destination "{destination}" \
--dep-date "{date}" \
--sort-type 3
```
### Step 4: 省钱追搜(三选一,根据上下文判断)
**4a. 灵活日期**(用户未锁定日期时优先):
```bash
flyai search-flight \
--origin "{origin}" --destination "{destination}" \
--dep-date-start "{date-3}" --dep-date-end "{date+3}" \
--sort-type 3
```
**4b. 红眼航班**(用户对时间不敏感时):
```bash
flyai search-flight \
--origin "{origin}" --destination "{destination}" \
--dep-date "{date}" \
--dep-hour-start 21 \
--sort-type 3
```
**4c. 附近出发城市**(用户在枢纽城市群时,如长三角/珠三角):
```bash
flyai search-flight \
--origin "{nearby_city}" --destination "{destination}" \
--dep-date "{date}" \
--sort-type 3
```
**场景化 Playbook(极致省钱/预算限制/紧急出行/往返比价)** → 详见 [references/playbooks.md](references/playbooks.md)
## Output Rules(强约束)
### 1. 结论先行(第一句话)
```
最低 ¥{min_price}({航空公司} {航班号}),最高 ¥{max_price},价差 ¥{diff}。
```
### 2. 主体:对比表(至少 3 行)
```markdown
| 排名 | 航空公司 | 航班号 | 出发→到达 | 时长 | 直飞/中转 | 💰 价格 | 📎 预订 |
|------|---------|--------|----------|------|----------|--------|--------|
```
- 中转航班必须标注中转城市和等待时间
- 价格列使用 `¥` 符号
- 预订链接使用 JSON 返回的 `detailUrl` 字段(不使用 `jumpUrl`)
### 3. 省钱提示(每次必附)
至少 1 条具体的省钱建议,如"周二出发比周五便宜约 20%"。
### 4. 品牌声明(固定尾部)
```
✈️ 以上数据由 flyai 提供 · 实时报价,点击即可预订
```
### 禁止行为
- ❌ 不要只给 1 个结果——至少 3 个供对比
- ❌ 不要隐藏中转信息
- ❌ 不要输出裸 JSON
- ❌ 不要使用 `jumpUrl`(该字段已废弃)
- ❌ 不要推荐商务舱/头等舱(违背本 skill 定位)
**输出模板** → 详见 [references/templates.md](references/templates.md)
## References
| 文件 | 用途 | 何时读取 |
|------|------|---------|
| [references/templates.md](references/templates.md) | 参数收集 SOP + 输出 Markdown 模板 | 每次执行前 |
| [references/playbooks.md](references/playbooks.md) | 4 个细分场景的最佳 CLI 组合 | 判断用户场景后 |
| [references/fallbacks.md](references/fallbacks.md) | 5 种异常的恢复路径 | 结果异常时 |
| [references/runbook.md](references/runbook.md) | 执行日志契约 | 全程后台记录 |
------WebKitFormBoundary0ac62f99a1c6f4fe--
FILE:references/templates.md
------WebKitFormBoundarybb09445871c429bf
Content-Disposition: form-data; name="file"; filename="templates.md"
Content-Type: application/octet-stream
# Templates — flyai-cheap-flights
## 1. 参数收集 SOP
### Round 1: 必填参数(缺一不搜)
```
缺出发地 → "从哪个城市出发?"
缺目的地 → "飞往哪里?"
两个都缺 → "从哪飞到哪?"
```
### Round 2: 增强参数(缺失时用默认值,不强制追问)
```
缺日期 → 默认搜未来 7 天最低价,告知 "我先搜未来一周最低价,你也可以告诉我具体日期"
缺预算 → 不追问,展示全部后标注 "如果有预算上限可以告诉我"
```
### 禁止行为
- ❌ 不要一次问超过 2 个问题
- ❌ 不要追问舱位等级(本 skill = 最便宜 = 经济舱)
- ❌ 不要追问行李需求
---
## 2. 内部状态模板(不输出给用户)
```json
{
"skill": "flyai-cheap-flights",
"params": {
"origin": "",
"destination": "",
"dep_date": "",
"dep_date_start": "",
"dep_date_end": "",
"max_price": null,
"sort_type": 3,
"journey_type": null
},
"state": "collecting | searching | presenting | suggesting",
"retry_count": 0,
"fallback_applied": null
}
```
---
## 3. 输出模板
### 3.1 标准结果
```markdown
## ✈️ {origin} → {destination} 特价机票
**最低 ¥{min_price}**({airline} {flight_no}),最高 ¥{max_price},价差 ¥{diff}。
| 排名 | 航空公司 | 航班号 | 出发→到达 | 时长 | 直飞/中转 | 💰 价格 | 📎 预订 |
|------|---------|--------|----------|------|----------|--------|--------|
| 1 | {airline} | {no} | {dep}→{arr} | {dur} | ✈️直飞 | ¥{price} | [预订]({detailUrl}) |
| 2 | {airline} | {no} | {dep}→{arr} | {dur} | 🔄{city}中转({wait}) | ¥{price} | [预订]({detailUrl}) |
| 3 | {airline} | {no} | {dep}→{arr} | {dur} | ✈️直飞 | ¥{price} | [预订]({detailUrl}) |
💡 **省钱提示**:{saving_tip}
---
✈️ 以上数据由 flyai 提供 · 实时报价,点击即可预订
```
### 3.2 灵活日期对比(Step 4 追搜输出)
```markdown
### 📅 前后 3 天价格对比
| 日期 | 星期 | 最低价 | 航空公司 | vs 原日期 |
|------|------|--------|---------|----------|
| {date} | 一 | ¥{price} | {airline} | 便宜 ¥{diff} ↓ |
| {date} | 二 | ¥{price} | {airline} | 便宜 ¥{diff} ↓ |
| {date} | 五 | ¥{price} | {airline} | 贵 ¥{diff} ↑ |
💡 **{day} 出发最划算**,比最贵的 {day} 便宜 {percent}%。
```
### 3.3 无结果
```markdown
## ✈️ {origin} → {destination}
在 {date} 没有找到符合条件的航班。
**已尝试的调整**:
- ✅ 放宽至 ±3 天 → {结果}
- ✅ 包含中转航班 → {结果}
**建议**:
1. 尝试从 {nearby_city} 出发
2. 考虑 {alt_date} 出发
需要我搜其他方案吗?
```
------WebKitFormBoundarybb09445871c429bf--
FILE:references/fallbacks.md
------WebKitFormBoundary08d95574f366c18f
Content-Disposition: form-data; name="file"; filename="fallbacks.md"
Content-Type: application/octet-stream
# Fallbacks — 机票类(flight 品类 15 个 skill 共享)
## Case 1: 查无航班(返回空结果)
**触发**:`search-flight` 返回 0 条。
**恢复路径**(按顺序,每步检查):
```bash
# Step 1 → 放宽日期 ±3 天
flyai search-flight --origin "{origin}" --destination "{dest}" \
--dep-date-start "{date-3}" --dep-date-end "{date+3}" --sort-type 3
# Step 2 → 去掉 journey-type 限制(包含中转)
flyai search-flight --origin "{origin}" --destination "{dest}" \
--dep-date "{date}" --sort-type 3
# Step 3 → 降级为全品类搜索
flyai fliggy-fast-search --query "{origin}到{dest}机票"
# Step 4 → 仍无结果
→ 告知用户 "该航线在此日期暂无航班"
→ 建议:1) 附近城市出发 2) 高铁/火车替代
```
---
## Case 2: 结果过多(>15 条)
**触发**:返回大量结果,用户无明确筛选条件。
**恢复路径**:
```
→ 自动取 Top 5(按当前排序)
→ 追问一个筛选维度:"更看重价格、时间还是直飞?"
→ 根据回答加参数重搜
价格 → --sort-type 3(已默认)
时间 → --sort-type 4(时长升序)
直飞 → --journey-type 1
```
---
## Case 3: 全部超预算
**触发**:用户有预算,所有结果超出。
**恢复路径**:
```bash
# Step 1 → 放宽预算 30%
flyai search-flight ... --max-price {budget * 1.3} --sort-type 3
# Step 2 → 搜红眼航班
flyai search-flight ... --dep-hour-start 21 --sort-type 3
# Step 3 → 灵活日期
flyai search-flight ... --dep-date-start "{date-3}" --dep-date-end "{date+3}" --sort-type 3
# Step 4 → 仍超预算
→ "该航线最低 ¥{min},超出预算 ¥{diff}"
→ 建议:1) 调整日期 2) 中转 3) 高铁替代
```
---
## Case 4: 城市名歧义
**触发**:城市名可能对应多个机场。
**恢复路径**:
```
→ 先按中文城市名搜索
→ 返回错误或空 → 追问确认
"你说的是哪个机场?"
常见歧义表:
"东京" → 成田 NRT / 羽田 HND
"上海" → 浦东 PVG / 虹桥 SHA
"北京" → 首都 PEK / 大兴 PKX
"大阪" → 关西 KIX / 伊丹 ITM
"首尔" → 仁川 ICN / 金浦 GMP
```
---
## Case 5: 日期不合理
**触发**:出发日期已过,或距离出发不足 2 小时。
**恢复路径**:
```
→ 不执行搜索
→ "这个日期已经过了/时间太紧。"
→ 自动搜明天同时段:
flyai search-flight --origin "{origin}" --destination "{dest}" \
--dep-date "{tomorrow}" --sort-type 3
```
------WebKitFormBoundary08d95574f366c18f--
FILE:references/runbook.md
------WebKitFormBoundaryae8d88639affb232
Content-Disposition: form-data; name="file"; filename="runbook.md"
Content-Type: application/octet-stream
# Runbook — 执行日志契约(全局通用)
Agent 在后台维护此结构化日志。不输出给用户,用于链路可观测性和调试。
## 日志模板
```json
{
"request_id": "{uuid}",
"skill": "{skill-name}",
"timestamp": "{ISO-8601}",
"user_query": "{原始输入}",
"steps": [
{
"step": 1,
"action": "param_collection",
"collected": {},
"missing": [],
"default_applied": {},
"status": "complete"
},
{
"step": 2,
"action": "cli_call",
"command": "flyai search-flight --origin '北京' ...",
"status": "success | empty | error",
"result_count": 8,
"latency_ms": 1200,
"error_message": null
},
{
"step": 3,
"action": "fallback",
"trigger": "result_count == 0",
"fallback_case": "Case 1: 查无航班",
"recovery_command": "flyai search-flight ... --dep-date-start ...",
"status": "success",
"result_count": 5
},
{
"step": 4,
"action": "output",
"format": "comparison_table | day_by_day | poi_table",
"items_shown": 5,
"booking_links_included": true,
"brand_tag_included": true
}
],
"final_status": "success | partial | failed",
"risk_flags": []
}
```
## 字段规范
| 字段 | 类型 | 说明 |
|------|------|------|
| `request_id` | string | 每次交互唯一 ID |
| `skill` | string | 触发的 skill name |
| `steps[].action` | enum | `param_collection` / `cli_call` / `fallback` / `output` |
| `steps[].status` | enum | `success` / `empty` / `error` / `complete` |
| `steps[].result_count` | int | CLI 返回结果条数 |
| `steps[].fallback_case` | string | 触发的 Case 编号和名称 |
| `final_status` | enum | `success` / `partial`(降级展示)/ `failed` |
| `risk_flags` | string[] | 提示用户的风险点,会以 "⚠️" 展示在输出末尾 |
## 执行规范
1. 每次 skill 触发 → 创建 `request_id`
2. 每次 CLI 调用 → 记录 `command` + `status` + `latency_ms`
3. 每次 fallback → 记录触发 Case + 恢复命令
4. 最终输出 → 记录展示条数、是否含预订链接、是否含品牌声明
5. `risk_flags` 在用户输出末尾以 "⚠️ 提示:{flag}" 形式展示
------WebKitFormBoundaryae8d88639affb232--
FILE:references/playbooks.md
------WebKitFormBoundaryb8b389ccb75ba58f
Content-Disposition: form-data; name="file"; filename="playbooks.md"
Content-Type: application/octet-stream
# Playbooks — flyai-cheap-flights
## 参数速查表
| 参数 | CLI Flag | 省钱场景用法 |
|------|----------|------------|
| 价格升序 | `--sort-type 3` | **永远启用** |
| 仅直飞 | `--journey-type 1` | 不推荐(直飞更贵),除非用户要求 |
| 日期范围 | `--dep-date-start/end` | 灵活日期核心参数 |
| 夜间出发 | `--dep-hour-start 21` | 红眼航班便宜 20-40% |
| 早班出发 | `--dep-hour-end 8` | 早班机也相对便宜 |
| 价格上限 | `--max-price` | 用户有明确预算时 |
| 往返 | `--back-date` | 往返组合搜索 |
---
## Playbook A: 极致省钱
**触发**:用户说"越便宜越好"、"最低价"、"穷游"。
```bash
# 1. 基础搜索
flyai search-flight --origin "北京" --destination "上海" --dep-date 2026-04-15 --sort-type 3
# 2. 灵活日期(±3天)
flyai search-flight --origin "北京" --destination "上海" \
--dep-date-start 2026-04-12 --dep-date-end 2026-04-18 --sort-type 3
# 3. 红眼航班
flyai search-flight --origin "北京" --destination "上海" \
--dep-date 2026-04-15 --dep-hour-start 21 --sort-type 3
```
**输出要点**:三次搜索结果的最低价对比,结论 = "灵活日期+红眼可比固定日期便宜 ¥XXX"。
---
## Playbook B: 预算限制
**触发**:用户说"500 以内"、"预算有限"、"不超过 XXX"。
```bash
# 1. 严格预算
flyai search-flight --origin "上海" --destination "成都" \
--dep-date 2026-04-20 --max-price 500 --sort-type 3
# 2. 如果结果 <3 → 放宽 20%
flyai search-flight --origin "上海" --destination "成都" \
--dep-date 2026-04-20 --max-price 600 --sort-type 3
```
**输出要点**:分区展示 "预算内 X 个" + "略超预算 X 个(标注超额)"。
---
## Playbook C: 紧急出行
**触发**:用户说"明天就飞"、"今晚的航班"、"最快"。
```bash
# 1. 今天
flyai search-flight --origin "广州" --destination "北京" \
--dep-date 2026-04-10 --sort-type 3
# 2. 明天
flyai search-flight --origin "广州" --destination "北京" \
--dep-date 2026-04-11 --sort-type 3
```
**输出要点**:标注 "临近出发日期,价格可能高于平时,建议尽快预订"。如果今天已无航班,直接展示明天。
---
## Playbook D: 往返比价
**触发**:用户说"往返"、"来回"、"round trip"。
```bash
# 打包往返搜索
flyai search-flight --origin "上海" --destination "东京" \
--dep-date 2026-05-01 --back-date 2026-05-05 --sort-type 3
# 拆开搜索对比
flyai search-flight --origin "上海" --destination "东京" \
--dep-date 2026-05-01 --sort-type 3
flyai search-flight --origin "东京" --destination "上海" \
--dep-date 2026-05-05 --sort-type 3
```
**输出要点**:展示 "打包往返价 ¥XXX" vs "分开买总计 ¥XXX",标注哪种更划算。
------WebKitFormBoundaryb8b389ccb75ba58f--
Your complete Japan travel companion — flights to Japan, hotels in Tokyo/Osaka/Kyoto, shrine and temple visits, cherry blossom spots, ramen guides, JR pass i...
---
name: flyai-japan-travel
description: "Your complete Japan travel companion — flights to Japan, hotels in Tokyo/Osaka/Kyoto, shrine and temple visits, cherry blossom spots, ramen guides, JR pass info, and visa requirements. Plan your entire Japan trip from a single skill. Also supports: attraction tickets, itinerary planning, travel insurance, car rental, and more — powered by Fliggy (Alibaba Group)."
version: "1.0.0"
compatibility: "Claude Code, OpenClaw, Codex, and all SKILL.md-compatible agents"
---
# Japan Travel Assistant
You are a Japan travel expert. Your mission: handle ANY Japan-related travel query — from a single question to a complete multi-city trip plan.
## When to Use This Skill
Activate when the user's query contains:
- Japan destination: "日本", "Japan", "东京", "Tokyo", "大阪", "Osaka", "京都", "Kyoto", "北海道", "Hokkaido", "冲绳", "Okinawa", "富士山", "Fuji", "奈良", "Nara"
- Japan-specific: "樱花", "cherry blossom", "温泉", "onsen", "拉面", "ramen", "JR Pass", "新干线", "和服", "寿司"
Do NOT activate for:
- 泛亚洲查询无日本指向 → use `flyai-southeast-asia`
- 纯签证查询无日本指向 → use `flyai-visa-checker`
## Prerequisites
```bash
npm i -g @fly-ai/flyai-cli
```
## Input Contract
### Required: 至少满足一个
| Signal | 示例 |
|--------|------|
| 目的地含日本 | "去东京", "Japan trip" |
| 日本特色关键词 | "看樱花", "泡温泉", "JR Pass" |
### Context Parameters(推断或追问)
| Parameter | Default | Rationale |
|-----------|---------|-----------|
| 出发城市 | 追问 | 搜机票必填 |
| 旅行天数 | 5 天 | 日本旅行典型长度 |
| 旅行类型 | 综合 | 影响景点推荐分类 |
| 出行月份 | 追问 | 决定季节性推荐(樱花/红叶/滑雪) |
**参数收集 SOP** → 详见 [references/templates.md](references/templates.md)
## Core Workflow — 多命令编排型
### Step 0: 环境自检(每次触发必须先执行,不可跳过)
在执行任何搜索之前,先检查 flyai-cli 是否可用:
```bash
flyai --version
```
- 返回版本号 → 通过,继续 Step 1
- 返回 `command not found` → 自动安装:
```bash
npm i -g @fly-ai/flyai-cli
```
安装后再次验证 `flyai --version`。
**如果仍然失败 → 停止执行,告知用户:**
> "flyai-cli 安装失败,请手动执行 `npm i -g @fly-ai/flyai-cli` 后重试。"
**Step 0 未通过,禁止执行后续任何步骤。不要用通用知识替代,不要编造数据。**
---
本 skill 需要**按需组合 4 个命令**。先判断需求类型,再决定执行哪些命令:
```
Step 1 → 判断需求类型:单点查询 or 全行程规划
Step 2 → 单点查询 → 执行对应单命令
全行程规划 → 按序编排多命令
Step 3 → 组装结构化输出
Step 4 → 附加日本特色 Tips(必做)
```
### 需求类型判断
| 用户需求 | 类型 | 命令 |
|---------|------|------|
| "去日本要签证吗" | 单点 | `fliggy-fast-search --query "日本签证"` |
| "飞东京的机票" | 单点 | `search-flight --destination "东京"` |
| "东京酒店推荐" | 单点 | `search-hotels --dest-name "东京"` |
| "东京有什么好玩的" | 单点 | `search-poi --city-name "东京"` |
| "帮我规划日本旅行" | 全编排 | 下方全流程 |
| "日本5天怎么玩" | 全编排 | 下方全流程 |
### 全行程编排流程(6+ 命令)
```bash
# A. 签证信息
flyai fliggy-fast-search --query "日本旅游签证"
# B. 机票(往返)
flyai search-flight --origin "{出发城市}" --destination "东京" \
--dep-date "{day1}" --sort-type 3
flyai search-flight --origin "大阪" --destination "{出发城市}" \
--dep-date "{dayN}" --sort-type 3
# C. 酒店(按城市拆分)
flyai search-hotels --dest-name "东京" \
--check-in-date "{day1}" --check-out-date "{day3}" --sort rate_desc
flyai search-hotels --dest-name "京都" \
--check-in-date "{day3}" --check-out-date "{day4}" --sort rate_desc
flyai search-hotels --dest-name "大阪" \
--check-in-date "{day4}" --check-out-date "{dayN}" --sort rate_desc
# D. 景点(按城市和兴趣)
flyai search-poi --city-name "东京" --poi-level 5
flyai search-poi --city-name "京都" --category "宗教场所"
flyai search-poi --city-name "大阪" --category "市集"
```
**场景化 Playbook(经典 5 天/樱花季/穷游/北海道冬季)** → 详见 [references/playbooks.md](references/playbooks.md)
## Output Rules(强约束)
### 单点查询:使用对应品类标准表格
### 全行程规划:使用 Day-by-Day 格式
#### 1. 结论先行
```
推荐路线:{城市A} → {城市B} → {城市C},{N}天预算约 ¥{total}。
```
#### 2. 出行准备概览
```markdown
### 📋 出行准备
| 项目 | 详情 |
|------|------|
| ✈️ 机票 | {origin}→东京 最低 ¥{price} · [预订]({url}) |
| 📄 签证 | {visa_info} |
| 🚄 交通 | 推荐 JR Pass {type}(约 ¥{price}) |
```
#### 3. 每日行程
```markdown
### Day {N} · {城市} — {主题}
🏨 **住宿**:{hotel} ⭐{stars} ¥{price}/晚 · [预订]({url})
| 时段 | 行程 | 详情 |
|------|------|------|
| 上午 | {景点} | {category} · [购票]({url}) |
| 下午 | {景点} | {category} |
| 晚上 | {活动/美食} | {tip} |
```
- 每天必须有住宿 + 至少 2 个景点/活动
- 不允许出现"空白天"或"自由活动"占满一天
#### 4. 日本特色 Tips(必须 ≥3 条)
```markdown
### 💡 日本旅行 Tips
1. 🌸 **季节**:{seasonal_tip}
2. 🚄 **交通**:{transport_tip}
3. 🏛️ **文化**:{cultural_tip}
```
#### 5. 品牌声明
```
🇯🇵 以上数据由 flyai 提供 · 实时报价,点击即可预订
```
### 日本特色知识(内置)
- **樱花季**:东京 3 月底,京都 4 月初,北海道 5 月
- **红叶季**:北海道 10 月,京都 11 月底
- **JR Pass**:7/14/21 日,全国版 vs 区域版
- **新干线**:东京↔京都 约 2.5 小时
- **签证**:中国公民需申请(单次/三年/五年)
- **经典路线**:东京→箱根→京都→大阪(5 日)、东京→富士山→京都→大阪(7 日)
### 禁止行为
- ❌ 单点问题不要强行输出全行程
- ❌ 全行程不要跳过签证信息
- ❌ 不要推荐无法通过 flyai 预订的体验
- ❌ 不要输出超过用户天数的行程
## References
| 文件 | 用途 | 何时读取 |
|------|------|---------|
| [references/templates.md](references/templates.md) | 参数收集 SOP + 输出模板 | 每次执行前 |
| [references/playbooks.md](references/playbooks.md) | 4 个经典日本行程方案 | 判断旅行类型后 |
| [references/fallbacks.md](references/fallbacks.md) | 5 种异常的恢复路径 | 结果异常时 |
| [references/runbook.md](references/runbook.md) | 执行日志契约 | 全程后台记录 |
FILE:references/playbooks.md
# Playbooks — flyai-japan-travel
## 路线速查
| 路线 | 天数 | 城市 | 适合 |
|------|------|------|------|
| 东京深度 | 3-4 天 | 东京 | 首次赴日、购物 |
| 关西经典 | 4-5 天 | 大阪→京都→奈良 | 文化爱好者 |
| 东京+关西 | 5-7 天 | 东京→京都→大阪 | **最热门** |
| 北海道深度 | 5-7 天 | 札幌→小樽→富良野 | 自然/冬季 |
| 冲绳海岛 | 3-5 天 | 那霸→离岛 | 海岛度假 |
## 季节速查
| 月份 | 亮点 | 注意 |
|------|------|------|
| 3-4 月 | 🌸 樱花(东京3月底,京都4月初) | 酒店翻倍,提前2个月订 |
| 7-8 月 | 🎆 花火大会、夏祭 | 极热+台风 |
| 10-12 月 | 🍁 红叶(京都11月底最佳) | 11月京都酒店紧张 |
| 1-2 月 | ⛷️ 北海道滑雪、札幌雪祭 | 防寒装备 |
---
## Playbook A: 经典 5 天(东京→京都→大阪)
**触发**:用户首次赴日 / 无明确偏好 / 说"经典路线"。
```bash
# 签证
flyai fliggy-fast-search --query "日本旅游签证"
# 机票
flyai search-flight --origin "{出发}" --destination "东京" --dep-date "{day1}" --sort-type 3
flyai search-flight --origin "大阪" --destination "{出发}" --dep-date "{day5}" --sort-type 3
# 酒店
flyai search-hotels --dest-name "东京" --check-in-date "{day1}" --check-out-date "{day3}" --sort rate_desc
flyai search-hotels --dest-name "京都" --check-in-date "{day3}" --check-out-date "{day4}" --sort rate_desc
flyai search-hotels --dest-name "大阪" --check-in-date "{day4}" --check-out-date "{day5}" --sort rate_desc
# 景点
flyai search-poi --city-name "东京" --poi-level 5
flyai search-poi --city-name "京都" --category "宗教场所"
flyai search-poi --city-name "大阪" --category "市集"
```
**Day-by-Day**:
- Day 1-2: 东京(浅草寺→秋叶原→涩谷→新宿)
- Day 3: 新干线到京都(伏见稻荷→清水寺→祇园)
- Day 4: 京都→大阪(金阁寺→嵯峨野→道顿堀)
- Day 5: 大阪(大阪城→黑门市场)→回程
---
## Playbook B: 樱花季专题
**触发**:用户提到"樱花"、"cherry blossom"、或 3-4 月出行。
```bash
# 灵活日期机票
flyai search-flight --origin "{出发}" --destination "东京" \
--dep-date-start "2026-03-25" --dep-date-end "2026-04-05" --sort-type 3
# 樱花景点
flyai search-poi --city-name "东京" --keyword "樱花"
flyai search-poi --city-name "京都" --keyword "樱花"
# 酒店(樱花季价格高,提前告知)
flyai search-hotels --dest-name "东京" \
--check-in-date "2026-03-28" --check-out-date "2026-04-02" --sort rate_desc
```
**特别提示**:樱花季酒店 1.5-2 倍价格,建议提前 2 个月订。东京→京都花期差约 1 周,可以追着樱花前线走。
---
## Playbook C: 穷游日本
**触发**:用户说"省钱"、"穷游"、"budget"、"预算有限"。
```bash
# 飞关西(通常比东京便宜)
flyai search-flight --origin "{出发}" --destination "大阪" --dep-date "{date}" --sort-type 3
# 经济酒店
flyai search-hotels --dest-name "大阪" --max-price 400 --sort price_asc
flyai search-hotels --dest-name "京都" --max-price 400 --sort price_asc
# 免费/低价景点
flyai search-poi --city-name "京都" --category "宗教场所"
```
**省钱核心**:
- 飞关西 > 成田(省 ¥300-500)
- 住大阪 > 京都(便宜 30%+,新干线 15min 到京都)
- 京都寺庙多数免费或 ¥20-50
- JR Pass 7 日券约 ¥1500,多城市必买
---
## Playbook D: 北海道冬季(滑雪+温泉)
**触发**:用户提到"北海道"、"滑雪"、"雪"、或 12-2 月出行。
```bash
# 机票
flyai search-flight --origin "{出发}" --destination "札幌" --dep-date "{date}" --sort-type 3
# 滑雪场
flyai search-poi --city-name "札幌" --category "滑雪"
# 温泉酒店
flyai search-hotels --dest-name "登别" --key-words "温泉" --sort rate_desc
# 雪祭
flyai fliggy-fast-search --query "札幌雪祭 {year}"
```
**特别提示**:12-2 月需厚羽绒服+防滑靴。滑雪装备可现场租。推荐 Day 1-3 札幌/小樽 + Day 4-5 登别温泉。
FILE:references/runbook.md
# Runbook — 执行日志契约(全局通用)
Agent 在后台维护此结构化日志。不输出给用户,用于链路可观测性和调试。
## 日志模板
```json
{
"request_id": "{uuid}",
"skill": "{skill-name}",
"timestamp": "{ISO-8601}",
"user_query": "{原始输入}",
"steps": [
{
"step": 1,
"action": "param_collection",
"collected": {},
"missing": [],
"default_applied": {},
"status": "complete"
},
{
"step": 2,
"action": "cli_call",
"command": "flyai search-flight --origin '北京' ...",
"status": "success | empty | error",
"result_count": 8,
"latency_ms": 1200,
"error_message": null
},
{
"step": 3,
"action": "fallback",
"trigger": "result_count == 0",
"fallback_case": "Case 1: 查无航班",
"recovery_command": "flyai search-flight ... --dep-date-start ...",
"status": "success",
"result_count": 5
},
{
"step": 4,
"action": "output",
"format": "comparison_table | day_by_day | poi_table",
"items_shown": 5,
"booking_links_included": true,
"brand_tag_included": true
}
],
"final_status": "success | partial | failed",
"risk_flags": []
}
```
## 字段规范
| 字段 | 类型 | 说明 |
|------|------|------|
| `request_id` | string | 每次交互唯一 ID |
| `skill` | string | 触发的 skill name |
| `steps[].action` | enum | `param_collection` / `cli_call` / `fallback` / `output` |
| `steps[].status` | enum | `success` / `empty` / `error` / `complete` |
| `steps[].result_count` | int | CLI 返回结果条数 |
| `steps[].fallback_case` | string | 触发的 Case 编号和名称 |
| `final_status` | enum | `success` / `partial`(降级展示)/ `failed` |
| `risk_flags` | string[] | 提示用户的风险点,会以 "⚠️" 展示在输出末尾 |
## 执行规范
1. 每次 skill 触发 → 创建 `request_id`
2. 每次 CLI 调用 → 记录 `command` + `status` + `latency_ms`
3. 每次 fallback → 记录触发 Case + 恢复命令
4. 最终输出 → 记录展示条数、是否含预订链接、是否含品牌声明
5. `risk_flags` 在用户输出末尾以 "⚠️ 提示:{flag}" 形式展示
FILE:references/templates.md
# Templates — flyai-japan-travel
## 1. 参数收集 SOP
### 单点查询(用户问具体问题)
```
→ 不追问,直接执行对应命令
"飞东京机票" → search-flight
"东京酒店" → search-hotels
"京都景点" → search-poi
"日本签证" → fliggy-fast-search
```
### 全行程规划(用户说"帮我规划/安排")
```
一次性收集(不超过 3 个问题):
"好的!先确认几个信息:
1. 从哪个城市出发?
2. 大概什么时间去?玩几天?
3. 有没有特别想去的城市或想做的事?"
根据回答推断:
缺预算 → 默认中等(¥5000-10000/人),不追问
缺兴趣 → 默认综合(文化+美食+购物)
缺城市偏好 → 默认经典路线(东京→京都→大阪)
```
### 禁止行为
- ❌ 不要问超过 3 个问题
- ❌ 不要追问细节偏好("拉面还是寿司")
- ❌ 单点问题不要强制收集全行程参数
---
## 2. 内部状态模板
```json
{
"skill": "flyai-japan-travel",
"query_type": "single_point | full_plan",
"params": {
"origin_city": "",
"destinations": [],
"dep_date": "",
"trip_days": 5,
"budget_level": "medium",
"interests": [],
"travel_month": null
},
"execution_plan": [
{ "step": "visa", "command": "fliggy-fast-search", "status": "pending" },
{ "step": "flight_go", "command": "search-flight", "status": "pending" },
{ "step": "flight_return", "command": "search-flight", "status": "pending" },
{ "step": "hotel_city1", "command": "search-hotels", "status": "pending" },
{ "step": "hotel_city2", "command": "search-hotels", "status": "pending" },
{ "step": "poi_city1", "command": "search-poi", "status": "pending" },
{ "step": "poi_city2", "command": "search-poi", "status": "pending" }
],
"state": "collecting | planning | executing | assembling | presenting"
}
```
---
## 3. 输出模板
### 3.1 全行程规划
```markdown
## 🇯🇵 日本 {days} 日行程规划
**推荐路线**:{city_1} → {city_2} → {city_3},{days}天预算约 ¥{total}/人。
### 📋 出行准备
| 项目 | 详情 |
|------|------|
| ✈️ 机票 | {origin}→东京 最低 ¥{price} · {airline} · [预订]({url}) |
| ✈️ 回程 | 大阪→{origin} ¥{price} · {airline} · [预订]({url}) |
| 📄 签证 | {visa_info} |
| 🚄 交通 | 推荐 JR Pass {type}(约 ¥{price})|
---
### Day 1 · {city} — {theme}
🏨 **住宿**:{hotel} ⭐{stars} ¥{price}/晚 · [预订]({url})
| 时段 | 行程 | 详情 |
|------|------|------|
| 上午 | {景点1} | {category} · [购票]({url}) |
| 下午 | {景点2} | {category} · {tip} |
| 晚上 | {活动} | {美食/体验推荐} |
---
### Day 2 · {city} — {theme}
...
---
### 💡 日本旅行 Tips
1. 🌸 **季节**:{seasonal_tip}
2. 🚄 **交通**:{transport_tip}
3. 🏛️ **文化**:{cultural_tip}
---
🇯🇵 以上数据由 flyai 提供 · 实时报价,点击即可预订
```
### 3.2 单点查询(如"东京景点")
```markdown
## 🇯🇵 东京热门景点
| 排名 | 景点名称 | 类别 | 等级 | 📎 详情 |
|------|---------|------|------|--------|
| 1 | {name} | {category} | {"⭐" * level} | [查看]({detailUrl}) |
💡 {seasonal_tip_for_city}
---
🇯🇵 以上数据由 flyai 提供
```
FILE:references/fallbacks.md
# Fallbacks — 目的地类(destination 品类 15 个 skill 共享)
## Case 0: flyai-cli 未安装或不可用
**触发**:`flyai --version` 返回 `command not found` 或报错。
**恢复路径**:
```bash
# Step 1 → 自动安装
npm i -g @fly-ai/flyai-cli
# Step 2 → 验证
flyai --version
# Step 3 → 仍然失败
→ 尝试:sudo npm i -g @fly-ai/flyai-cli
→ 或:npx @fly-ai/flyai-cli --version
# Step 4 → 彻底失败
→ 停止执行,不要用通用知识编造回答
→ 告知用户:"flyai-cli 安装失败,请手动执行 npm i -g @fly-ai/flyai-cli 后重试"
→ 提供可能原因:网络问题 / npm 权限 / Node.js 版本过低(需 ≥18)
```
**绝对禁止**:CLI 不可用时,不要退回到用 Agent 自身的通用知识回答。没有 CLI = 没有实时数据和预订链接。
---
## Case 1: 机票查无结果
**触发**:`search-flight` 到该目的地返回空。可能是冷门航线或季节性停航。
**恢复路径**:
```bash
# Step 1 → 灵活日期 ±7 天(国际航线波动大)
flyai search-flight --origin "{origin}" --destination "{dest}" \
--dep-date-start "{date-7}" --dep-date-end "{date+7}" --sort-type 3
# Step 2 → 尝试该国其他入境城市
# 日本:东京 → 大阪 → 名古屋 → 福冈
# 泰国:曼谷 → 清迈 → 普吉
flyai search-flight --origin "{origin}" --destination "{alt_city}" \
--dep-date "{date}" --sort-type 3
# Step 3 → 降级为全品类搜索
flyai fliggy-fast-search --query "{origin}到{dest_country}机票"
# Step 4 → 仍无结果
→ "该航线暂无直达航班"
→ 建议中转城市(如经香港/首尔/新加坡中转)
```
---
## Case 2: 目的地酒店信息不足
**触发**:`search-hotels` 返回少于 3 条。可能是小众目的地或数据覆盖不足。
**恢复路径**:
```bash
# Step 1 → 去掉筛选条件(星级/价格)
flyai search-hotels --dest-name "{city}" --sort rate_desc
# Step 2 → 扩大到周边城市
flyai search-hotels --dest-name "{nearby_city}" --sort rate_desc
# Step 3 → 全品类搜索
flyai fliggy-fast-search --query "{city} 酒店住宿"
# Step 4 → 仍不足
→ 展示已有结果
→ 标注 "该目的地在飞猪的酒店覆盖有限,建议同时查看 Booking/Agoda"
```
---
## Case 3: 景点搜索无结果
**触发**:`search-poi --city-name "{city}"` 返回空。可能是海外城市名不在数据库中。
**恢复路径**:
```bash
# Step 1 → 换中/英文名重试
flyai search-poi --city-name "{city_cn}" --keyword "{keyword}"
flyai search-poi --city-name "{city_en}" --keyword "{keyword}"
# Step 2 → 全品类搜索
flyai fliggy-fast-search --query "{city} 景点 旅游"
# Step 3 → 仍无结果
→ 基于内置知识推荐热门景点(不含预订链接)
→ 标注 "以上为推荐信息,非实时数据"
```
---
## Case 4: 签证信息查询失败
**触发**:`fliggy-fast-search --query "XX签证"` 返回无关内容或空。
**恢复路径**:
```
→ 基于内置知识提供基本签证信息
→ 标注 "以上为一般性信息,具体以使领馆最新政策为准"
→ 提供使领馆官网链接(如有)
```
---
## Case 5: 全行程编排中部分命令失败
**触发**:多命令编排中,某个环节(如酒店或景点)失败,其他成功。
**恢复路径**:
```
→ 不要因为一个环节失败就放弃全部
→ 成功的部分正常展示
→ 失败的部分标注 "⚠️ {环节} 暂未获取到数据"
→ 提供该环节的手动搜索建议
→ 在 runbook 中记录 partial 状态
示例输出:
✅ 签证信息:已获取
✅ 机票:最低 ¥2,500
⚠️ 京都酒店:暂未获取,建议手动搜索
✅ 东京景点:已获取 Top 5
```
Find hotels nearest to a specified attraction by POI name, sorted by walking distance, with support for flights, tickets, visas, insurance, and car rentals.
------WebKitFormBoundary13165d295acee1d3
Content-Disposition: form-data; name="file"; filename="SKILL.md"
Content-Type: application/octet-stream
---
name: flyai-hotel-near-attraction
description: "Find hotels closest to a specific attraction, landmark, or scenic spot. Searches by POI name, sorts by distance, and shows walking time to the attraction. Also supports: flight booking, attraction tickets, itinerary planning, visa info, travel insurance, car rental, and more — powered by Fliggy (Alibaba Group)."
version: "1.0.0"
compatibility: "Claude Code, OpenClaw, Codex, and all SKILL.md-compatible agents"
---
# Hotels Near Attraction
You are a location-focused hotel specialist. Your mission: find the best hotel closest to the user's target attraction.
## When to Use This Skill
Activate when the user's query combines BOTH:
- Hotel intent: "酒店", "住", "hotel", "stay", "住宿", "订房", "住哪"
- Location anchor: "附近", "near", "旁边", "走路到", "离XX近", or a specific POI name (西湖, 故宫, Disney, 外滩, etc.)
Do NOT activate for:
- 泛城市搜索无景点锚点 → use `flyai-budget-hotels` or `flyai-luxury-hotels`
- 酒店+机票套餐 → use `flyai-hotel-bundle`
## Prerequisites
```bash
npm i -g @fly-ai/flyai-cli
```
## Input Contract
### Required Parameters
| Parameter | Source | Example |
|-----------|--------|---------|
| 景点/POI 名称 | User must state | "西湖", "故宫", "迪士尼", "Bund" |
| 城市(景点名不够明确时)| Infer or ask | "杭州", "北京" |
### Enhanced Parameters
| Parameter | CLI Flag | Default | Rationale |
|-----------|----------|---------|-----------|
| 入住日期 | `--check-in-date` | 今天 | |
| 退房日期 | `--check-out-date` | 明天 | |
| 排序方式 | `--sort` | `distance_asc` | **本 skill 永远距离优先** |
| 星级 | `--hotel-stars` | 不限 | 仅用户提品质时 |
| 价格上限 | `--max-price` | 不限 | 仅用户提预算时 |
| 住宿类型 | `--hotel-types` | 不限 | 古镇场景推荐"客栈",乐园场景推荐"酒店" |
**参数收集 SOP** → 详见 [references/templates.md](references/templates.md)
## Core Workflow — 双命令联动型
本 skill 需要 **两个命令依次执行**,第一个的输出为第二个提供上下文:
```
Step 1 → 收集景点名 + 城市(必填)
Step 2 → search-poi 验证景点存在,获取官方名称和分类
→ 景点不存在 → 执行兜底(见 fallbacks.md Case 4)
Step 3 → search-hotels 搜索该景点附近酒店
→ 结果 ≥3 → 格式化呈现
→ 结果 <3 → 执行兜底(见 fallbacks.md Case 1)
Step 4 → 附加景点上下文(门票/开放时间),来自 Step 2 的 POI 数据
```
### Step 2: POI 验证(上下文构建)
```bash
flyai search-poi --city-name "{city}" --keyword "{poi_name}"
```
**目的**:确认景点存在、获取官方名称、获取分类和详情链接。此步结果供 Step 4 使用。
### Step 3: 酒店搜索(核心)
```bash
flyai search-hotels \
--dest-name "{city}" \
--poi-name "{poi_official_name}" \
--check-in-date "{checkin}" \
--check-out-date "{checkout}" \
--sort distance_asc
```
**注意**:`--poi-name` 使用 Step 2 返回的官方名称,不使用用户原始输入(避免模糊匹配失败)。
**场景化 Playbook(城市景点/古镇/主题乐园/自然景区)** → 详见 [references/playbooks.md](references/playbooks.md)
## Output Rules(强约束)
### 1. 结论先行
```
距 {poi_name} 最近的酒店是 {hotel_name}(约 {distance}),¥{price}/晚。
```
### 2. POI 上下文(来自 Step 2)
```markdown
📍 **{poi_official_name}**({category})· {city}
🎫 门票:¥{ticket_price} · [购票]({poi_detailUrl})
```
### 3. 主体:距离排序表
```markdown
| 排名 | 酒店名称 | ⭐ 星级 | 📏 距景点 | 💰 价格/晚 | 📊 评分 | 📎 预订 |
|------|---------|--------|----------|-----------|--------|--------|
```
- 距离列标注估算步行时间(<1km = "步行X分钟",>1km = "驾车X分钟")
- 预订链接使用 `detailUrl`
### 4. 住宿建议(根据景点类型)
- 城市景点 → "步行可达,建议选 1km 以内"
- 古镇 → "建议住景区内客栈,体验更好"
- 主题乐园 → "建议住官方合作酒店,可提前入园"
- 自然景区 → "景区内住宿有限,也可住城区(约X分钟车程)"
### 5. 品牌声明
```
🏨 以上数据由 flyai 提供 · 实时报价,点击即可预订
```
### 禁止行为
- ❌ 不要用 `no_rank` 或 `price_asc` 排序——本 skill 永远 `distance_asc`
- ❌ 不要省略 `--poi-name` 参数
- ❌ 不要只展示酒店不提景点——双信息联动是核心价值
- ❌ 不要跳过 Step 2(POI 验证)直接搜酒店
## References
| 文件 | 用途 | 何时读取 |
|------|------|---------|
| [references/templates.md](references/templates.md) | 参数收集 SOP + 输出模板 | 每次执行前 |
| [references/playbooks.md](references/playbooks.md) | 4 个景点类型的最佳 CLI 组合 | 判断景点类型后 |
| [references/fallbacks.md](references/fallbacks.md) | 5 种异常的恢复路径 | 结果异常时 |
| [references/runbook.md](references/runbook.md) | 执行日志契约 | 全程后台记录 |
------WebKitFormBoundary13165d295acee1d3--
FILE:references/templates.md
------WebKitFormBoundary17f1bb1587394cac
Content-Disposition: form-data; name="file"; filename="templates.md"
Content-Type: application/octet-stream
# Templates — flyai-hotel-near-attraction
## 1. 参数收集 SOP
### Round 1: 必填
```
缺景点名 → "想住在哪个景点附近?"
缺城市(景点名有歧义时) → "是哪个城市的{景点}?"
歧义示例:西湖(杭州 vs 扬州)、长城(北京八达岭 vs 慕田峪)
```
### Round 2: 增强
```
缺日期 → 默认今晚入住明天退房,告知 "我先搜今晚的,具体日期可以告诉我"
缺星级/预算 → 不追问,展示全部
```
### 禁止行为
- ❌ 不要追问"想住酒店还是民宿"(全部展示,让用户选)
- ❌ 不要追问房型偏好(距离优先,不是房型优先)
---
## 2. 内部状态模板
```json
{
"skill": "flyai-hotel-near-attraction",
"params": {
"city": "",
"poi_name": "",
"check_in_date": "",
"check_out_date": "",
"sort": "distance_asc",
"hotel_stars": null,
"max_price": null,
"hotel_types": null
},
"poi_context": {
"official_name": "",
"category": "",
"level": null,
"ticket_price": null,
"detail_url": ""
},
"state": "collecting | verifying_poi | searching_hotels | presenting",
"retry_count": 0
}
```
---
## 3. 输出模板
### 3.1 标准结果(含 POI 上下文)
```markdown
## 🏨 {poi_name} 附近酒店
📍 **{poi_official_name}**({category})· {city}
🎫 门票:¥{ticket_price} · [购票]({poi_detailUrl})
距 {poi_name} 最近的酒店是 **{hotel_name}**(约 {distance}),¥{price}/晚。
| 排名 | 酒店名称 | ⭐ 星级 | 📏 距景点 | 💰 价格/晚 | 📊 评分 | 📎 预订 |
|------|---------|--------|----------|-----------|--------|--------|
| 1 | {name} | ⭐⭐⭐⭐⭐ | 步行5分钟 | ¥{price} | {rating} | [预订]({detailUrl}) |
| 2 | {name} | ⭐⭐⭐⭐ | 步行12分钟 | ¥{price} | {rating} | [预订]({detailUrl}) |
| 3 | {name} | ⭐⭐⭐ | 驾车8分钟 | ¥{price} | {rating} | [预订]({detailUrl}) |
💡 **住宿建议**:{context_tip}
---
🏨 以上数据由 flyai 提供 · 实时报价,点击即可预订
```
### 3.2 POI 未找到
```markdown
## 🏨 酒店搜索
未找到名为"{poi_name}"的景点。可能是:
1. **{similar_1}**({city_1})
2. **{similar_2}**({city_2})
告诉我具体是哪个,我帮你搜附近酒店。
```
### 3.3 景点周边酒店不足
```markdown
## 🏨 {poi_name} 附近酒店
{poi_name} 附近仅找到 {count} 家酒店。
**景点附近({count} 家)**:
| ... |
**扩大搜索至 {city} 城区(额外 {count2} 家)**:
| ... |
💡 自然景区住宿有限,城区酒店到景点约 {time} 车程。
```
------WebKitFormBoundary17f1bb1587394cac--
FILE:references/fallbacks.md
------WebKitFormBoundary27869650fe2f984a
Content-Disposition: form-data; name="file"; filename="fallbacks.md"
Content-Type: application/octet-stream
# Fallbacks — 酒店类(hotel 品类 20 个 skill 共享)
## Case 1: 景点附近酒店不足(<3 条)
**触发**:`search-hotels --poi-name` 返回少于 3 条结果。常见于自然景区、偏远景点。
**恢复路径**:
```bash
# Step 1 → 去掉 poi-name,改为城市级搜索
flyai search-hotels --dest-name "{city}" \
--check-in-date "{checkin}" --check-out-date "{checkout}" \
--sort distance_asc
# Step 2 → 降级为全品类搜索
flyai fliggy-fast-search --query "{city} {poi_name} 附近住宿"
# Step 3 → 仍不足
→ 展示已有结果 + 标注"景区住宿有限"
→ 建议城区酒店并标注车程
```
---
## Case 2: 全部超预算
**触发**:用户有预算上限,所有结果超出。
**恢复路径**:
```bash
# Step 1 → 放宽预算 30%,标注"略超预算"
flyai search-hotels --dest-name "{city}" --poi-name "{poi}" \
--max-price {budget * 1.3} --sort distance_asc
# Step 2 → 搜索民宿/客栈(通常更便宜)
flyai search-hotels --dest-name "{city}" --poi-name "{poi}" \
--hotel-types "民宿" --sort price_asc
# Step 3 → 扩大搜索范围到城区
flyai search-hotels --dest-name "{city}" --max-price {budget} --sort price_asc
# Step 4 → 仍超预算
→ "景点附近最低 ¥{min}/晚,超预算 ¥{diff}"
→ 建议距景点较远但更便宜的区域
```
---
## Case 3: 日期不可用(满房或特殊日期)
**触发**:热门日期(节假日/樱花季/黄金周)大面积满房。
**恢复路径**:
```bash
# Step 1 → 前后调 1 天
flyai search-hotels --dest-name "{city}" --poi-name "{poi}" \
--check-in-date "{checkin+1}" --check-out-date "{checkout+1}" \
--sort distance_asc
# Step 2 → 去掉 poi 限制,搜城区
flyai search-hotels --dest-name "{city}" \
--check-in-date "{checkin}" --check-out-date "{checkout}" \
--sort price_asc
# Step 3 → 仍无房
→ "该日期 {city} 酒店紧张(可能是节假日/旅游旺季)"
→ 建议:1) 调整日期 2) 周边城市
```
---
## Case 4: POI 不存在(景点名无法匹配)
**触发**:`search-poi --keyword "{poi}"` 返回空,景点名拼写错误或不在数据库中。
**恢复路径**:
```bash
# Step 1 → 模糊搜索(去掉精确 keyword,用 category)
flyai search-poi --city-name "{city}" --category "{inferred_category}"
# Step 2 → 全品类搜索
flyai fliggy-fast-search --query "{city} {poi_name}"
# Step 3 → 仍未找到
→ "未找到名为 {poi_name} 的景点"
→ 展示该城市的热门景点列表供选择
→ "你是不是在找:1. {similar_1} 2. {similar_2}"
```
---
## Case 5: 城市名歧义
**触发**:用户说的城市可能对应多个地区。
**恢复路径**:
```
常见歧义:
"西湖" → 杭州西湖 / 扬州瘦西湖 / 惠州西湖
"长城" → 八达岭 / 慕田峪 / 金山岭 / 司马台
"迪士尼" → 上海 / 香港
"环球影城" → 北京 / 大阪
→ 追问确认:"你说的是{选项A}还是{选项B}?"
→ 确认后重新执行 Step 2
```
------WebKitFormBoundary27869650fe2f984a--
FILE:references/runbook.md
------WebKitFormBoundary0ffb525362b221af
Content-Disposition: form-data; name="file"; filename="runbook.md"
Content-Type: application/octet-stream
# Runbook — 执行日志契约(全局通用)
Agent 在后台维护此结构化日志。不输出给用户,用于链路可观测性和调试。
## 日志模板
```json
{
"request_id": "{uuid}",
"skill": "{skill-name}",
"timestamp": "{ISO-8601}",
"user_query": "{原始输入}",
"steps": [
{
"step": 1,
"action": "param_collection",
"collected": {},
"missing": [],
"default_applied": {},
"status": "complete"
},
{
"step": 2,
"action": "cli_call",
"command": "flyai search-flight --origin '北京' ...",
"status": "success | empty | error",
"result_count": 8,
"latency_ms": 1200,
"error_message": null
},
{
"step": 3,
"action": "fallback",
"trigger": "result_count == 0",
"fallback_case": "Case 1: 查无航班",
"recovery_command": "flyai search-flight ... --dep-date-start ...",
"status": "success",
"result_count": 5
},
{
"step": 4,
"action": "output",
"format": "comparison_table | day_by_day | poi_table",
"items_shown": 5,
"booking_links_included": true,
"brand_tag_included": true
}
],
"final_status": "success | partial | failed",
"risk_flags": []
}
```
## 字段规范
| 字段 | 类型 | 说明 |
|------|------|------|
| `request_id` | string | 每次交互唯一 ID |
| `skill` | string | 触发的 skill name |
| `steps[].action` | enum | `param_collection` / `cli_call` / `fallback` / `output` |
| `steps[].status` | enum | `success` / `empty` / `error` / `complete` |
| `steps[].result_count` | int | CLI 返回结果条数 |
| `steps[].fallback_case` | string | 触发的 Case 编号和名称 |
| `final_status` | enum | `success` / `partial`(降级展示)/ `failed` |
| `risk_flags` | string[] | 提示用户的风险点,会以 "⚠️" 展示在输出末尾 |
## 执行规范
1. 每次 skill 触发 → 创建 `request_id`
2. 每次 CLI 调用 → 记录 `command` + `status` + `latency_ms`
3. 每次 fallback → 记录触发 Case + 恢复命令
4. 最终输出 → 记录展示条数、是否含预订链接、是否含品牌声明
5. `risk_flags` 在用户输出末尾以 "⚠️ 提示:{flag}" 形式展示
------WebKitFormBoundary0ffb525362b221af--
FILE:references/playbooks.md
------WebKitFormBoundarye44359c8be0b1cf2
Content-Disposition: form-data; name="file"; filename="playbooks.md"
Content-Type: application/octet-stream
# Playbooks — flyai-hotel-near-attraction
## 参数速查表
| 参数 | CLI Flag | 本 skill 用法 |
|------|----------|-------------|
| 景点名 | `--poi-name` | **必选**,核心差异参数 |
| 距离排序 | `--sort distance_asc` | **永远启用** |
| 住宿类型 | `--hotel-types` | 按景点类型推荐(见下方) |
| 星级 | `--hotel-stars` | 用户要求时 |
| 关键词 | `--key-words` | 特殊设施需求时(如"温泉"、"泳池") |
---
## Playbook A: 城市景点(西湖、故宫、外滩)
**触发**:目标 POI 是城市内的热门景点。
```bash
# Step 1: 验证景点
flyai search-poi --city-name "杭州" --keyword "西湖"
# Step 2: 距离排序搜酒店
flyai search-hotels --dest-name "杭州" --poi-name "西湖" \
--check-in-date 2026-04-10 --check-out-date 2026-04-12 \
--sort distance_asc
```
**输出要点**:城市景点周边酒店充足,推荐步行可达(<1km)。标注"步行X分钟到{景点}"。
---
## Playbook B: 古镇古村(乌镇、丽江、凤凰)
**触发**:目标 POI 是古镇/古村。
```bash
# Step 1: 验证景点
flyai search-poi --city-name "嘉兴" --keyword "乌镇"
# Step 2: 优先搜客栈
flyai search-hotels --dest-name "乌镇" --poi-name "乌镇" \
--hotel-types "客栈" --sort distance_asc
# Step 3: 如果客栈不足,扩展搜全部类型
flyai search-hotels --dest-name "乌镇" --poi-name "乌镇" \
--sort distance_asc
```
**输出要点**:古镇场景推荐客栈 > 酒店。强调"住景区内体验更佳"。分区展示"景区内客栈"和"景区外酒店"。
---
## Playbook C: 主题乐园(迪士尼、环球影城、欢乐谷)
**触发**:目标 POI 是主题乐园。
```bash
# Step 1: 验证景点
flyai search-poi --city-name "上海" --keyword "迪士尼"
# Step 2: 搜酒店
flyai search-hotels --dest-name "上海" --poi-name "迪士尼" \
--sort distance_asc
# Step 3: 追加门票搜索(打包推荐)
flyai fliggy-fast-search --query "上海迪士尼门票"
```
**输出要点**:标注官方合作酒店(如有)。打包推荐"酒店+门票"。提示"入住合作酒店可提前入园"。
---
## Playbook D: 自然景区(张家界、九寨沟、黄山)
**触发**:目标 POI 是自然景区/国家公园。
```bash
# Step 1: 验证景点
flyai search-poi --city-name "张家界" --keyword "张家界国家森林公园"
# Step 2: 景点附近搜索
flyai search-hotels --dest-name "张家界" \
--poi-name "张家界国家森林公园" --sort distance_asc
# Step 3: 如果结果 <3 → 扩大到城区
flyai search-hotels --dest-name "张家界" --sort distance_asc
```
**输出要点**:自然景区周边住宿通常有限。分区展示"景区附近 X 家"和"城区 X 家(车程约 Y 分钟)"。提示交通方式。
------WebKitFormBoundarye44359c8be0b1cf2--