@flydocs/cli 0.6.0-alpha.2 → 0.6.0-alpha.20

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.
Files changed (148) hide show
  1. package/dist/cli.js +678 -392
  2. package/package.json +1 -1
  3. package/template/.claude/CLAUDE.md +62 -63
  4. package/template/.claude/agents/implementation-agent.md +1 -1
  5. package/template/.claude/agents/pm-agent.md +1 -1
  6. package/template/.claude/commands/activate.md +1 -1
  7. package/template/.claude/commands/attach.md +1 -1
  8. package/template/.claude/commands/block.md +2 -2
  9. package/template/.claude/commands/capture.md +1 -1
  10. package/template/.claude/commands/close.md +1 -1
  11. package/template/.claude/commands/flydocs-setup.md +387 -74
  12. package/template/.claude/commands/flydocs-upgrade.md +48 -37
  13. package/template/.claude/commands/implement.md +1 -1
  14. package/template/.claude/commands/knowledge.md +61 -0
  15. package/template/.claude/commands/new-project.md +1 -1
  16. package/template/.claude/commands/onboard.md +275 -0
  17. package/template/.claude/commands/project-update.md +1 -1
  18. package/template/.claude/commands/refine.md +1 -1
  19. package/template/.claude/commands/review.md +1 -1
  20. package/template/.claude/commands/start-session.md +1 -1
  21. package/template/.claude/commands/status.md +1 -1
  22. package/template/.claude/commands/validate.md +1 -1
  23. package/template/.claude/commands/wrap-session.md +1 -1
  24. package/template/.claude/hooks/auto-approve.py +132 -0
  25. package/template/.claude/hooks/post-pr-check.py +108 -0
  26. package/template/.claude/hooks/post-transition-check.py +94 -0
  27. package/template/.claude/hooks/prompt-submit.py +513 -0
  28. package/template/.claude/hooks/session-start.py +146 -0
  29. package/template/.claude/hooks/stop-gate.py +109 -0
  30. package/template/.claude/settings.json +41 -4
  31. package/template/.claude/skills/README.md +23 -25
  32. package/template/.claude/skills/flydocs-workflow/SKILL.md +134 -42
  33. package/template/.claude/skills/flydocs-workflow/cursor-rule.mdc +9 -8
  34. package/template/.claude/skills/flydocs-workflow/reference/comment-templates.md +1 -0
  35. package/template/.claude/skills/flydocs-workflow/reference/golden-rules.md +28 -17
  36. package/template/.claude/skills/flydocs-workflow/reference/graph-schema.md +116 -0
  37. package/template/.claude/skills/flydocs-workflow/reference/pr-workflow.md +120 -0
  38. package/template/.claude/skills/flydocs-workflow/reference/priority-estimates.md +37 -15
  39. package/template/.claude/skills/flydocs-workflow/reference/service-descriptor-schema.md +251 -0
  40. package/template/.claude/skills/flydocs-workflow/reference/status-workflow.md +26 -26
  41. package/template/.claude/skills/flydocs-workflow/scripts/_local/__init__.py +0 -0
  42. package/template/.claude/skills/{flydocs-local/scripts/flydocs_api.py → flydocs-workflow/scripts/_local/file_store.py} +137 -47
  43. package/template/.claude/skills/flydocs-workflow/scripts/flydocs_api.py +693 -0
  44. package/template/{.flydocs → .claude/skills/flydocs-workflow}/scripts/generate_manifest.py +4 -4
  45. package/template/.claude/skills/{flydocs-context-graph → flydocs-workflow}/scripts/graph_build.py +132 -1
  46. package/template/.claude/skills/{flydocs-context-graph → flydocs-workflow}/scripts/graph_query.py +18 -5
  47. package/template/.claude/skills/{flydocs-context-graph → flydocs-workflow}/scripts/graph_session.py +1 -10
  48. package/template/.claude/skills/{flydocs-context-graph → flydocs-workflow}/scripts/graph_update.py +4 -4
  49. package/template/.claude/skills/{flydocs-context-graph → flydocs-workflow}/scripts/graph_utils.py +2 -1
  50. package/template/.claude/skills/flydocs-workflow/scripts/issues.py +489 -0
  51. package/template/.claude/skills/flydocs-workflow/scripts/projects.py +144 -0
  52. package/template/.claude/skills/flydocs-workflow/scripts/pull_services.py +128 -0
  53. package/template/.claude/skills/flydocs-workflow/scripts/push_service.py +132 -0
  54. package/template/.claude/skills/flydocs-workflow/scripts/session.py +54 -0
  55. package/template/.claude/skills/flydocs-workflow/scripts/workspace.py +860 -0
  56. package/template/.claude/skills/flydocs-workflow/session.md +63 -25
  57. package/template/.claude/skills/flydocs-workflow/stages/activate.md +18 -7
  58. package/template/.claude/skills/flydocs-workflow/stages/capture.md +10 -5
  59. package/template/.claude/skills/flydocs-workflow/stages/close.md +4 -3
  60. package/template/.claude/skills/flydocs-workflow/stages/implement.md +33 -9
  61. package/template/.claude/skills/flydocs-workflow/stages/refine.md +22 -6
  62. package/template/.claude/skills/flydocs-workflow/stages/review.md +16 -4
  63. package/template/.claude/skills/flydocs-workflow/stages/validate.md +3 -1
  64. package/template/.claude/skills/flydocs-workflow/templates/pr/default.md +33 -0
  65. package/template/.cursor/agents/implementation-agent.md +1 -1
  66. package/template/.cursor/agents/pm-agent.md +2 -2
  67. package/template/.cursor/hooks.json +10 -3
  68. package/template/.env.example +6 -6
  69. package/template/.flydocs/config.json +5 -18
  70. package/template/.flydocs/templates/README.md +13 -14
  71. package/template/.flydocs/templates/quick-capture.md +4 -8
  72. package/template/.flydocs/version +1 -1
  73. package/template/AGENTS.md +39 -32
  74. package/template/CHANGELOG.md +39 -0
  75. package/template/flydocs/README.md +1 -3
  76. package/template/flydocs/context/project.md +6 -3
  77. package/template/flydocs/design-system/README.md +3 -3
  78. package/template/flydocs/knowledge/INDEX.md +38 -53
  79. package/template/flydocs/knowledge/README.md +60 -9
  80. package/template/flydocs/knowledge/templates/decision.md +47 -0
  81. package/template/flydocs/knowledge/templates/feature.md +35 -0
  82. package/template/flydocs/knowledge/templates/note.md +25 -0
  83. package/template/manifest.json +24 -20
  84. package/template/.claude/skills/flydocs-cloud/SKILL.md +0 -111
  85. package/template/.claude/skills/flydocs-cloud/cursor-rule.mdc +0 -50
  86. package/template/.claude/skills/flydocs-cloud/scripts/assign.py +0 -22
  87. package/template/.claude/skills/flydocs-cloud/scripts/assign_cycle.py +0 -28
  88. package/template/.claude/skills/flydocs-cloud/scripts/assign_milestone.py +0 -22
  89. package/template/.claude/skills/flydocs-cloud/scripts/comment.py +0 -29
  90. package/template/.claude/skills/flydocs-cloud/scripts/create_issue.py +0 -63
  91. package/template/.claude/skills/flydocs-cloud/scripts/create_milestone.py +0 -35
  92. package/template/.claude/skills/flydocs-cloud/scripts/create_project.py +0 -33
  93. package/template/.claude/skills/flydocs-cloud/scripts/create_team.py +0 -39
  94. package/template/.claude/skills/flydocs-cloud/scripts/estimate.py +0 -29
  95. package/template/.claude/skills/flydocs-cloud/scripts/flydocs_api.py +0 -210
  96. package/template/.claude/skills/flydocs-cloud/scripts/get_issue.py +0 -24
  97. package/template/.claude/skills/flydocs-cloud/scripts/link.py +0 -28
  98. package/template/.claude/skills/flydocs-cloud/scripts/list_cycles.py +0 -28
  99. package/template/.claude/skills/flydocs-cloud/scripts/list_issues.py +0 -44
  100. package/template/.claude/skills/flydocs-cloud/scripts/list_labels.py +0 -19
  101. package/template/.claude/skills/flydocs-cloud/scripts/list_milestones.py +0 -28
  102. package/template/.claude/skills/flydocs-cloud/scripts/list_projects.py +0 -31
  103. package/template/.claude/skills/flydocs-cloud/scripts/list_teams.py +0 -19
  104. package/template/.claude/skills/flydocs-cloud/scripts/priority.py +0 -29
  105. package/template/.claude/skills/flydocs-cloud/scripts/project_update.py +0 -45
  106. package/template/.claude/skills/flydocs-cloud/scripts/set_labels.py +0 -68
  107. package/template/.claude/skills/flydocs-cloud/scripts/set_team.py +0 -41
  108. package/template/.claude/skills/flydocs-cloud/scripts/transition.py +0 -26
  109. package/template/.claude/skills/flydocs-cloud/scripts/update_description.py +0 -36
  110. package/template/.claude/skills/flydocs-cloud/scripts/update_issue.py +0 -82
  111. package/template/.claude/skills/flydocs-context-graph/SKILL.md +0 -87
  112. package/template/.claude/skills/flydocs-context-graph/schema.md +0 -78
  113. package/template/.claude/skills/flydocs-context-graph/scripts/graph_context.py +0 -338
  114. package/template/.claude/skills/flydocs-context7/SKILL.md +0 -105
  115. package/template/.claude/skills/flydocs-context7/cursor-rule.mdc +0 -49
  116. package/template/.claude/skills/flydocs-context7/scripts/context7.py +0 -293
  117. package/template/.claude/skills/flydocs-estimates/SKILL.md +0 -384
  118. package/template/.claude/skills/flydocs-figma/SKILL.md +0 -377
  119. package/template/.claude/skills/flydocs-figma/references/PROMPTING.md +0 -108
  120. package/template/.claude/skills/flydocs-figma/references/TROUBLESHOOTING.md +0 -112
  121. package/template/.claude/skills/flydocs-local/SKILL.md +0 -103
  122. package/template/.claude/skills/flydocs-local/cursor-rule.mdc +0 -43
  123. package/template/.claude/skills/flydocs-local/scripts/assign.py +0 -20
  124. package/template/.claude/skills/flydocs-local/scripts/comment.py +0 -27
  125. package/template/.claude/skills/flydocs-local/scripts/create_issue.py +0 -44
  126. package/template/.claude/skills/flydocs-local/scripts/estimate.py +0 -37
  127. package/template/.claude/skills/flydocs-local/scripts/get_issue.py +0 -20
  128. package/template/.claude/skills/flydocs-local/scripts/link.py +0 -41
  129. package/template/.claude/skills/flydocs-local/scripts/list_issues.py +0 -34
  130. package/template/.claude/skills/flydocs-local/scripts/priority.py +0 -37
  131. package/template/.claude/skills/flydocs-local/scripts/project_update.py +0 -67
  132. package/template/.claude/skills/flydocs-local/scripts/status_summary.py +0 -16
  133. package/template/.claude/skills/flydocs-local/scripts/transition.py +0 -24
  134. package/template/.claude/skills/flydocs-local/scripts/update_description.py +0 -35
  135. package/template/.claude/skills/flydocs-local/scripts/update_issue.py +0 -84
  136. package/template/.flydocs/hooks/auto-approve.py +0 -71
  137. package/template/.flydocs/hooks/prompt-submit.py +0 -277
  138. package/template/.flydocs/scripts/skill_manager.py +0 -541
  139. package/template/.flydocs/templates/bug.md +0 -166
  140. package/template/.flydocs/templates/chore.md +0 -110
  141. package/template/.flydocs/templates/feature.md +0 -173
  142. package/template/.flydocs/templates/idea.md +0 -122
  143. /package/template/{.flydocs → .claude}/hooks/post-edit.py +0 -0
  144. /package/template/.claude/skills/{flydocs-estimates/references → flydocs-workflow/reference}/provider-costs.md +0 -0
  145. /package/template/.claude/skills/flydocs-workflow/templates/{bug.md → issues/bug.md} +0 -0
  146. /package/template/.claude/skills/flydocs-workflow/templates/{chore.md → issues/chore.md} +0 -0
  147. /package/template/.claude/skills/flydocs-workflow/templates/{feature.md → issues/feature.md} +0 -0
  148. /package/template/.claude/skills/flydocs-workflow/templates/{idea.md → issues/idea.md} +0 -0
@@ -1,105 +0,0 @@
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
@@ -1,49 +0,0 @@
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
@@ -1,293 +0,0 @@
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()