@flydocs/cli 0.6.0-alpha.3 → 0.6.0-alpha.31
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 +2053 -469
- package/package.json +1 -1
- package/template/.claude/CLAUDE.md +43 -48
- package/template/.claude/agents/implementation-agent.md +1 -1
- package/template/.claude/agents/pm-agent.md +1 -1
- package/template/.claude/commands/activate.md +1 -1
- package/template/.claude/commands/attach.md +1 -1
- package/template/.claude/commands/block.md +2 -2
- package/template/.claude/commands/capture.md +1 -1
- package/template/.claude/commands/close.md +1 -1
- package/template/.claude/commands/flydocs-setup.md +359 -72
- package/template/.claude/commands/flydocs-upgrade.md +26 -27
- package/template/.claude/commands/implement.md +1 -1
- package/template/.claude/commands/knowledge.md +61 -0
- package/template/.claude/commands/new-project.md +1 -1
- package/template/.claude/commands/onboard.md +275 -0
- package/template/.claude/commands/project-update.md +1 -1
- package/template/.claude/commands/refine.md +1 -1
- package/template/.claude/commands/review.md +1 -1
- package/template/.claude/commands/start-session.md +1 -1
- package/template/.claude/commands/status.md +1 -1
- package/template/.claude/commands/validate.md +1 -1
- package/template/.claude/commands/wrap-session.md +1 -1
- package/template/.claude/hooks/auto-approve.py +212 -0
- package/template/.claude/hooks/post-pr-check.py +108 -0
- package/template/.claude/hooks/post-transition-check.py +281 -0
- package/template/.claude/hooks/prompt-submit.py +554 -0
- package/template/.claude/hooks/session-start.py +262 -0
- package/template/.claude/hooks/stop-gate.py +162 -0
- package/template/.claude/settings.json +41 -4
- package/template/.claude/skills/README.md +23 -25
- package/template/.claude/skills/flydocs-workflow/SKILL.md +134 -42
- package/template/.claude/skills/flydocs-workflow/cursor-rule.mdc +9 -8
- package/template/.claude/skills/flydocs-workflow/reference/comment-templates.md +1 -0
- package/template/.claude/skills/flydocs-workflow/reference/golden-rules.md +28 -17
- package/template/.claude/skills/flydocs-workflow/reference/graph-schema.md +116 -0
- package/template/.claude/skills/flydocs-workflow/reference/pr-workflow.md +120 -0
- package/template/.claude/skills/flydocs-workflow/reference/priority-estimates.md +37 -15
- package/template/.claude/skills/flydocs-workflow/reference/service-descriptor-schema.md +260 -0
- package/template/.claude/skills/flydocs-workflow/reference/status-workflow.md +26 -26
- package/template/.claude/skills/flydocs-workflow/scripts/_local/__init__.py +0 -0
- package/template/.claude/skills/{flydocs-local/scripts/flydocs_api.py → flydocs-workflow/scripts/_local/file_store.py} +137 -47
- package/template/.claude/skills/flydocs-workflow/scripts/flydocs_api.py +724 -0
- package/template/{.flydocs → .claude/skills/flydocs-workflow}/scripts/generate_manifest.py +4 -4
- package/template/.claude/skills/{flydocs-context-graph → flydocs-workflow}/scripts/graph_build.py +132 -1
- package/template/.claude/skills/{flydocs-context-graph → flydocs-workflow}/scripts/graph_query.py +18 -5
- package/template/.claude/skills/{flydocs-context-graph → flydocs-workflow}/scripts/graph_session.py +1 -10
- package/template/.claude/skills/{flydocs-context-graph → flydocs-workflow}/scripts/graph_update.py +4 -4
- package/template/.claude/skills/{flydocs-context-graph → flydocs-workflow}/scripts/graph_utils.py +2 -1
- package/template/.claude/skills/flydocs-workflow/scripts/issues.py +738 -0
- package/template/.claude/skills/flydocs-workflow/scripts/projects.py +144 -0
- package/template/.claude/skills/flydocs-workflow/scripts/pull_services.py +128 -0
- package/template/.claude/skills/flydocs-workflow/scripts/push_service.py +132 -0
- package/template/.claude/skills/flydocs-workflow/scripts/session.py +54 -0
- package/template/.claude/skills/flydocs-workflow/scripts/test_enforcement.py +225 -0
- package/template/.claude/skills/flydocs-workflow/scripts/workspace.py +902 -0
- package/template/.claude/skills/flydocs-workflow/session.md +87 -29
- package/template/.claude/skills/flydocs-workflow/stages/activate.md +18 -7
- package/template/.claude/skills/flydocs-workflow/stages/capture.md +10 -5
- package/template/.claude/skills/flydocs-workflow/stages/close.md +4 -3
- package/template/.claude/skills/flydocs-workflow/stages/implement.md +33 -9
- package/template/.claude/skills/flydocs-workflow/stages/refine.md +22 -6
- package/template/.claude/skills/flydocs-workflow/stages/review.md +16 -4
- package/template/.claude/skills/flydocs-workflow/stages/validate.md +3 -1
- package/template/.claude/skills/flydocs-workflow/templates/pr/default.md +33 -0
- package/template/.cursor/agents/implementation-agent.md +1 -1
- package/template/.cursor/agents/pm-agent.md +2 -2
- package/template/.cursor/hooks.json +10 -3
- package/template/.env.example +6 -6
- package/template/.flydocs/config.json +5 -18
- package/template/.flydocs/templates/README.md +13 -14
- package/template/.flydocs/templates/bug.md +17 -153
- package/template/.flydocs/templates/chore.md +10 -98
- package/template/.flydocs/templates/feature.md +12 -158
- package/template/.flydocs/templates/idea.md +11 -111
- package/template/.flydocs/templates/quick-capture.md +4 -8
- package/template/.flydocs/version +1 -1
- package/template/AGENTS.md +44 -32
- package/template/CHANGELOG.md +37 -0
- package/template/flydocs/README.md +1 -3
- package/template/flydocs/context/project.md +6 -3
- package/template/flydocs/design-system/README.md +3 -3
- package/template/flydocs/knowledge/INDEX.md +38 -53
- package/template/flydocs/knowledge/README.md +60 -9
- package/template/flydocs/knowledge/templates/decision.md +47 -0
- package/template/flydocs/knowledge/templates/feature.md +35 -0
- package/template/flydocs/knowledge/templates/note.md +25 -0
- package/template/manifest.json +24 -20
- package/template/.claude/skills/flydocs-cloud/SKILL.md +0 -113
- package/template/.claude/skills/flydocs-cloud/cursor-rule.mdc +0 -50
- package/template/.claude/skills/flydocs-cloud/scripts/assign.py +0 -22
- package/template/.claude/skills/flydocs-cloud/scripts/assign_cycle.py +0 -28
- package/template/.claude/skills/flydocs-cloud/scripts/assign_milestone.py +0 -22
- package/template/.claude/skills/flydocs-cloud/scripts/comment.py +0 -29
- package/template/.claude/skills/flydocs-cloud/scripts/create_issue.py +0 -66
- package/template/.claude/skills/flydocs-cloud/scripts/create_milestone.py +0 -35
- package/template/.claude/skills/flydocs-cloud/scripts/create_project.py +0 -33
- package/template/.claude/skills/flydocs-cloud/scripts/create_team.py +0 -39
- package/template/.claude/skills/flydocs-cloud/scripts/estimate.py +0 -29
- package/template/.claude/skills/flydocs-cloud/scripts/flydocs_api.py +0 -210
- package/template/.claude/skills/flydocs-cloud/scripts/get_issue.py +0 -24
- package/template/.claude/skills/flydocs-cloud/scripts/link.py +0 -28
- package/template/.claude/skills/flydocs-cloud/scripts/list_cycles.py +0 -28
- package/template/.claude/skills/flydocs-cloud/scripts/list_issues.py +0 -44
- package/template/.claude/skills/flydocs-cloud/scripts/list_labels.py +0 -19
- package/template/.claude/skills/flydocs-cloud/scripts/list_milestones.py +0 -28
- package/template/.claude/skills/flydocs-cloud/scripts/list_projects.py +0 -31
- package/template/.claude/skills/flydocs-cloud/scripts/list_providers.py +0 -19
- package/template/.claude/skills/flydocs-cloud/scripts/list_teams.py +0 -19
- package/template/.claude/skills/flydocs-cloud/scripts/priority.py +0 -29
- package/template/.claude/skills/flydocs-cloud/scripts/project_update.py +0 -45
- package/template/.claude/skills/flydocs-cloud/scripts/set_labels.py +0 -68
- package/template/.claude/skills/flydocs-cloud/scripts/set_provider.py +0 -46
- package/template/.claude/skills/flydocs-cloud/scripts/set_team.py +0 -41
- package/template/.claude/skills/flydocs-cloud/scripts/transition.py +0 -26
- package/template/.claude/skills/flydocs-cloud/scripts/update_description.py +0 -36
- package/template/.claude/skills/flydocs-cloud/scripts/update_issue.py +0 -82
- package/template/.claude/skills/flydocs-context-graph/SKILL.md +0 -87
- package/template/.claude/skills/flydocs-context-graph/schema.md +0 -78
- package/template/.claude/skills/flydocs-context-graph/scripts/graph_context.py +0 -338
- package/template/.claude/skills/flydocs-context7/SKILL.md +0 -105
- package/template/.claude/skills/flydocs-context7/cursor-rule.mdc +0 -49
- package/template/.claude/skills/flydocs-context7/scripts/context7.py +0 -293
- package/template/.claude/skills/flydocs-estimates/SKILL.md +0 -384
- package/template/.claude/skills/flydocs-figma/SKILL.md +0 -377
- package/template/.claude/skills/flydocs-figma/references/PROMPTING.md +0 -108
- package/template/.claude/skills/flydocs-figma/references/TROUBLESHOOTING.md +0 -112
- package/template/.claude/skills/flydocs-local/SKILL.md +0 -103
- package/template/.claude/skills/flydocs-local/cursor-rule.mdc +0 -43
- package/template/.claude/skills/flydocs-local/scripts/assign.py +0 -20
- package/template/.claude/skills/flydocs-local/scripts/comment.py +0 -27
- package/template/.claude/skills/flydocs-local/scripts/create_issue.py +0 -44
- package/template/.claude/skills/flydocs-local/scripts/estimate.py +0 -37
- package/template/.claude/skills/flydocs-local/scripts/get_issue.py +0 -20
- package/template/.claude/skills/flydocs-local/scripts/link.py +0 -41
- package/template/.claude/skills/flydocs-local/scripts/list_issues.py +0 -34
- package/template/.claude/skills/flydocs-local/scripts/priority.py +0 -37
- package/template/.claude/skills/flydocs-local/scripts/project_update.py +0 -67
- package/template/.claude/skills/flydocs-local/scripts/status_summary.py +0 -16
- package/template/.claude/skills/flydocs-local/scripts/transition.py +0 -24
- package/template/.claude/skills/flydocs-local/scripts/update_description.py +0 -35
- package/template/.claude/skills/flydocs-local/scripts/update_issue.py +0 -84
- package/template/.flydocs/hooks/auto-approve.py +0 -71
- package/template/.flydocs/hooks/prompt-submit.py +0 -277
- package/template/.flydocs/scripts/skill_manager.py +0 -541
- /package/template/{.flydocs → .claude}/hooks/post-edit.py +0 -0
- /package/template/.claude/skills/{flydocs-estimates/references → flydocs-workflow/reference}/provider-costs.md +0 -0
- /package/template/.claude/skills/flydocs-workflow/templates/{bug.md → issues/bug.md} +0 -0
- /package/template/.claude/skills/flydocs-workflow/templates/{chore.md → issues/chore.md} +0 -0
- /package/template/.claude/skills/flydocs-workflow/templates/{feature.md → issues/feature.md} +0 -0
- /package/template/.claude/skills/flydocs-workflow/templates/{idea.md → issues/idea.md} +0 -0
|
@@ -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()
|
|
@@ -1,384 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: flydocs-estimates
|
|
3
|
-
description: "FlyDocs premium: Estimates token usage and API costs for AI development tasks. Apply when refining issues, activating work, or when user asks about costs. v1.0: Guidance-only. Future: Scripts via API relay for premium functionality."
|
|
4
|
-
triggers:
|
|
5
|
-
- estimate
|
|
6
|
-
- cost
|
|
7
|
-
- token usage
|
|
8
|
-
- API cost
|
|
9
|
-
- labor estimate
|
|
10
|
-
- sizing
|
|
11
|
-
- effort
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
# FlyDocs Estimates
|
|
15
|
-
|
|
16
|
-
> **Purpose**: Estimate token usage and API costs for AI-driven development tasks before implementation begins.
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## Opt-In Feature
|
|
21
|
-
|
|
22
|
-
**This skill is disabled by default.** To enable, set in `.flydocs/config.json`:
|
|
23
|
-
|
|
24
|
-
```json
|
|
25
|
-
{
|
|
26
|
-
"aiLabor": {
|
|
27
|
-
"enabled": true
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
### Before Using This Skill
|
|
33
|
-
|
|
34
|
-
```
|
|
35
|
-
□ 1. CHECK config: Read .flydocs/config.json
|
|
36
|
-
□ 2. IF aiLabor.enabled !== true:
|
|
37
|
-
→ DO NOT apply any rules from this skill
|
|
38
|
-
→ DO NOT warn about missing estimates
|
|
39
|
-
→ DO NOT add estimate sections to issues
|
|
40
|
-
→ Proceed with standard workflow
|
|
41
|
-
□ 3. IF aiLabor.enabled === true:
|
|
42
|
-
→ Apply all rules below
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
**When disabled**: This skill is completely silent. No warnings, no prompts, no estimate tracking.
|
|
46
|
-
|
|
47
|
-
---
|
|
48
|
-
|
|
49
|
-
## Overview
|
|
50
|
-
|
|
51
|
-
This skill enables agents to:
|
|
52
|
-
1. **Analyze specs** to predict token consumption
|
|
53
|
-
2. **Calculate cost ranges** based on provider pricing
|
|
54
|
-
3. **Track actuals** for calibration over time
|
|
55
|
-
4. **Compare** Human vs AI vs Hybrid cost projections
|
|
56
|
-
|
|
57
|
-
---
|
|
58
|
-
|
|
59
|
-
## When to Use (Only if enabled)
|
|
60
|
-
|
|
61
|
-
| Trigger | Action |
|
|
62
|
-
|---------|--------|
|
|
63
|
-
| `/refine [spec]` | Calculate estimate, add to issue |
|
|
64
|
-
| `/activate [spec]` | Validate estimate exists; if missing, offer to calculate; warn on high estimates |
|
|
65
|
-
| `/implement [spec]` | Show estimate in checklist if present |
|
|
66
|
-
| `/close [spec]` | Record actuals, calculate variance |
|
|
67
|
-
| Implementation complete | Estimate tokens used, update actuals in issue |
|
|
68
|
-
| User asks "how much will this cost?" | Run estimation |
|
|
69
|
-
|
|
70
|
-
### Validation Flow (for /activate and /implement) — Only When Enabled
|
|
71
|
-
|
|
72
|
-
```
|
|
73
|
-
1. Read issue description
|
|
74
|
-
2. Search for "## AI Effort Estimate" section
|
|
75
|
-
3. IF missing:
|
|
76
|
-
→ OFFER: "Would you like me to calculate an AI Effort Estimate?"
|
|
77
|
-
→ IF yes: Run estimation, update description
|
|
78
|
-
→ IF no: Proceed normally
|
|
79
|
-
4. IF present but has placeholders ([X]k):
|
|
80
|
-
→ OFFER: "Estimate exists but incomplete. Fill it now?"
|
|
81
|
-
5. IF estimate exceeds thresholds:
|
|
82
|
-
→ tokens > 200k OR cost > $5: Show warning
|
|
83
|
-
→ cost > $10: Require explicit approval
|
|
84
|
-
6. Continue with activation/implementation
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
---
|
|
88
|
-
|
|
89
|
-
## Estimation Formula
|
|
90
|
-
|
|
91
|
-
```
|
|
92
|
-
estimated_tokens = base_tokens × scope_mult × novelty_mult × clarity_mult × codebase_mult
|
|
93
|
-
|
|
94
|
-
Where:
|
|
95
|
-
base_tokens = task type baseline (see table below)
|
|
96
|
-
scope_mult = 0.5 (S) / 1.0 (M) / 2.0 (L) / 4.0 (XL)
|
|
97
|
-
novelty_mult = 0.7 (existing pattern) / 1.2 (partial new) / 2.0 (greenfield)
|
|
98
|
-
clarity_mult = 0.8 (well-defined) / 1.5 (needs discovery) / 2.5 (exploratory)
|
|
99
|
-
codebase_mult = 0.8 (simple) / 1.0 (moderate) / 1.5 (complex)
|
|
100
|
-
|
|
101
|
-
Confidence Range:
|
|
102
|
-
low_estimate = estimated_tokens × 0.6
|
|
103
|
-
high_estimate = estimated_tokens × 2.5
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
### Base Tokens by Task Type
|
|
107
|
-
|
|
108
|
-
| Task Type | Base Tokens | Rationale |
|
|
109
|
-
|-----------|-------------|-----------|
|
|
110
|
-
| **feature** | 40,000 | Full cycle: plan, implement, iterate, review |
|
|
111
|
-
| **bug** | 20,000 | Investigation + targeted fix |
|
|
112
|
-
| **chore** | 10,000 | Usually straightforward |
|
|
113
|
-
| **idea** | 5,000 | Quick exploration only |
|
|
114
|
-
|
|
115
|
-
---
|
|
116
|
-
|
|
117
|
-
## Scoring Multipliers
|
|
118
|
-
|
|
119
|
-
### Scope (from Complexity field)
|
|
120
|
-
|
|
121
|
-
| Complexity | Multiplier | Indicators |
|
|
122
|
-
|------------|------------|------------|
|
|
123
|
-
| **S** | 0.5 | 1-3 acceptance criteria, single file |
|
|
124
|
-
| **M** | 1.0 | 4-6 acceptance criteria, 2-5 files |
|
|
125
|
-
| **L** | 2.0 | 7-10 acceptance criteria, multiple modules |
|
|
126
|
-
| **XL** | 4.0 | 10+ criteria, cross-cutting changes |
|
|
127
|
-
|
|
128
|
-
### Novelty (from Technical Notes)
|
|
129
|
-
|
|
130
|
-
| Level | Multiplier | Indicators |
|
|
131
|
-
|-------|------------|------------|
|
|
132
|
-
| **existing-pattern** | 0.7 | "Follow existing X pattern", references similar code |
|
|
133
|
-
| **partial-new** | 1.2 | Mix of new + existing, some exploration needed |
|
|
134
|
-
| **greenfield** | 2.0 | New patterns, no precedent in codebase |
|
|
135
|
-
|
|
136
|
-
### Clarity (from Acceptance Criteria quality)
|
|
137
|
-
|
|
138
|
-
| Level | Multiplier | Indicators |
|
|
139
|
-
|-------|------------|------------|
|
|
140
|
-
| **well-defined** | 0.8 | All criteria specific & testable |
|
|
141
|
-
| **needs-discovery** | 1.5 | Some vague criteria, needs investigation |
|
|
142
|
-
| **exploratory** | 2.5 | Research-heavy, unclear solution |
|
|
143
|
-
|
|
144
|
-
### Codebase Complexity (from `stack.md`)
|
|
145
|
-
|
|
146
|
-
| Level | Multiplier | Indicators |
|
|
147
|
-
|-------|------------|------------|
|
|
148
|
-
| **simple** | 0.8 | Small codebase, clear patterns |
|
|
149
|
-
| **moderate** | 1.0 | Standard project, documented patterns |
|
|
150
|
-
| **complex** | 1.5 | Large codebase, multiple integrations |
|
|
151
|
-
|
|
152
|
-
---
|
|
153
|
-
|
|
154
|
-
## Cost Calculation
|
|
155
|
-
|
|
156
|
-
```
|
|
157
|
-
cost = tokens × (input_rate × input_ratio + output_rate × output_ratio)
|
|
158
|
-
|
|
159
|
-
Where:
|
|
160
|
-
input_rate = provider cost per 1M input tokens
|
|
161
|
-
output_rate = provider cost per 1M output tokens
|
|
162
|
-
input_ratio = 0.70 (typical for development)
|
|
163
|
-
output_ratio = 0.30 (typical for development)
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
See `references/provider-costs.md` for current pricing.
|
|
167
|
-
|
|
168
|
-
---
|
|
169
|
-
|
|
170
|
-
## Issue Template Section
|
|
171
|
-
|
|
172
|
-
Add this to Linear issue description during `/refine`:
|
|
173
|
-
|
|
174
|
-
```markdown
|
|
175
|
-
---
|
|
176
|
-
|
|
177
|
-
## AI Effort Estimate
|
|
178
|
-
|
|
179
|
-
### Sizing Factors
|
|
180
|
-
|
|
181
|
-
| Factor | Value | Multiplier |
|
|
182
|
-
|--------|-------|------------|
|
|
183
|
-
| **Task Type** | [feature/bug/chore] | base: [X]k |
|
|
184
|
-
| **Scope** | [S/M/L/XL] | ×[0.5/1.0/2.0/4.0] |
|
|
185
|
-
| **Novelty** | [existing/partial/greenfield] | ×[0.7/1.2/2.0] |
|
|
186
|
-
| **Clarity** | [defined/discovery/exploratory] | ×[0.8/1.5/2.5] |
|
|
187
|
-
| **Codebase** | [simple/moderate/complex] | ×[0.8/1.0/1.5] |
|
|
188
|
-
|
|
189
|
-
### Estimate
|
|
190
|
-
|
|
191
|
-
**Provider**: [Claude Sonnet 4 / GPT-4o / etc.]
|
|
192
|
-
**Calculated Tokens**: ~[X]k
|
|
193
|
-
**Confidence**: ±[40-60]%
|
|
194
|
-
**Token Range**: [low]k - [high]k
|
|
195
|
-
**Cost Range**: $[low] - $[high]
|
|
196
|
-
|
|
197
|
-
### Comparison
|
|
198
|
-
|
|
199
|
-
| Approach | Est. Cost | Est. Time | Best For |
|
|
200
|
-
|----------|-----------|-----------|----------|
|
|
201
|
-
| **Full AI** | $[X] | [X] hrs | Well-defined, pattern-matching |
|
|
202
|
-
| **AI-Assisted** | $[X] + [X]hrs human | [X] hrs | Complex decisions |
|
|
203
|
-
| **Human-Led** | $[X] (review) + [X]hrs | [X] hrs | Novel architecture |
|
|
204
|
-
|
|
205
|
-
---
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
---
|
|
209
|
-
|
|
210
|
-
## Recording Actuals (on /close)
|
|
211
|
-
|
|
212
|
-
Add to issue comment on completion:
|
|
213
|
-
|
|
214
|
-
```markdown
|
|
215
|
-
## AI Effort Actuals
|
|
216
|
-
|
|
217
|
-
**Estimated Tokens**: [X]k
|
|
218
|
-
**Actual Tokens**: [X]k (from session/API logs if available)
|
|
219
|
-
**Variance**: [+/-X]% [under/over]
|
|
220
|
-
**Actual Cost**: $[X]
|
|
221
|
-
|
|
222
|
-
### Variance Notes
|
|
223
|
-
- [What drove the variance - blockers, scope change, retries, etc.]
|
|
224
|
-
- [Lessons for future estimation]
|
|
225
|
-
|
|
226
|
-
### Calibration Data
|
|
227
|
-
- Task Type: [feature]
|
|
228
|
-
- Final Complexity: [M]
|
|
229
|
-
- Novelty Actual: [partial-new]
|
|
230
|
-
- Clarity Actual: [well-defined]
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
---
|
|
234
|
-
|
|
235
|
-
## Agent Instructions
|
|
236
|
-
|
|
237
|
-
### During /refine (PM Agent)
|
|
238
|
-
|
|
239
|
-
1. **Read the spec** completely
|
|
240
|
-
2. **Identify task type** from labels (feature, bug, chore, idea)
|
|
241
|
-
3. **Score each factor**:
|
|
242
|
-
- Count acceptance criteria → scope
|
|
243
|
-
- Check Technical Notes for patterns → novelty
|
|
244
|
-
- Assess criteria specificity → clarity
|
|
245
|
-
- Reference `stack.md` → codebase complexity
|
|
246
|
-
4. **Calculate estimate** using formula
|
|
247
|
-
5. **Look up provider costs** from `references/provider-costs.md` or `.flydocs/config.json`
|
|
248
|
-
6. **Add estimate section** to issue description (replace placeholders with values)
|
|
249
|
-
7. **If estimate exceeds threshold**, flag for human review:
|
|
250
|
-
- \> 200k tokens → Consider breaking down the issue
|
|
251
|
-
- \> $5 estimated → Confirm before proceeding
|
|
252
|
-
8. **Include estimate in refine comment**: `AI Estimate: ~Xk tokens ($X-$X)`
|
|
253
|
-
|
|
254
|
-
### During /activate (PM Agent)
|
|
255
|
-
|
|
256
|
-
1. **Search issue description** for "## AI Effort Estimate"
|
|
257
|
-
2. **If missing**:
|
|
258
|
-
- WARN: "⚠️ This issue is missing an AI Effort Estimate."
|
|
259
|
-
- ASK: "Would you like me to calculate one now before activation?"
|
|
260
|
-
- If yes → Calculate and add to description
|
|
261
|
-
- If no → Proceed but note: "No baseline for actuals comparison"
|
|
262
|
-
3. **If present but incomplete** (still has `[X]k` placeholders):
|
|
263
|
-
- OFFER: "AI Effort Estimate exists but has placeholder values. Complete it now?"
|
|
264
|
-
4. **If present and exceeds thresholds**:
|
|
265
|
-
- \> 200k tokens or \> $5 → Show warning, ask for confirmation
|
|
266
|
-
- \> $10 → Require explicit "yes proceed" before continuing
|
|
267
|
-
5. **Include in activation comment**: `AI Effort: ~Xk tokens ($X-$X)`
|
|
268
|
-
|
|
269
|
-
### During /implement (Implementation Agent)
|
|
270
|
-
|
|
271
|
-
1. **Search issue description** for "## AI Effort Estimate"
|
|
272
|
-
2. **If missing**:
|
|
273
|
-
- WARN: "⚠️ Missing AI Effort Estimate - tracking actuals won't have comparison baseline."
|
|
274
|
-
- OFFER: "Calculate estimate before starting implementation?"
|
|
275
|
-
- If yes → Calculate estimate, update description
|
|
276
|
-
- If no → Proceed with warning
|
|
277
|
-
3. **If present**:
|
|
278
|
-
- Show estimate in implementation checklist
|
|
279
|
-
- Note: "Tracking against estimate of ~Xk tokens"
|
|
280
|
-
4. **During implementation**:
|
|
281
|
-
- Keep rough mental model of token usage
|
|
282
|
-
- Note if work is going significantly over estimate (scope discovery, retries)
|
|
283
|
-
|
|
284
|
-
### On Implementation Complete (Implementation Agent)
|
|
285
|
-
|
|
286
|
-
1. **Estimate actual tokens used**:
|
|
287
|
-
- Rough method: conversation turns × ~2k tokens/turn
|
|
288
|
-
- Or estimate based on files changed, complexity of work
|
|
289
|
-
2. **Update AI Effort Estimate section** in issue description:
|
|
290
|
-
- Fill "Actual Tokens" field
|
|
291
|
-
- Calculate variance percentage
|
|
292
|
-
- Add notes on variance drivers
|
|
293
|
-
3. **Include in completion comment**: `AI Effort: ~Xk actual (estimated Xk, +/-X% variance)`
|
|
294
|
-
|
|
295
|
-
### During /close (PM Agent)
|
|
296
|
-
|
|
297
|
-
1. **Verify actuals were recorded** (from implementation completion)
|
|
298
|
-
2. **If actuals missing**: Estimate based on issue activity/comments
|
|
299
|
-
3. **Calculate final variance** from estimate
|
|
300
|
-
4. **Add final actuals to issue** if not already present
|
|
301
|
-
5. **Log patterns for calibration**:
|
|
302
|
-
- Which factor assessments were off?
|
|
303
|
-
- What should be adjusted for similar future work?
|
|
304
|
-
6. **Include in close comment**: `Final AI Effort: ~Xk tokens (+/-X% from estimate)`
|
|
305
|
-
|
|
306
|
-
---
|
|
307
|
-
|
|
308
|
-
## Configuration
|
|
309
|
-
|
|
310
|
-
In `.flydocs/config.json`:
|
|
311
|
-
|
|
312
|
-
```json
|
|
313
|
-
{
|
|
314
|
-
"aiLabor": {
|
|
315
|
-
"enabled": false,
|
|
316
|
-
"defaultProvider": "claude-sonnet-4",
|
|
317
|
-
"thresholds": {
|
|
318
|
-
"warnTokens": 200000,
|
|
319
|
-
"warnCost": 5.00,
|
|
320
|
-
"requireApproval": 10.00
|
|
321
|
-
},
|
|
322
|
-
"tracking": {
|
|
323
|
-
"recordActuals": true,
|
|
324
|
-
"calibrationEnabled": true
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
**To enable**, change `"enabled": false` to `"enabled": true`.
|
|
331
|
-
|
|
332
|
-
When enabled, the skill will:
|
|
333
|
-
- Add AI Effort Estimate sections during `/refine`
|
|
334
|
-
- Offer to calculate estimates during `/activate` and `/implement`
|
|
335
|
-
- Track actuals on completion
|
|
336
|
-
- Warn on high-cost estimates based on thresholds
|
|
337
|
-
|
|
338
|
-
---
|
|
339
|
-
|
|
340
|
-
## Example Calculation
|
|
341
|
-
|
|
342
|
-
**Spec**: "Add user profile photo upload"
|
|
343
|
-
|
|
344
|
-
| Factor | Assessment | Value |
|
|
345
|
-
|--------|------------|-------|
|
|
346
|
-
| Type | Feature | 40k base |
|
|
347
|
-
| Scope | M (5 criteria, ~4 files) | ×1.0 |
|
|
348
|
-
| Novelty | Existing pattern (similar to doc upload) | ×0.7 |
|
|
349
|
-
| Clarity | Well-defined (clear criteria) | ×0.8 |
|
|
350
|
-
| Codebase | Moderate | ×1.0 |
|
|
351
|
-
|
|
352
|
-
**Calculation**:
|
|
353
|
-
```
|
|
354
|
-
40,000 × 1.0 × 0.7 × 0.8 × 1.0 = 22,400 tokens
|
|
355
|
-
|
|
356
|
-
Range: 13,440 - 56,000 tokens (±60% confidence)
|
|
357
|
-
|
|
358
|
-
Cost (Claude Sonnet 4 @ $3/$15 per 1M):
|
|
359
|
-
Low: 13.4k × (0.7×$3 + 0.3×$15)/1M = $0.09
|
|
360
|
-
High: 56k × (0.7×$3 + 0.3×$15)/1M = $0.37
|
|
361
|
-
```
|
|
362
|
-
|
|
363
|
-
**Result**: ~22k tokens, $0.09 - $0.37 estimated cost
|
|
364
|
-
|
|
365
|
-
---
|
|
366
|
-
|
|
367
|
-
## Related Skills
|
|
368
|
-
|
|
369
|
-
- `flydocs-workflow` - For workflow lifecycle and issue operations
|
|
370
|
-
- `spec-templates` - Template structure reference
|
|
371
|
-
|
|
372
|
-
---
|
|
373
|
-
|
|
374
|
-
## Calibration Over Time
|
|
375
|
-
|
|
376
|
-
Track estimates vs actuals to improve accuracy:
|
|
377
|
-
|
|
378
|
-
1. **Log all estimates and actuals** in issue comments
|
|
379
|
-
2. **Review monthly** for patterns:
|
|
380
|
-
- Which task types are consistently over/under?
|
|
381
|
-
- Which factors need adjustment?
|
|
382
|
-
3. **Adjust multipliers** based on your codebase patterns
|
|
383
|
-
4. **Document adjustments** in `.flydocs/knowledge/notes/`
|
|
384
|
-
|