@flydocs/cli 0.5.0-beta.7 → 0.5.0-beta.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -15,7 +15,7 @@ var CLI_VERSION, CLI_NAME, PACKAGE_NAME;
15
15
  var init_constants = __esm({
16
16
  "src/lib/constants.ts"() {
17
17
  "use strict";
18
- CLI_VERSION = "0.5.0-beta.7";
18
+ CLI_VERSION = "0.5.0-beta.8";
19
19
  CLI_NAME = "flydocs";
20
20
  PACKAGE_NAME = "@flydocs/cli";
21
21
  }
@@ -371,6 +371,16 @@ async function copyCursorRules(targetDir) {
371
371
  await copyFile(mechRule, join4(rulesDir, "flydocs-mechanism.mdc"));
372
372
  }
373
373
  }
374
+ const context7Rule = join4(
375
+ targetDir,
376
+ ".claude",
377
+ "skills",
378
+ "flydocs-context7",
379
+ "cursor-rule.mdc"
380
+ );
381
+ if (await pathExists(context7Rule)) {
382
+ await copyFile(context7Rule, join4(rulesDir, "flydocs-context7.mdc"));
383
+ }
374
384
  }
375
385
  var OWNED_SKILLS, MECHANISM_SKILLS;
376
386
  var init_skills = __esm({
@@ -381,7 +391,8 @@ var init_skills = __esm({
381
391
  "flydocs-workflow",
382
392
  "flydocs-figma",
383
393
  "flydocs-estimates",
384
- "flydocs-context-graph"
394
+ "flydocs-context-graph",
395
+ "flydocs-context7"
385
396
  ];
386
397
  MECHANISM_SKILLS = {
387
398
  local: "flydocs-local",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flydocs/cli",
3
- "version": "0.5.0-beta.7",
3
+ "version": "0.5.0-beta.8",
4
4
  "type": "module",
5
5
  "description": "FlyDocs AI CLI — install, setup, and manage FlyDocs projects",
6
6
  "bin": {
@@ -116,6 +116,7 @@ Consult the relevant skill BEFORE writing code or making workflow decisions.
116
116
  | Skill | Triggers | Entry |
117
117
  | ----------------- | ----------------------------------------------------------------------------------------------------------------------- | ----------------------------------------- |
118
118
  | flydocs-cloud | create issue, transition, comment, list issues, assign, update description, update issue, project update, Linear, cloud | .claude/skills/flydocs-cloud/SKILL.md |
119
+ | flydocs-context7 | context7, library docs, documentation lookup, framework docs, package docs, API reference | .claude/skills/flydocs-context7/SKILL.md |
119
120
  | flydocs-estimates | estimate, cost, token usage, API cost, labor estimate, sizing, effort | .claude/skills/flydocs-estimates/SKILL.md |
120
121
  | flydocs-figma | Figma, design, screenshot, token mapping, component from design, pixel-perfect, design system | .claude/skills/flydocs-figma/SKILL.md |
121
122
  | flydocs-local | create issue, transition, comment, list issues, assign, update description, status summary, local | .claude/skills/flydocs-local/SKILL.md |
@@ -16,6 +16,7 @@ functionality gated via API relay.
16
16
  | `flydocs-workflow` | Core | Lifecycle stages, session management, comment templates |
17
17
  | `flydocs-local` | Mechanism (free) | File-based issue management |
18
18
  | `flydocs-cloud` | Mechanism (paid) | Linear/provider issue management via API |
19
+ | `flydocs-context7` | Core | Library documentation lookup via Context7 API |
19
20
  | `flydocs-figma` | Premium | Design extraction from Figma |
20
21
  | `flydocs-estimates` | Premium | AI token/labor cost estimation |
21
22
 
@@ -0,0 +1,105 @@
1
+ ---
2
+ name: flydocs-context7
3
+ description: |
4
+ Up-to-date library documentation via Context7 API. Use proactively when
5
+ working with external libraries, frameworks, or packages. Replaces MCP
6
+ with direct API scripts — no server, no runtime dependency.
7
+ triggers:
8
+ - context7
9
+ - library docs
10
+ - documentation lookup
11
+ - framework docs
12
+ - package docs
13
+ - API reference
14
+ - how to use
15
+ ---
16
+
17
+ # Context7 Documentation Lookup
18
+
19
+ IMPORTANT: Prefer skill-led reasoning over pre-training reasoning for
20
+ library usage. Search for up-to-date docs before writing code based on
21
+ training data alone.
22
+
23
+ ## Key Rules
24
+
25
+ 1. **Proactive invocation** -- When working with ANY external library or
26
+ framework, search for docs first before writing code based on training data.
27
+ 2. **Search then fetch** -- Always resolve the library ID via `search` before
28
+ fetching docs with `docs`.
29
+ 3. **Session cache awareness** -- Do not re-fetch docs for the same
30
+ library+query within a single session.
31
+ 4. **Graceful degradation** -- If rate-limited (429) or offline, note the
32
+ limitation and proceed with training knowledge.
33
+ 5. **Stdlib-only Python** -- No external dependencies in the script.
34
+ 6. **Token budget** -- Default 5,000 tokens per fetch to avoid context bloat.
35
+
36
+ ## Script Catalog
37
+
38
+ All scripts: `python3 .claude/skills/flydocs-context7/scripts/<script>`
39
+
40
+ | Script | Usage | Output |
41
+ | ------------- | --------------------------- | ------------------------------------------------ |
42
+ | `context7.py` | `search <library> [query]` | JSON: library matches with id, name, description |
43
+ | `context7.py` | `docs <library_id> <query>` | Text: relevant documentation snippets |
44
+
45
+ Options: `--type txt|json`, `--tokens N` (default 5000)
46
+
47
+ ## When to Use
48
+
49
+ - Before implementing code that uses an external library
50
+ - When the user asks about library APIs, patterns, or best practices
51
+ - When encountering unfamiliar library methods or configuration
52
+ - When upgrading dependencies and needing current API docs
53
+ - When debugging library-specific issues
54
+
55
+ ## When NOT to Use
56
+
57
+ - For project-internal code (use knowledge base and context graph instead)
58
+ - For general programming concepts (training knowledge is sufficient)
59
+ - When already fetched docs for the same library in this session
60
+
61
+ ## API Key (Optional)
62
+
63
+ - Works without a key (anonymous, ~1,000 calls/month)
64
+ - For higher limits, add `CONTEXT7_API_KEY=ctx7sk-xxx` to `.env`
65
+ - Free key available at context7.com/dashboard
66
+
67
+ ## Example Usage
68
+
69
+ ```bash
70
+ # Find the React library
71
+ python3 .claude/skills/flydocs-context7/scripts/context7.py search "react" "hooks"
72
+
73
+ # Fetch docs for React hooks
74
+ python3 .claude/skills/flydocs-context7/scripts/context7.py docs "/facebook/react" "useState useEffect hooks"
75
+
76
+ # Get Next.js App Router docs
77
+ python3 .claude/skills/flydocs-context7/scripts/context7.py search "next.js"
78
+ python3 .claude/skills/flydocs-context7/scripts/context7.py docs "/vercel/next.js" "app router middleware"
79
+
80
+ # Fetch with custom token budget
81
+ python3 .claude/skills/flydocs-context7/scripts/context7.py docs "/expressjs/express" "routing middleware" --tokens 8000
82
+
83
+ # Get output as JSON
84
+ python3 .claude/skills/flydocs-context7/scripts/context7.py search "prisma" --type json
85
+ ```
86
+
87
+ ## Typical Workflow
88
+
89
+ 1. **Identify the library** you need docs for (from import statements,
90
+ `package.json`, or the task at hand).
91
+ 2. **Search** to resolve the library ID:
92
+ ```bash
93
+ python3 .claude/skills/flydocs-context7/scripts/context7.py search "react-hook-form"
94
+ ```
95
+ 3. **Fetch docs** for the specific topic:
96
+ ```bash
97
+ python3 .claude/skills/flydocs-context7/scripts/context7.py docs "/react-hook-form/react-hook-form" "useForm validation"
98
+ ```
99
+ 4. **Apply** the retrieved documentation to your implementation.
100
+ 5. **Do not re-fetch** for the same library+query later in the session.
101
+
102
+ ## Related Skills
103
+
104
+ - `flydocs-context-graph` -- Project-internal knowledge navigation
105
+ - `flydocs-workflow` -- Development lifecycle and issue operations
@@ -0,0 +1,49 @@
1
+ ---
2
+ description: Context7 — look up library and framework documentation before writing code
3
+ alwaysApply: true
4
+ ---
5
+
6
+ <!-- Condensed from SKILL.md — update both when changing patterns -->
7
+
8
+ # FlyDocs Context7
9
+
10
+ Proactively look up library documentation via Context7 scripts before writing
11
+ code that uses external packages. Do not rely on training data for API details.
12
+
13
+ ## When to Use
14
+
15
+ - Installing or importing a library you haven't used in this session
16
+ - Unsure about API signatures, configuration options, or return types
17
+ - Framework-specific patterns (routing, data fetching, middleware, hooks)
18
+ - Resolving version-specific behavior or breaking changes
19
+
20
+ ## Scripts
21
+
22
+ ```bash
23
+ # Step 1: Search for the library
24
+ python3 .claude/skills/flydocs-context7/scripts/context7.py search "<library>" "[query]"
25
+
26
+ # Step 2: Fetch docs using the library ID from search results
27
+ python3 .claude/skills/flydocs-context7/scripts/context7.py docs "<library_id>" "<query>"
28
+ ```
29
+
30
+ ### Examples
31
+
32
+ React hooks:
33
+ ```bash
34
+ python3 .claude/skills/flydocs-context7/scripts/context7.py search "react" "hooks"
35
+ python3 .claude/skills/flydocs-context7/scripts/context7.py docs "/facebook/react" "hooks useState"
36
+ ```
37
+
38
+ Next.js App Router:
39
+ ```bash
40
+ python3 .claude/skills/flydocs-context7/scripts/context7.py search "next.js"
41
+ python3 .claude/skills/flydocs-context7/scripts/context7.py docs "/vercel/next.js" "app router middleware"
42
+ ```
43
+
44
+ ## Key Rules
45
+
46
+ - Always resolve the library ID first via `search` — do not guess the ID format
47
+ - Prefer Context7 docs over training data for API specifics
48
+ - If Context7 has no results or is rate-limited, fall back to web search
49
+ - Cache within a session — no need to re-fetch the same library docs repeatedly
@@ -0,0 +1,293 @@
1
+ #!/usr/bin/env python3
2
+ """Context7 API client for fetching library documentation.
3
+
4
+ Queries the Context7 REST API to search for libraries and retrieve
5
+ LLM-ready documentation. Replaces the Context7 MCP server with a
6
+ lightweight script that follows the FlyDocs mechanism pattern.
7
+
8
+ Usage:
9
+ python3 .claude/skills/flydocs-context7/scripts/context7.py \\
10
+ search <library_name> [query]
11
+
12
+ python3 .claude/skills/flydocs-context7/scripts/context7.py \\
13
+ docs <library_id> <query> [--type txt|json] [--tokens N]
14
+ """
15
+
16
+ import argparse
17
+ import json
18
+ import os
19
+ import sys
20
+ import urllib.error
21
+ import urllib.parse
22
+ import urllib.request
23
+ from pathlib import Path
24
+
25
+ BASE_URL = "https://context7.com/api/v2"
26
+ DEFAULT_TIMEOUT = 10
27
+ DEFAULT_TOKENS = 5000
28
+
29
+
30
+ # --- Helpers ---
31
+
32
+
33
+ def fail(message):
34
+ """Print error to stderr and exit 1."""
35
+ print(message, file=sys.stderr)
36
+ sys.exit(1)
37
+
38
+
39
+ def output_json(data):
40
+ """Print JSON to stdout."""
41
+ print(json.dumps(data, indent=2))
42
+
43
+
44
+ def find_project_root(start=None):
45
+ """Walk up from start (or script location) to find the directory containing .flydocs/."""
46
+ current = Path(start) if start else Path(__file__).resolve().parent
47
+ for parent in [current] + list(current.parents):
48
+ if (parent / ".flydocs").is_dir():
49
+ return parent
50
+ return None
51
+
52
+
53
+ def read_env_file(root):
54
+ """Read .env file at project root and return a dict of key=value pairs."""
55
+ env_path = root / ".env"
56
+ if not env_path.is_file():
57
+ return {}
58
+
59
+ env_vars = {}
60
+ try:
61
+ with open(env_path, "r", encoding="utf-8") as f:
62
+ for line in f:
63
+ line = line.strip()
64
+ # Skip empty lines and comments
65
+ if not line or line.startswith("#"):
66
+ continue
67
+ if "=" not in line:
68
+ continue
69
+ key, _, value = line.partition("=")
70
+ key = key.strip()
71
+ value = value.strip()
72
+ # Strip surrounding quotes if present
73
+ if len(value) >= 2 and value[0] == value[-1] and value[0] in ('"', "'"):
74
+ value = value[1:-1]
75
+ env_vars[key] = value
76
+ except OSError:
77
+ pass
78
+
79
+ return env_vars
80
+
81
+
82
+ def resolve_api_key(args_key):
83
+ """Resolve the API key from flag, env var, or .env file. Returns None if unavailable."""
84
+ # 1. Explicit flag
85
+ if args_key:
86
+ return args_key
87
+
88
+ # 2. Environment variable
89
+ env_key = os.environ.get("CONTEXT7_API_KEY")
90
+ if env_key:
91
+ return env_key
92
+
93
+ # 3. .env file at project root
94
+ root = find_project_root()
95
+ if root:
96
+ env_vars = read_env_file(root)
97
+ dotenv_key = env_vars.get("CONTEXT7_API_KEY")
98
+ if dotenv_key:
99
+ return dotenv_key
100
+
101
+ # 4. Anonymous (no key)
102
+ return None
103
+
104
+
105
+ def api_request(path, params, api_key=None):
106
+ """Make a GET request to the Context7 API and return parsed response data.
107
+
108
+ Handles HTTP errors, timeouts, and network failures with clear messages.
109
+ """
110
+ query_string = urllib.parse.urlencode(params)
111
+ url = f"{BASE_URL}/{path}?{query_string}"
112
+
113
+ request = urllib.request.Request(url)
114
+ request.add_header("User-Agent", "flydocs-context7/1.0")
115
+
116
+ if api_key:
117
+ request.add_header("Authorization", f"Bearer {api_key}")
118
+
119
+ try:
120
+ with urllib.request.urlopen(request, timeout=DEFAULT_TIMEOUT) as response:
121
+ body = response.read().decode("utf-8")
122
+ content_type = response.headers.get("Content-Type", "")
123
+ if "application/json" in content_type:
124
+ return json.loads(body)
125
+ return body
126
+ except urllib.error.HTTPError as e:
127
+ if e.code == 429:
128
+ fail("Rate limited by Context7 API. Wait a moment and try again.")
129
+ body_text = ""
130
+ try:
131
+ body_text = e.read().decode("utf-8", errors="replace")
132
+ except Exception:
133
+ pass
134
+ fail(f"Context7 API error (HTTP {e.code}): {e.reason}\n{body_text}".strip())
135
+ except urllib.error.URLError as e:
136
+ if "timed out" in str(e.reason).lower():
137
+ fail("Context7 API request timed out (10s). The service may be slow or unavailable.")
138
+ fail(f"Cannot reach Context7 API. Check your network connection.\nDetails: {e.reason}")
139
+ except OSError as e:
140
+ fail(f"Network error connecting to Context7 API: {e}")
141
+
142
+
143
+ # --- Commands ---
144
+
145
+
146
+ def cmd_search(args):
147
+ """Search for libraries by name and optional query."""
148
+ params = {"libraryName": args.library_name}
149
+ if args.query:
150
+ params["query"] = args.query
151
+
152
+ api_key = resolve_api_key(args.key)
153
+ data = api_request("libs/search", params, api_key=api_key)
154
+
155
+ # Normalize response — API wraps results in {"results": [...]}
156
+ if isinstance(data, dict) and "results" in data:
157
+ results = data["results"]
158
+ elif isinstance(data, list):
159
+ results = data
160
+ else:
161
+ results = []
162
+
163
+ if args.type == "json" or args.type is None:
164
+ # Default for search is JSON
165
+ compact = []
166
+ for lib in results:
167
+ compact.append({
168
+ "id": lib.get("id", ""),
169
+ "name": lib.get("title", lib.get("name", "")),
170
+ "description": lib.get("description", ""),
171
+ "trustScore": lib.get("trustScore", 0),
172
+ })
173
+ output_json(compact)
174
+ else:
175
+ # txt format for search — one line per result
176
+ for lib in results:
177
+ name = lib.get("title", lib.get("name", "unknown"))
178
+ lib_id = lib.get("id", "")
179
+ desc = lib.get("description", "")
180
+ score = lib.get("trustScore", 0)
181
+ print(f"{lib_id} {name} (trust: {score})")
182
+ if desc:
183
+ print(f" {desc}")
184
+ print()
185
+
186
+
187
+ def cmd_docs(args):
188
+ """Fetch documentation for a specific library."""
189
+ params = {
190
+ "libraryId": args.library_id,
191
+ "query": args.query,
192
+ }
193
+
194
+ output_type = args.type if args.type else "txt"
195
+ params["type"] = output_type
196
+
197
+ if args.tokens:
198
+ params["tokens"] = str(args.tokens)
199
+
200
+ api_key = resolve_api_key(args.key)
201
+ data = api_request("context", params, api_key=api_key)
202
+
203
+ if output_type == "json":
204
+ if isinstance(data, str):
205
+ # API returned text when we asked for JSON; wrap it
206
+ output_json({"content": data})
207
+ else:
208
+ output_json(data)
209
+ else:
210
+ # txt — print directly
211
+ if isinstance(data, str):
212
+ print(data)
213
+ elif isinstance(data, dict):
214
+ content = data.get("content", data.get("text", ""))
215
+ if content:
216
+ print(content)
217
+ else:
218
+ output_json(data)
219
+ else:
220
+ output_json(data)
221
+
222
+
223
+ # --- Main ---
224
+
225
+
226
+ def main():
227
+ parser = argparse.ArgumentParser(
228
+ description="Context7 API client — search libraries and fetch documentation"
229
+ )
230
+ parser.add_argument(
231
+ "--key", type=str, default=None,
232
+ help="API key override (default: CONTEXT7_API_KEY env var or .env file)"
233
+ )
234
+
235
+ subparsers = parser.add_subparsers(dest="command", required=True)
236
+
237
+ # search subcommand
238
+ search_parser = subparsers.add_parser(
239
+ "search",
240
+ help="Search for libraries by name"
241
+ )
242
+ search_parser.add_argument(
243
+ "library_name",
244
+ help="Library name to search for (e.g., 'react', 'next.js')"
245
+ )
246
+ search_parser.add_argument(
247
+ "query", nargs="?", default=None,
248
+ help="Optional search query to refine results"
249
+ )
250
+ search_parser.add_argument(
251
+ "--type", choices=["txt", "json"], default=None,
252
+ help="Output format (default: json for search)"
253
+ )
254
+ search_parser.add_argument(
255
+ "--tokens", type=int, default=DEFAULT_TOKENS,
256
+ help=f"Max tokens budget hint (default: {DEFAULT_TOKENS})"
257
+ )
258
+
259
+ # docs subcommand
260
+ docs_parser = subparsers.add_parser(
261
+ "docs",
262
+ help="Fetch documentation for a library"
263
+ )
264
+ docs_parser.add_argument(
265
+ "library_id",
266
+ help="Library ID from search results (e.g., '/vercel/next.js')"
267
+ )
268
+ docs_parser.add_argument(
269
+ "query",
270
+ help="Documentation query (e.g., 'server components', 'routing')"
271
+ )
272
+ docs_parser.add_argument(
273
+ "--type", choices=["txt", "json"], default=None,
274
+ help="Output format (default: txt for docs)"
275
+ )
276
+ docs_parser.add_argument(
277
+ "--tokens", type=int, default=DEFAULT_TOKENS,
278
+ help=f"Max tokens budget hint (default: {DEFAULT_TOKENS})"
279
+ )
280
+
281
+ args = parser.parse_args()
282
+
283
+ if args.command == "search":
284
+ cmd_search(args)
285
+ elif args.command == "docs":
286
+ cmd_docs(args)
287
+ else:
288
+ parser.print_help()
289
+ sys.exit(1)
290
+
291
+
292
+ if __name__ == "__main__":
293
+ main()
@@ -33,9 +33,17 @@ LINEAR_API_KEY=
33
33
  # OPTIONAL: Figma Access Token
34
34
  # ===========================================
35
35
  # Get from: Figma → Settings → Personal Access Tokens
36
- # Only needed if using Figma MCP for design integration
36
+ # Only needed if using the flydocs-figma skill for design integration
37
37
  FIGMA_ACCESS_TOKEN=
38
38
 
39
+ # ===========================================
40
+ # OPTIONAL: Context7 API Key
41
+ # ===========================================
42
+ # Enables higher rate limits for library documentation lookup
43
+ # Get from: context7.com/dashboard (free account)
44
+ # Works without a key at lower rate limits (~1,000 calls/month)
45
+ CONTEXT7_API_KEY=
46
+
39
47
  # ===========================================
40
48
  # NOTE: Team ID and Project ID are discovered automatically
41
49
  # ===========================================
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.5.0-beta.7",
2
+ "version": "0.5.0-beta.8",
3
3
  "sourceRepo": "github.com/plastrlab/flydocs-core",
4
4
  "tier": "local",
5
5
  "setupComplete": false,
@@ -21,7 +21,7 @@ import re
21
21
  # Pattern matches any flydocs skill scripts directory
22
22
  # Covers: flydocs-local, flydocs-cloud, flydocs-workflow, flydocs-context-graph
23
23
  APPROVED_PATTERN = re.compile(
24
- r'python3?\s+(?:["\']?(?:\$CLAUDE_PROJECT_DIR|\$\{CLAUDE_PROJECT_DIR\}|\.)["\']?/)?\.?claude/skills/flydocs-(?:local|cloud|workflow|context-graph)/scripts/\w+\.py'
24
+ r'python3?\s+(?:["\']?(?:\$CLAUDE_PROJECT_DIR|\$\{CLAUDE_PROJECT_DIR\}|\.)["\']?/)?\.?claude/skills/flydocs-(?:local|cloud|workflow|context-graph|context7)/scripts/\w+\.py'
25
25
  )
26
26
 
27
27
 
@@ -1 +1 @@
1
- 0.5.0-beta.7
1
+ 0.5.0-beta.8
@@ -95,6 +95,7 @@ Consult the relevant skill BEFORE writing code or making workflow decisions.
95
95
  | Skill | Triggers | Entry |
96
96
  | ----------------- | ----------------------------------------------------------------------------------------------------------------------- | ----------------------------------------- |
97
97
  | flydocs-cloud | create issue, transition, comment, list issues, assign, update description, update issue, project update, Linear, cloud | .claude/skills/flydocs-cloud/SKILL.md |
98
+ | flydocs-context7 | context7, library docs, documentation lookup, framework docs, package docs, API reference | .claude/skills/flydocs-context7/SKILL.md |
98
99
  | flydocs-estimates | estimate, cost, token usage, API cost, labor estimate, sizing, effort | .claude/skills/flydocs-estimates/SKILL.md |
99
100
  | flydocs-figma | Figma, design, screenshot, token mapping, component from design, pixel-perfect, design system | .claude/skills/flydocs-figma/SKILL.md |
100
101
  | flydocs-local | create issue, transition, comment, list issues, assign, update description, status summary, local | .claude/skills/flydocs-local/SKILL.md |
@@ -7,9 +7,62 @@ Versioning: [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  ---
9
9
 
10
+ ## [0.5.0-beta.8] — 2026-02-22
11
+
12
+ ### Added
13
+
14
+ - **Context7 documentation skill** (`flydocs-context7`) — stdlib-only Python script
15
+ that calls the Context7 REST API to fetch up-to-date library documentation.
16
+ Replaces the removed Context7 MCP with a skill+script pattern.
17
+ - `context7.py search <library> [query]` — resolve library name to Context7 ID
18
+ - `context7.py docs <library_id> <query>` — fetch relevant documentation snippets
19
+ - Works without API key (anonymous, ~1,000 calls/month); optional
20
+ `CONTEXT7_API_KEY` in `.env` for higher rate limits
21
+ - Auto-approved by hook for seamless agent invocation
22
+ - Cursor rule included for cross-IDE support
23
+ - **Context7 API key** in `.env.example` — optional configuration for higher rate limits
24
+
25
+ ### Fixed
26
+
27
+ - `.env.example` — corrected "Figma MCP" reference to "flydocs-figma skill"
28
+
29
+ ## [0.5.0-beta.7] — 2026-02-22
30
+
31
+ ### Removed
32
+
33
+ - **All MCP references** — removed `.cursor/mcp.json`, `prefer-scripts.py` hook,
34
+ MCP config preservation in update flow, MCP section in instructions template.
35
+ Skills fully replace MCPs as the FlyDocs architecture.
36
+ - **Phantom skills** — removed references to `implementation-flow`, `review-workflow`,
37
+ `spec-templates` skills that were never shipped.
38
+
39
+ ### Fixed
40
+
41
+ - **Command injection** (`connect.ts`) — replaced `execSync` subprocess with native
42
+ `fetch()` for Linear API key validation.
43
+ - **Version comparison** — pre-release versions (e.g. `0.5.0-beta.3`) now compare
44
+ correctly instead of returning NaN.
45
+ - **Auto-approve hook** — tightened regex to anchor script paths, preventing potential
46
+ pattern-matching bypasses.
47
+ - **Post-edit hook** — added path traversal validation using `os.path.realpath()`.
48
+ - **Post-install scripts** — switched from `execSync` to `execFileSync` for subprocess safety.
49
+
50
+ ### Changed
51
+
52
+ - **Stack detection** — now reads `flydocs/context/project.md` in addition to
53
+ `package.json` for declared stack frameworks.
54
+ - **Community skills on update** — filters already-installed skills before prompting.
55
+ - **Cloud exposure** — `.env.example` marked as cloud tier only, `flydocs/README.md`
56
+ rewritten as tier-generic, config defaults changed to `tier: "local"`.
57
+ - **Deprecated cleanup** — `.cursor/mcp.json` and `prefer-scripts.py` added to
58
+ deprecated files list for automatic cleanup on update.
59
+
60
+ ---
61
+
10
62
  ## [0.4.0] — 2026-02-18
11
63
 
12
64
  ### Added
65
+
13
66
  - **Context Graph skill** (`flydocs-context-graph`) — relationship-aware knowledge
14
67
  graph that connects skills, ADRs, issues, modules, and sessions. Implemented as
15
68
  ADR-006 across five phases:
@@ -32,12 +85,14 @@ Versioning: [Semantic Versioning](https://semver.org/).
32
85
  graph automatically.
33
86
 
34
87
  ### Changed
88
+
35
89
  - **Session wrap procedure** — `session.md` now includes a step to record session
36
90
  outcomes in the context graph via `graph_session.py`. Skips silently if not installed.
37
91
  - **Session staleness policy** — session nodes within 7 days get full weight, linear
38
92
  decay to 30 days, then excluded from context.
39
93
 
40
94
  ### Migration
95
+
41
96
  - **`.gitignore` update** — `flydocs/context/graph.json` is automatically added to
42
97
  `.gitignore` during update if missing. The graph is gitignored because it contains
43
98
  session-specific data and can be rebuilt from sources.
@@ -47,6 +102,7 @@ Versioning: [Semantic Versioning](https://semver.org/).
47
102
  ## [0.3.10] — 2026-02-17
48
103
 
49
104
  ### Fixed
105
+
50
106
  - **API null data crash** (FLY-178) — `flydocs_api.py` now normalizes `null` data
51
107
  responses to empty dict before returning. Fixes `AttributeError` crashes in all
52
108
  20+ scripts when Linear returns API errors. `create_issue.py` also retries without
@@ -65,6 +121,7 @@ Versioning: [Semantic Versioning](https://semver.org/).
65
121
  ## [0.3.9] — 2026-02-17
66
122
 
67
123
  ### Added
124
+
68
125
  - **Skill search and install CLI** (ENG-443) — `flydocs skills` subcommand with
69
126
  `search`, `add`, `remove`, and `list` operations. Search the curated community
70
127
  skills catalog, install from known names or GitHub repo references, and manage
@@ -81,6 +138,7 @@ Versioning: [Semantic Versioning](https://semver.org/).
81
138
  ## [0.3.8] — 2026-02-14
82
139
 
83
140
  ### Added
141
+
84
142
  - **`create_issue.py --description-file` and stdin** — both cloud and local tiers now
85
143
  accept `--description-file PATH` or piped stdin for issue descriptions. Eliminates
86
144
  the two-step create + update_description workaround for long descriptions.
@@ -92,6 +150,7 @@ Versioning: [Semantic Versioning](https://semver.org/).
92
150
  ## [0.3.7] — 2026-02-11
93
151
 
94
152
  ### Added
153
+
95
154
  - **Skill manifest generator** (ENG-442) — `generate_manifest.py` scans SKILL.md
96
155
  frontmatter and produces a compressed skills index table. Injected into CLAUDE.md
97
156
  and AGENTS.md between `<!-- flydocs:skills-manifest -->` markers. Bridges skill
@@ -104,12 +163,14 @@ Versioning: [Semantic Versioning](https://semver.org/).
104
163
  ## [0.3.6] — 2026-02-10
105
164
 
106
165
  ### Added
166
+
107
167
  - **Milestone, project, and dueDate in issue output** — `list_issues.py` now returns
108
168
  `milestone`, `milestoneId`, `milestoneSortOrder`, `project`, `projectId`, and `dueDate`
109
169
  for every issue. `get_issue.py` returns the same fields (minus `milestoneSortOrder`).
110
170
  Enables milestone-grouped dashboards and priority-based session planning.
111
171
 
112
172
  ### Changed
173
+
113
174
  - **Session start workflow rewritten** — `session.md` now instructs agents to group issues
114
175
  by milestone (in milestone order), identify the current milestone, suggest a starting point
115
176
  based on priority cascade (blocked → in-progress → due soon → highest priority in current
@@ -117,6 +178,7 @@ Versioning: [Semantic Versioning](https://semver.org/).
117
178
  the product scope.
118
179
 
119
180
  ### Fixed
181
+
120
182
  - **`create_milestone.py` missing projectId** — `ProjectMilestoneCreateInput` requires a
121
183
  `projectId`. Script now defaults to first `activeProject` from config, with `--project`
122
184
  flag to override.
@@ -126,10 +188,12 @@ Versioning: [Semantic Versioning](https://semver.org/).
126
188
  ## [0.3.5] — 2026-02-10
127
189
 
128
190
  ### Added
191
+
129
192
  - **`list_projects.py` product scope** (ENG-475) — now respects `workspace.activeProjects`
130
193
  config. `--all` bypasses product scope to show all team projects.
131
194
 
132
195
  ### Fixed
196
+
133
197
  - **`list_projects.py` 400 error** (ENG-474) — state filter was using nested
134
198
  `{type: {nin: [...]}}` instead of direct `StringComparator` `{nin: [...]}`.
135
199
  Both `--active` (started only) and default (excludes completed/canceled) now work.
@@ -143,6 +207,7 @@ Versioning: [Semantic Versioning](https://semver.org/).
143
207
  ## [0.3.4] — 2026-02-10
144
208
 
145
209
  ### Added
210
+
146
211
  - **`list_issues.py --milestone` filter** — filter issues by project milestone ID.
147
212
  Get milestone IDs from `list_milestones.py`, then pass to `list_issues.py --milestone <ID>`
148
213
  to see all issues within a specific milestone.
@@ -152,6 +217,7 @@ Versioning: [Semantic Versioning](https://semver.org/).
152
217
  ## [0.3.3] — 2026-02-10
153
218
 
154
219
  ### Fixed
220
+
155
221
  - **Shell escaping in `update_description.py`** — descriptions with apostrophes,
156
222
  parentheses, quotes, and other shell metacharacters no longer break when passed
157
223
  via `--text`. Scripts now accept stdin as input, allowing safe heredoc piping:
@@ -164,6 +230,7 @@ Versioning: [Semantic Versioning](https://semver.org/).
164
230
  ## [0.3.2] — 2026-02-09
165
231
 
166
232
  ### Fixed
233
+
167
234
  - **API connection reliability** — reduced socket timeout from 30s to 10s and increased
168
235
  max retries from 3 to 5. Resolves intermittent hangs caused by DNS returning unreachable
169
236
  Cloudflare edge IPs. Scripts now fail over to a working IP within seconds instead of
@@ -176,11 +243,13 @@ Versioning: [Semantic Versioning](https://semver.org/).
176
243
  ## [0.3.1] — 2026-02-08
177
244
 
178
245
  ### Fixed
246
+
179
247
  - **`list_issues.py` product scope** — scoping via `activeProjects` and `product.labelIds`
180
248
  now applies regardless of `--active` or `--status` flags. Previously, these flags
181
249
  bypassed product scope entirely, returning all team issues.
182
250
 
183
251
  ### Added
252
+
184
253
  - **`build_product_scope()` API helper** — new method on `FlyDocsClient` implements the
185
254
  product scope cascade: `activeProjects` → `product.labelIds` → team-wide.
186
255
  - **Multiple `activeProjects` support** — `list_issues.py` now uses OR logic when
@@ -193,6 +262,7 @@ Versioning: [Semantic Versioning](https://semver.org/).
193
262
  ## [0.3.0] — 2026-02-08
194
263
 
195
264
  ### Added
265
+
196
266
  - **`update_issue.py` bulk update script** — set multiple fields (priority, estimate,
197
267
  assignee, state, description, comment) in a single API call instead of separate scripts.
198
268
  - **`list_issues.py --active` flag** — returns all non-terminal issues (excludes Done,
@@ -204,12 +274,14 @@ Versioning: [Semantic Versioning](https://semver.org/).
204
274
  cached within each script invocation to reduce redundant API calls.
205
275
 
206
276
  ### Changed
277
+
207
278
  - **`transition.py` optimized** — combined state update and cycle assignment into a
208
279
  single `issueUpdate` mutation (was two separate calls for IMPLEMENTING transitions).
209
280
  - **Session start efficiency** — single `list_issues.py --active` call replaces
210
281
  per-status queries. Issues grouped by status in response.
211
282
 
212
283
  ### Removed
284
+
213
285
  - **`status_summary.py`** — retired from cloud mechanism. Use `list_issues.py --active`
214
286
  and group results by the status field instead.
215
287
 
@@ -218,6 +290,7 @@ Versioning: [Semantic Versioning](https://semver.org/).
218
290
  ## [0.2.1] — 2026-02-07
219
291
 
220
292
  ### Fixed
293
+
221
294
  - **Commands not fully populating** — changed from additive `cp` to clear-then-copy
222
295
  for `.claude/commands/` and `.cursor/commands/` directories.
223
296
  - **`docflow-core.mdc` not cleaned up** — added to deprecated cursor rules list.
@@ -227,6 +300,7 @@ Versioning: [Semantic Versioning](https://semver.org/).
227
300
  synced with version file.
228
301
 
229
302
  ### Added
303
+
230
304
  - **`--force` flag** — force update even when versions match.
231
305
  - **Old cursor rule directories and commands** added to deprecated cleanup.
232
306
 
@@ -235,6 +309,7 @@ Versioning: [Semantic Versioning](https://semver.org/).
235
309
  ## [0.2.0] — 2026-02-06
236
310
 
237
311
  ### Added
312
+
238
313
  - **Scenario-aware setup command** — `/flydocs-setup` rewritten as a comprehensive
239
314
  agent prompt handling three scenarios: New Project, DocFlow Migration, FlyDocs Update.
240
315
  Includes proactive repo scanning for PRDs and existing documentation.
@@ -247,10 +322,12 @@ Versioning: [Semantic Versioning](https://semver.org/).
247
322
  pre-v1.0 artifacts: old skills, rules, hooks, and cursor rules.
248
323
 
249
324
  ### Changed
325
+
250
326
  - **Version file synced with manifest** — `.flydocs/version` now matches
251
327
  `manifest.json` version field (was out of sync in 0.1.0).
252
328
 
253
329
  ### Removed
330
+
254
331
  - Orphaned hook scripts: `session-end.py`, `linear-auto-approve.py`
255
332
 
256
333
  ---
@@ -258,6 +335,7 @@ Versioning: [Semantic Versioning](https://semver.org/).
258
335
  ## [0.1.0] — 2026-01-15
259
336
 
260
337
  ### Added
338
+
261
339
  - Initial release of FlyDocs Core
262
340
  - Workflow skill (`flydocs-workflow`) with full lifecycle stages
263
341
  - Mechanism skills: `flydocs-cloud` (Linear API) and `flydocs-local` (file-based)
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.5.0-beta.7",
2
+ "version": "0.5.0-beta.8",
3
3
  "description": "FlyDocs Core - Manifest of all managed files",
4
4
  "repository": "github.com/plastrlab/flydocs-core",
5
5
 
@@ -18,6 +18,7 @@
18
18
  ".claude/skills/flydocs-figma",
19
19
  ".claude/skills/flydocs-estimates",
20
20
  ".claude/skills/flydocs-context-graph",
21
+ ".claude/skills/flydocs-context7",
21
22
  ".flydocs/scripts",
22
23
  ".cursor/agents"
23
24
  ]
@@ -145,7 +146,8 @@
145
146
  "flydocs-local": ["SKILL.md", "cursor-rule.mdc", "scripts/"],
146
147
  "flydocs-figma": ["SKILL.md", "references/"],
147
148
  "flydocs-estimates": ["SKILL.md", "references/"],
148
- "flydocs-context-graph": ["SKILL.md", "schema.md", "scripts/"]
149
+ "flydocs-context-graph": ["SKILL.md", "schema.md", "scripts/"],
150
+ "flydocs-context7": ["SKILL.md", "cursor-rule.mdc", "scripts/"]
149
151
  }
150
152
  },
151
153
  ".cursor": {