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

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.9";
19
19
  CLI_NAME = "flydocs";
20
20
  PACKAGE_NAME = "@flydocs/cli";
21
21
  }
@@ -136,6 +136,9 @@ var init_template = __esm({
136
136
 
137
137
  // src/lib/ui.ts
138
138
  import pc2 from "picocolors";
139
+ function hyperlink(text3, url) {
140
+ return `\x1B]8;;${url}\x1B\\${text3}\x1B]8;;\x1B\\`;
141
+ }
139
142
  function printStatus(message) {
140
143
  console.log(`${pc2.green("\u2714")} ${message}`);
141
144
  }
@@ -162,10 +165,10 @@ function printBanner(version) {
162
165
  console.log(` ${pinkBlock12}`);
163
166
  console.log(` ${pinkBlock4}`);
164
167
  console.log(
165
- ` ${pinkBlock4} ${purpleBlock12} ${bold("Fly")}${bold("Docs")} ${bold("Core")}`
168
+ ` ${pinkBlock4} ${purpleBlock12} ${bold("FlyDocs")} ${dim("(Beta)")}`
166
169
  );
167
170
  console.log(
168
- ` ${purpleBlock12} ${dim("Context-as-a-Service Platform Built for Engineering at Altitude")}`
171
+ ` ${purpleBlock12} ${dim("Spec-Driven Context That Helps Engineers Fly")}`
169
172
  );
170
173
  console.log(` ${purpleBlock4}`);
171
174
  console.log(` ${purpleBlock4} ${dim(`v${version}`)}`);
@@ -189,17 +192,16 @@ function printCompletionBox(title, lines) {
189
192
  }
190
193
  function printBetaCta() {
191
194
  const dim = pc2.dim;
195
+ const url = "https://www.flydocs.ai?utm_source=cli&utm_medium=install&utm_campaign=beta";
192
196
  console.log(
193
197
  dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")
194
198
  );
195
199
  console.log();
196
200
  console.log(` ${pc2.bold("Join the FlyDocs Closed Beta")}`);
197
201
  console.log(
198
- ` ${dim("Early access to cloud features, priority support, and more.")}`
199
- );
200
- console.log(
201
- ` ${pc2.cyan("https://www.flydocs.ai?utm_source=cli&utm_medium=install&utm_campaign=beta")}`
202
+ ` ${dim("Early access to cloud features, web portal, and more.")}`
202
203
  );
204
+ console.log(` ${pc2.cyan(hyperlink("flydocs.ai", url))}`);
203
205
  console.log();
204
206
  }
205
207
  var init_ui = __esm({
@@ -371,6 +373,16 @@ async function copyCursorRules(targetDir) {
371
373
  await copyFile(mechRule, join4(rulesDir, "flydocs-mechanism.mdc"));
372
374
  }
373
375
  }
376
+ const context7Rule = join4(
377
+ targetDir,
378
+ ".claude",
379
+ "skills",
380
+ "flydocs-context7",
381
+ "cursor-rule.mdc"
382
+ );
383
+ if (await pathExists(context7Rule)) {
384
+ await copyFile(context7Rule, join4(rulesDir, "flydocs-context7.mdc"));
385
+ }
374
386
  }
375
387
  var OWNED_SKILLS, MECHANISM_SKILLS;
376
388
  var init_skills = __esm({
@@ -381,7 +393,8 @@ var init_skills = __esm({
381
393
  "flydocs-workflow",
382
394
  "flydocs-figma",
383
395
  "flydocs-estimates",
384
- "flydocs-context-graph"
396
+ "flydocs-context-graph",
397
+ "flydocs-context7"
385
398
  ];
386
399
  MECHANISM_SKILLS = {
387
400
  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.9",
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.9",
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.9
@@ -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,73 @@ Versioning: [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  ---
9
9
 
10
+ ## [0.5.0-beta.9] — 2026-02-22
11
+
12
+ ### Changed
13
+
14
+ - **Banner copy** — title changed from "FlyDocs Core" to "FlyDocs (Beta)",
15
+ subtitle changed to "Spec-Driven Context That Helps Engineers Fly"
16
+ - **Beta CTA** — "priority support" replaced with "web portal", URL now
17
+ renders as clickable `flydocs.ai` hyperlink via OSC 8 terminal escape
18
+
19
+ ---
20
+
21
+ ## [0.5.0-beta.8] — 2026-02-22
22
+
23
+ ### Added
24
+
25
+ - **Context7 documentation skill** (`flydocs-context7`) — stdlib-only Python script
26
+ that calls the Context7 REST API to fetch up-to-date library documentation.
27
+ Replaces the removed Context7 MCP with a skill+script pattern.
28
+ - `context7.py search <library> [query]` — resolve library name to Context7 ID
29
+ - `context7.py docs <library_id> <query>` — fetch relevant documentation snippets
30
+ - Works without API key (anonymous, ~1,000 calls/month); optional
31
+ `CONTEXT7_API_KEY` in `.env` for higher rate limits
32
+ - Auto-approved by hook for seamless agent invocation
33
+ - Cursor rule included for cross-IDE support
34
+ - **Context7 API key** in `.env.example` — optional configuration for higher rate limits
35
+
36
+ ### Fixed
37
+
38
+ - `.env.example` — corrected "Figma MCP" reference to "flydocs-figma skill"
39
+
40
+ ## [0.5.0-beta.7] — 2026-02-22
41
+
42
+ ### Removed
43
+
44
+ - **All MCP references** — removed `.cursor/mcp.json`, `prefer-scripts.py` hook,
45
+ MCP config preservation in update flow, MCP section in instructions template.
46
+ Skills fully replace MCPs as the FlyDocs architecture.
47
+ - **Phantom skills** — removed references to `implementation-flow`, `review-workflow`,
48
+ `spec-templates` skills that were never shipped.
49
+
50
+ ### Fixed
51
+
52
+ - **Command injection** (`connect.ts`) — replaced `execSync` subprocess with native
53
+ `fetch()` for Linear API key validation.
54
+ - **Version comparison** — pre-release versions (e.g. `0.5.0-beta.3`) now compare
55
+ correctly instead of returning NaN.
56
+ - **Auto-approve hook** — tightened regex to anchor script paths, preventing potential
57
+ pattern-matching bypasses.
58
+ - **Post-edit hook** — added path traversal validation using `os.path.realpath()`.
59
+ - **Post-install scripts** — switched from `execSync` to `execFileSync` for subprocess safety.
60
+
61
+ ### Changed
62
+
63
+ - **Stack detection** — now reads `flydocs/context/project.md` in addition to
64
+ `package.json` for declared stack frameworks.
65
+ - **Community skills on update** — filters already-installed skills before prompting.
66
+ - **Cloud exposure** — `.env.example` marked as cloud tier only, `flydocs/README.md`
67
+ rewritten as tier-generic, config defaults changed to `tier: "local"`.
68
+ - **Deprecated cleanup** — `.cursor/mcp.json` and `prefer-scripts.py` added to
69
+ deprecated files list for automatic cleanup on update.
70
+
71
+ ---
72
+
10
73
  ## [0.4.0] — 2026-02-18
11
74
 
12
75
  ### Added
76
+
13
77
  - **Context Graph skill** (`flydocs-context-graph`) — relationship-aware knowledge
14
78
  graph that connects skills, ADRs, issues, modules, and sessions. Implemented as
15
79
  ADR-006 across five phases:
@@ -32,12 +96,14 @@ Versioning: [Semantic Versioning](https://semver.org/).
32
96
  graph automatically.
33
97
 
34
98
  ### Changed
99
+
35
100
  - **Session wrap procedure** — `session.md` now includes a step to record session
36
101
  outcomes in the context graph via `graph_session.py`. Skips silently if not installed.
37
102
  - **Session staleness policy** — session nodes within 7 days get full weight, linear
38
103
  decay to 30 days, then excluded from context.
39
104
 
40
105
  ### Migration
106
+
41
107
  - **`.gitignore` update** — `flydocs/context/graph.json` is automatically added to
42
108
  `.gitignore` during update if missing. The graph is gitignored because it contains
43
109
  session-specific data and can be rebuilt from sources.
@@ -47,6 +113,7 @@ Versioning: [Semantic Versioning](https://semver.org/).
47
113
  ## [0.3.10] — 2026-02-17
48
114
 
49
115
  ### Fixed
116
+
50
117
  - **API null data crash** (FLY-178) — `flydocs_api.py` now normalizes `null` data
51
118
  responses to empty dict before returning. Fixes `AttributeError` crashes in all
52
119
  20+ scripts when Linear returns API errors. `create_issue.py` also retries without
@@ -65,6 +132,7 @@ Versioning: [Semantic Versioning](https://semver.org/).
65
132
  ## [0.3.9] — 2026-02-17
66
133
 
67
134
  ### Added
135
+
68
136
  - **Skill search and install CLI** (ENG-443) — `flydocs skills` subcommand with
69
137
  `search`, `add`, `remove`, and `list` operations. Search the curated community
70
138
  skills catalog, install from known names or GitHub repo references, and manage
@@ -81,6 +149,7 @@ Versioning: [Semantic Versioning](https://semver.org/).
81
149
  ## [0.3.8] — 2026-02-14
82
150
 
83
151
  ### Added
152
+
84
153
  - **`create_issue.py --description-file` and stdin** — both cloud and local tiers now
85
154
  accept `--description-file PATH` or piped stdin for issue descriptions. Eliminates
86
155
  the two-step create + update_description workaround for long descriptions.
@@ -92,6 +161,7 @@ Versioning: [Semantic Versioning](https://semver.org/).
92
161
  ## [0.3.7] — 2026-02-11
93
162
 
94
163
  ### Added
164
+
95
165
  - **Skill manifest generator** (ENG-442) — `generate_manifest.py` scans SKILL.md
96
166
  frontmatter and produces a compressed skills index table. Injected into CLAUDE.md
97
167
  and AGENTS.md between `<!-- flydocs:skills-manifest -->` markers. Bridges skill
@@ -104,12 +174,14 @@ Versioning: [Semantic Versioning](https://semver.org/).
104
174
  ## [0.3.6] — 2026-02-10
105
175
 
106
176
  ### Added
177
+
107
178
  - **Milestone, project, and dueDate in issue output** — `list_issues.py` now returns
108
179
  `milestone`, `milestoneId`, `milestoneSortOrder`, `project`, `projectId`, and `dueDate`
109
180
  for every issue. `get_issue.py` returns the same fields (minus `milestoneSortOrder`).
110
181
  Enables milestone-grouped dashboards and priority-based session planning.
111
182
 
112
183
  ### Changed
184
+
113
185
  - **Session start workflow rewritten** — `session.md` now instructs agents to group issues
114
186
  by milestone (in milestone order), identify the current milestone, suggest a starting point
115
187
  based on priority cascade (blocked → in-progress → due soon → highest priority in current
@@ -117,6 +189,7 @@ Versioning: [Semantic Versioning](https://semver.org/).
117
189
  the product scope.
118
190
 
119
191
  ### Fixed
192
+
120
193
  - **`create_milestone.py` missing projectId** — `ProjectMilestoneCreateInput` requires a
121
194
  `projectId`. Script now defaults to first `activeProject` from config, with `--project`
122
195
  flag to override.
@@ -126,10 +199,12 @@ Versioning: [Semantic Versioning](https://semver.org/).
126
199
  ## [0.3.5] — 2026-02-10
127
200
 
128
201
  ### Added
202
+
129
203
  - **`list_projects.py` product scope** (ENG-475) — now respects `workspace.activeProjects`
130
204
  config. `--all` bypasses product scope to show all team projects.
131
205
 
132
206
  ### Fixed
207
+
133
208
  - **`list_projects.py` 400 error** (ENG-474) — state filter was using nested
134
209
  `{type: {nin: [...]}}` instead of direct `StringComparator` `{nin: [...]}`.
135
210
  Both `--active` (started only) and default (excludes completed/canceled) now work.
@@ -143,6 +218,7 @@ Versioning: [Semantic Versioning](https://semver.org/).
143
218
  ## [0.3.4] — 2026-02-10
144
219
 
145
220
  ### Added
221
+
146
222
  - **`list_issues.py --milestone` filter** — filter issues by project milestone ID.
147
223
  Get milestone IDs from `list_milestones.py`, then pass to `list_issues.py --milestone <ID>`
148
224
  to see all issues within a specific milestone.
@@ -152,6 +228,7 @@ Versioning: [Semantic Versioning](https://semver.org/).
152
228
  ## [0.3.3] — 2026-02-10
153
229
 
154
230
  ### Fixed
231
+
155
232
  - **Shell escaping in `update_description.py`** — descriptions with apostrophes,
156
233
  parentheses, quotes, and other shell metacharacters no longer break when passed
157
234
  via `--text`. Scripts now accept stdin as input, allowing safe heredoc piping:
@@ -164,6 +241,7 @@ Versioning: [Semantic Versioning](https://semver.org/).
164
241
  ## [0.3.2] — 2026-02-09
165
242
 
166
243
  ### Fixed
244
+
167
245
  - **API connection reliability** — reduced socket timeout from 30s to 10s and increased
168
246
  max retries from 3 to 5. Resolves intermittent hangs caused by DNS returning unreachable
169
247
  Cloudflare edge IPs. Scripts now fail over to a working IP within seconds instead of
@@ -176,11 +254,13 @@ Versioning: [Semantic Versioning](https://semver.org/).
176
254
  ## [0.3.1] — 2026-02-08
177
255
 
178
256
  ### Fixed
257
+
179
258
  - **`list_issues.py` product scope** — scoping via `activeProjects` and `product.labelIds`
180
259
  now applies regardless of `--active` or `--status` flags. Previously, these flags
181
260
  bypassed product scope entirely, returning all team issues.
182
261
 
183
262
  ### Added
263
+
184
264
  - **`build_product_scope()` API helper** — new method on `FlyDocsClient` implements the
185
265
  product scope cascade: `activeProjects` → `product.labelIds` → team-wide.
186
266
  - **Multiple `activeProjects` support** — `list_issues.py` now uses OR logic when
@@ -193,6 +273,7 @@ Versioning: [Semantic Versioning](https://semver.org/).
193
273
  ## [0.3.0] — 2026-02-08
194
274
 
195
275
  ### Added
276
+
196
277
  - **`update_issue.py` bulk update script** — set multiple fields (priority, estimate,
197
278
  assignee, state, description, comment) in a single API call instead of separate scripts.
198
279
  - **`list_issues.py --active` flag** — returns all non-terminal issues (excludes Done,
@@ -204,12 +285,14 @@ Versioning: [Semantic Versioning](https://semver.org/).
204
285
  cached within each script invocation to reduce redundant API calls.
205
286
 
206
287
  ### Changed
288
+
207
289
  - **`transition.py` optimized** — combined state update and cycle assignment into a
208
290
  single `issueUpdate` mutation (was two separate calls for IMPLEMENTING transitions).
209
291
  - **Session start efficiency** — single `list_issues.py --active` call replaces
210
292
  per-status queries. Issues grouped by status in response.
211
293
 
212
294
  ### Removed
295
+
213
296
  - **`status_summary.py`** — retired from cloud mechanism. Use `list_issues.py --active`
214
297
  and group results by the status field instead.
215
298
 
@@ -218,6 +301,7 @@ Versioning: [Semantic Versioning](https://semver.org/).
218
301
  ## [0.2.1] — 2026-02-07
219
302
 
220
303
  ### Fixed
304
+
221
305
  - **Commands not fully populating** — changed from additive `cp` to clear-then-copy
222
306
  for `.claude/commands/` and `.cursor/commands/` directories.
223
307
  - **`docflow-core.mdc` not cleaned up** — added to deprecated cursor rules list.
@@ -227,6 +311,7 @@ Versioning: [Semantic Versioning](https://semver.org/).
227
311
  synced with version file.
228
312
 
229
313
  ### Added
314
+
230
315
  - **`--force` flag** — force update even when versions match.
231
316
  - **Old cursor rule directories and commands** added to deprecated cleanup.
232
317
 
@@ -235,6 +320,7 @@ Versioning: [Semantic Versioning](https://semver.org/).
235
320
  ## [0.2.0] — 2026-02-06
236
321
 
237
322
  ### Added
323
+
238
324
  - **Scenario-aware setup command** — `/flydocs-setup` rewritten as a comprehensive
239
325
  agent prompt handling three scenarios: New Project, DocFlow Migration, FlyDocs Update.
240
326
  Includes proactive repo scanning for PRDs and existing documentation.
@@ -247,10 +333,12 @@ Versioning: [Semantic Versioning](https://semver.org/).
247
333
  pre-v1.0 artifacts: old skills, rules, hooks, and cursor rules.
248
334
 
249
335
  ### Changed
336
+
250
337
  - **Version file synced with manifest** — `.flydocs/version` now matches
251
338
  `manifest.json` version field (was out of sync in 0.1.0).
252
339
 
253
340
  ### Removed
341
+
254
342
  - Orphaned hook scripts: `session-end.py`, `linear-auto-approve.py`
255
343
 
256
344
  ---
@@ -258,6 +346,7 @@ Versioning: [Semantic Versioning](https://semver.org/).
258
346
  ## [0.1.0] — 2026-01-15
259
347
 
260
348
  ### Added
349
+
261
350
  - Initial release of FlyDocs Core
262
351
  - Workflow skill (`flydocs-workflow`) with full lifecycle stages
263
352
  - 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.9",
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": {