@flydocs/cli 0.5.0-beta.9 → 0.6.0-alpha.2

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 (41) hide show
  1. package/README.md +6 -0
  2. package/dist/cli.js +1259 -370
  3. package/package.json +1 -1
  4. package/template/.claude/agents/implementation-agent.md +0 -1
  5. package/template/.claude/agents/pm-agent.md +0 -1
  6. package/template/.claude/agents/research-agent.md +0 -1
  7. package/template/.claude/agents/review-agent.md +0 -1
  8. package/template/.claude/commands/flydocs-setup.md +109 -26
  9. package/template/.claude/commands/flydocs-upgrade.md +330 -0
  10. package/template/.claude/skills/flydocs-cloud/SKILL.md +53 -38
  11. package/template/.claude/skills/flydocs-cloud/cursor-rule.mdc +5 -5
  12. package/template/.claude/skills/flydocs-cloud/scripts/assign.py +8 -24
  13. package/template/.claude/skills/flydocs-cloud/scripts/assign_cycle.py +14 -30
  14. package/template/.claude/skills/flydocs-cloud/scripts/assign_milestone.py +10 -32
  15. package/template/.claude/skills/flydocs-cloud/scripts/comment.py +15 -25
  16. package/template/.claude/skills/flydocs-cloud/scripts/create_issue.py +21 -58
  17. package/template/.claude/skills/flydocs-cloud/scripts/create_milestone.py +26 -37
  18. package/template/.claude/skills/flydocs-cloud/scripts/create_project.py +24 -31
  19. package/template/.claude/skills/flydocs-cloud/scripts/create_team.py +39 -0
  20. package/template/.claude/skills/flydocs-cloud/scripts/estimate.py +10 -19
  21. package/template/.claude/skills/flydocs-cloud/scripts/flydocs_api.py +103 -170
  22. package/template/.claude/skills/flydocs-cloud/scripts/get_issue.py +6 -59
  23. package/template/.claude/skills/flydocs-cloud/scripts/link.py +16 -35
  24. package/template/.claude/skills/flydocs-cloud/scripts/list_cycles.py +21 -28
  25. package/template/.claude/skills/flydocs-cloud/scripts/list_issues.py +16 -77
  26. package/template/.claude/skills/flydocs-cloud/scripts/list_labels.py +19 -0
  27. package/template/.claude/skills/flydocs-cloud/scripts/list_milestones.py +21 -33
  28. package/template/.claude/skills/flydocs-cloud/scripts/list_projects.py +24 -38
  29. package/template/.claude/skills/flydocs-cloud/scripts/list_teams.py +19 -0
  30. package/template/.claude/skills/flydocs-cloud/scripts/priority.py +10 -19
  31. package/template/.claude/skills/flydocs-cloud/scripts/project_update.py +36 -50
  32. package/template/.claude/skills/flydocs-cloud/scripts/set_labels.py +68 -0
  33. package/template/.claude/skills/flydocs-cloud/scripts/set_team.py +41 -0
  34. package/template/.claude/skills/flydocs-cloud/scripts/transition.py +11 -52
  35. package/template/.claude/skills/flydocs-cloud/scripts/update_description.py +16 -27
  36. package/template/.claude/skills/flydocs-cloud/scripts/update_issue.py +23 -52
  37. package/template/.env.example +16 -7
  38. package/template/.flydocs/config.json +1 -1
  39. package/template/.flydocs/version +1 -1
  40. package/template/CHANGELOG.md +144 -0
  41. package/template/manifest.json +5 -3
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env python3
2
- """Update an issue's description."""
2
+ """Update an issue's description via the FlyDocs Relay API."""
3
3
 
4
4
  import argparse
5
5
  import sys
@@ -9,39 +9,28 @@ sys.path.insert(0, str(Path(__file__).parent))
9
9
  from flydocs_api import get_client, output_json, fail
10
10
 
11
11
  parser = argparse.ArgumentParser(description="Update issue description")
12
- parser.add_argument("ref")
13
- parser.add_argument("--text", default="")
14
- parser.add_argument("--file", default="", dest="filepath")
12
+ parser.add_argument("ref", help="Issue reference (e.g., ENG-123)")
13
+ parser.add_argument("--text", default=None)
14
+ parser.add_argument("--file", default=None)
15
15
  args = parser.parse_args()
16
16
 
17
+ # Resolve text: --file > stdin > --text
17
18
  text = args.text
18
- if args.filepath:
19
+ if args.file:
19
20
  try:
20
- text = Path(args.filepath).read_text()
21
+ text = Path(args.file).read_text()
21
22
  except FileNotFoundError:
22
- fail(f"File not found: {args.filepath}")
23
- if not text and not sys.stdin.isatty():
23
+ fail(f"File not found: {args.file}")
24
+ elif text is None and not sys.stdin.isatty():
24
25
  text = sys.stdin.read().strip()
26
+
25
27
  if not text:
26
- fail("Provide --text, --file, or pipe via stdin")
28
+ fail("Provide text via --text, --file, or stdin")
27
29
 
28
30
  client = get_client()
29
- issue_uuid = client.resolve_issue_id(args.ref)
30
- if not issue_uuid:
31
- fail(f"Issue not found: {args.ref}")
32
-
33
- result = client.query(
34
- """mutation($id: String!, $description: String!) {
35
- issueUpdate(id: $id, input: { description: $description }) {
36
- success
37
- issue { identifier }
38
- }
39
- }""",
40
- {"id": issue_uuid, "description": text},
41
- )
42
-
43
- if not result.get("data", {}).get("issueUpdate", {}).get("success"):
44
- fail(f"Failed to update: {result}")
31
+ result = client.put(f"/issues/{args.ref}/description", {"text": text})
45
32
 
46
- issue = result["data"]["issueUpdate"]["issue"]
47
- output_json({"success": True, "issue": issue["identifier"]})
33
+ output_json({
34
+ "success": result.get("success", True),
35
+ "issue": result.get("issue", args.ref),
36
+ })
@@ -19,90 +19,61 @@ def main():
19
19
  parser.add_argument("--state", default=None)
20
20
  parser.add_argument("--description", default=None)
21
21
  parser.add_argument("--description-file", default=None)
22
+ parser.add_argument("--labels", default=None, help="Comma-separated label names")
22
23
  parser.add_argument("--comment", default=None)
23
24
  args = parser.parse_args()
24
25
 
25
- client = get_client()
26
-
27
- issue_uuid = client.resolve_issue_id(args.ref)
28
- if not issue_uuid:
29
- fail(f"Issue not found: {args.ref}")
30
-
31
- # Build mutation input from provided args
32
- mutation_input: dict = {}
26
+ # Build request body from provided args
27
+ body: dict = {}
33
28
  updated_fields: list[str] = []
34
29
 
35
30
  if args.title is not None:
36
- mutation_input["title"] = args.title
31
+ body["title"] = args.title
37
32
  updated_fields.append("title")
38
33
 
39
34
  if args.priority is not None:
40
- mutation_input["priority"] = args.priority
35
+ body["priority"] = args.priority
41
36
  updated_fields.append("priority")
42
37
 
43
38
  if args.estimate is not None:
44
- mutation_input["estimate"] = args.estimate
39
+ body["estimate"] = args.estimate
45
40
  updated_fields.append("estimate")
46
41
 
47
42
  if args.assignee is not None:
48
- user_id, user_name = client.resolve_user_id(args.assignee)
49
- if not user_id:
50
- fail(f"User not found: {args.assignee}")
51
- mutation_input["assigneeId"] = user_id
43
+ body["assignee"] = args.assignee
52
44
  updated_fields.append("assignee")
53
45
 
54
46
  if args.state is not None:
55
- state_id = client.get_state_id(args.state.upper())
56
- if not state_id:
57
- fail(f"Unknown status: {args.state}")
58
- mutation_input["stateId"] = state_id
47
+ body["state"] = args.state.upper()
59
48
  updated_fields.append("state")
60
49
 
61
50
  if args.description_file is not None:
62
51
  path = Path(args.description_file)
63
52
  if not path.exists():
64
53
  fail(f"File not found: {args.description_file}")
65
- mutation_input["description"] = path.read_text()
54
+ body["description"] = path.read_text()
66
55
  updated_fields.append("description")
67
56
  elif args.description is not None:
68
- mutation_input["description"] = args.description
57
+ body["description"] = args.description
69
58
  updated_fields.append("description")
70
59
 
71
- if not mutation_input and not args.comment:
72
- fail("No fields to update. Use --title, --priority, --estimate, --assignee, --state, --description, or --comment")
73
-
74
- # Single mutation for all field updates
75
- result = None
76
- if mutation_input:
77
- result = client.query(
78
- """mutation($id: String!, $input: IssueUpdateInput!) {
79
- issueUpdate(id: $id, input: $input) {
80
- success
81
- issue { identifier title state { name } assignee { name } priority estimate }
82
- }
83
- }""",
84
- {"id": issue_uuid, "input": mutation_input},
85
- )
86
- if not result.get("data", {}).get("issueUpdate", {}).get("success"):
87
- fail(f"Failed to update: {result}")
88
-
89
- # Comment is a separate mutation (Linear doesn't combine these)
90
- if args.comment:
91
- client.query(
92
- """mutation($id: String!, $body: String!) {
93
- commentCreate(input: { issueId: $id, body: $body }) { success }
94
- }""",
95
- {"id": issue_uuid, "body": args.comment},
96
- )
60
+ if args.labels is not None:
61
+ body["labels"] = [l.strip() for l in args.labels.split(",") if l.strip()]
62
+ updated_fields.append("labels")
63
+
64
+ if args.comment is not None:
65
+ body["comment"] = args.comment
97
66
  updated_fields.append("comment")
98
67
 
99
- issue = {}
100
- if result:
101
- issue = result["data"]["issueUpdate"]["issue"]
68
+ if not body:
69
+ fail("No fields to update. Use --title, --priority, --estimate, --assignee, --state, --description, --labels, or --comment")
70
+
71
+ client = get_client()
72
+ result = client.patch(f"/issues/{args.ref}", body)
102
73
 
103
74
  output_json({
104
- "success": True,
105
- "issue": issue.get("identifier", args.ref),
75
+ "success": result.get("success", True),
76
+ "issue": result.get("issue", args.ref),
106
77
  "updated": updated_fields,
107
78
  })
108
79
 
@@ -15,16 +15,25 @@
15
15
  # → Value auto-loads when you cd into the project!
16
16
  #
17
17
  # Option B: Add to shell profile (~/.zshrc)
18
- # export LINEAR_API_KEY="your_key_here"
18
+ # export FLYDOCS_API_KEY="your_key_here"
19
19
  #
20
20
  # Option C: Export manually before opening Cursor
21
21
  # source .env && cursor .
22
22
  #
23
23
 
24
24
  # ===========================================
25
- # CLOUD TIER ONLY: Linear API Key
25
+ # CLOUD TIER: FlyDocs API Key (Recommended)
26
26
  # ===========================================
27
- # Only needed if you use cloud tier (tier: "cloud" in .flydocs/config.json)
27
+ # Use this if connecting via FlyDocs Cloud (managed relay).
28
+ # Get from: your FlyDocs dashboard → API Keys
29
+ # Format: fdk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
30
+ # Set up with: flydocs connect
31
+ FLYDOCS_API_KEY=
32
+
33
+ # ===========================================
34
+ # CLOUD TIER: Direct Linear API Key (Legacy)
35
+ # ===========================================
36
+ # Use this ONLY if connecting directly to Linear without the relay.
28
37
  # Get from: Linear → Settings → API → Personal API Keys
29
38
  # Format: lin_api_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
30
39
  LINEAR_API_KEY=
@@ -45,9 +54,9 @@ FIGMA_ACCESS_TOKEN=
45
54
  CONTEXT7_API_KEY=
46
55
 
47
56
  # ===========================================
48
- # NOTE: Team ID and Project ID are discovered automatically
57
+ # NOTE: Provider configuration is discovered automatically
49
58
  # ===========================================
50
59
  # Run /flydocs-setup and the agent will:
51
- # 1. Query your Linear teams (you select one)
52
- # 2. Query projects in that team (you select one)
53
- # 3. Save both IDs to .flydocs/config.json
60
+ # 1. Detect your provider connection
61
+ # 2. Query teams and projects (you select)
62
+ # 3. Save IDs to .flydocs/config.json
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.5.0-beta.9",
2
+ "version": "0.6.0-alpha.2",
3
3
  "sourceRepo": "github.com/plastrlab/flydocs-core",
4
4
  "tier": "local",
5
5
  "setupComplete": false,
@@ -1 +1 @@
1
- 0.5.0-beta.9
1
+ 0.6.0-alpha.2
@@ -7,6 +7,150 @@ Versioning: [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  ---
9
9
 
10
+ ## [0.6.0-alpha.1] — 2026-03-12
11
+
12
+ ### Added
13
+
14
+ - **Cloud relay scripts** — all cloud mechanism scripts rewritten as thin REST
15
+ wrappers calling the FlyDocs Relay API (`app.flydocs.ai/api/relay`). Provider
16
+ translation (Linear, Jira) happens server-side.
17
+ - **Team discovery** — new `list_teams.py` and `set_team.py` scripts for
18
+ discovering available teams and storing team preference on the relay.
19
+ - **Label configuration** — new `list_labels.py` and `set_labels.py` scripts
20
+ for server-side label resolution. Labels are configured per API key with
21
+ defaults and type-to-label mapping.
22
+ - **`--labels` flag** — `create_issue.py` and `update_issue.py` now accept
23
+ optional `--labels "name1,name2"` for ad-hoc labels alongside the `type` field.
24
+ - **Cloud tier install** — `flydocs install` supports tier selection (local/cloud).
25
+ Cloud installs the relay mechanism skill and premium skills.
26
+ - **`flydocs connect`** — new command to validate and store `fdk_` API keys.
27
+ - **`/flydocs-upgrade`** — upgrade from local to cloud tier.
28
+ - **Alpha dist-tag** — `-alpha.x` versions publish to npm `alpha` dist-tag.
29
+
30
+ ### Changed
31
+
32
+ - **Setup flow updated** — `/flydocs-setup` Phase 2 now uses `list_teams.py`
33
+ for team discovery, `set_team.py` for selection, and `list_labels.py` +
34
+ `set_labels.py` for label configuration with auto-detection.
35
+ - **API key reference** — setup instructions now reference `FLYDOCS_API_KEY`
36
+ instead of `LINEAR_API_KEY`.
37
+ - **Relay URL** — `app.flydocs.ai/api/relay` (same Vercel deployment, no
38
+ separate API domain). Override with `FLYDOCS_RELAY_URL` env var.
39
+
40
+ ---
41
+
42
+ ## [0.5.0-beta.19] — 2026-02-27
43
+
44
+ ### Fixed
45
+
46
+ - **Install always confirms before proceeding** — the "Install FlyDocs here?"
47
+ prompt now shows even when an existing config is detected. Previously, reinstalls
48
+ with an existing `.flydocs/config.json` skipped the confirmation entirely.
49
+
50
+ ---
51
+
52
+ ## [0.5.0-beta.18] — 2026-02-27
53
+
54
+ ### Changed
55
+
56
+ - **Telemetry disabled by default** — analytics are opt-in only. No data is sent
57
+ until a user explicitly runs `flydocs telemetry enable`. Removed first-run notice.
58
+
59
+ ---
60
+
61
+ ## [0.5.0-beta.17] — 2026-02-26
62
+
63
+ ### Added
64
+
65
+ - **Anonymous usage analytics** — opt-in PostHog telemetry tracks install/update
66
+ funnel events (started, tier selected, completed). No personal data or code
67
+ collected. Opt out with `flydocs telemetry disable` or `FLYDOCS_TELEMETRY=0`.
68
+ - **`flydocs telemetry` command** — `enable`, `disable`, `status` subcommands
69
+ for managing anonymous analytics.
70
+ - **`flydocs uninstall` command** — cleanly removes FlyDocs from a project.
71
+ Interactive mode prompts to archive or delete user content. Supports `--force`,
72
+ `--all`, `--yes`, `--here`, `--path` flags. Preserves community skills and `.env`.
73
+
74
+ ---
75
+
76
+ ## [0.5.0-beta.16] — 2026-02-24
77
+
78
+ ### Changed
79
+
80
+ - **Premium skills are cloud-only** — `flydocs-figma` and `flydocs-estimates` are no
81
+ longer installed on local tier. Existing local installs have them cleaned up on
82
+ next update. Core skills (workflow, context-graph, context7) remain on all tiers.
83
+
84
+ ---
85
+
86
+ ## [0.5.0-beta.15] — 2026-02-24
87
+
88
+ ### Changed
89
+
90
+ - **CTA links use full URLs** — Discord and flydocs.ai links now display as full URLs
91
+ (`https://discord.com/invite/...`, `https://www.flydocs.ai`) for terminal compatibility.
92
+ Discord section shows "Join the Discord" heading with invite link on its own line.
93
+ Setup command CTA updated to match.
94
+
95
+ ---
96
+
97
+ ## [0.5.0-beta.14] — 2026-02-24
98
+
99
+ ### Changed
100
+
101
+ - **Discord CTA restyled** — "Join the Discord" is now a bold cyan clickable hyperlink
102
+ with descriptive copy ("for upcoming features, support, and early access to what's
103
+ next"), matching the docs page CTA style. "flydocs.ai" link also bold cyan and clickable.
104
+
105
+ ---
106
+
107
+ ## [0.5.0-beta.13] — 2026-02-24
108
+
109
+ ### Changed
110
+
111
+ - **New ASCII banner** — gradient block-letter "FlyDocs" heading with subtle drop shadow,
112
+ replacing the block mark logo. Pink-to-purple gradient matches brand colors using true
113
+ color (24-bit) escape sequences. Tagline in bold white, version label in dim.
114
+
115
+ ---
116
+
117
+ ## [0.5.0-beta.12] — 2026-02-24
118
+
119
+ ### Changed
120
+
121
+ - **Optional sub-agents** — sub-agents (PM, implementation, review, research) are now
122
+ an opt-in prompt during install and update. Recommended but not required. Existing
123
+ installs are silently updated on next `flydocs update`.
124
+ - **Removed hardcoded model selections** — Claude Code agent files no longer specify
125
+ `model: opus` or `model: sonnet`. Agents inherit the user's configured model,
126
+ matching the Cursor agent behavior.
127
+ - **CLI copy alignment** — banner tagline updated to "Structured context for AI coding
128
+ tools", beta CTA refocused on Discord community, docs references point to flydocs.ai.
129
+ - **Setup command CTA** — updated to show community links (Discord, flydocs.ai) and
130
+ upcoming features instead of "join the beta" messaging.
131
+
132
+ ---
133
+
134
+ ## [0.5.0-beta.11] — 2026-02-23
135
+
136
+ ### Fixed
137
+
138
+ - **Beta CTA hyperlink** — fixed OSC 8 escape sequence (BEL terminator, color inside
139
+ hyperlink wrapper). Display text changed to `https://www.flydocs.ai` for terminals
140
+ that don't support clickable links. UTM tracking preserved in the link target.
141
+
142
+ ---
143
+
144
+ ## [0.5.0-beta.10] — 2026-02-22
145
+
146
+ ### Fixed
147
+
148
+ - **`.env.example` not updating** — reclassified from `template_files` to `owned_files`
149
+ in manifest. Now overwritten on update so new config entries (like `CONTEXT7_API_KEY`)
150
+ and copy fixes propagate to existing installations.
151
+
152
+ ---
153
+
10
154
  ## [0.5.0-beta.9] — 2026-02-22
11
155
 
12
156
  ### Changed
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.5.0-beta.9",
2
+ "version": "0.6.0-alpha.2",
3
3
  "description": "FlyDocs Core - Manifest of all managed files",
4
4
  "repository": "github.com/plastrlab/flydocs-core",
5
5
 
@@ -36,6 +36,7 @@
36
36
  ".claude/commands/close.md",
37
37
  ".claude/commands/flydocs-setup.md",
38
38
  ".claude/commands/flydocs-update.md",
39
+ ".claude/commands/flydocs-upgrade.md",
39
40
  ".claude/commands/implement.md",
40
41
  ".claude/commands/new-project.md",
41
42
  ".claude/commands/project-update.md",
@@ -49,7 +50,8 @@
49
50
  ".cursor/hooks.json",
50
51
  ".flydocs/version",
51
52
  ".flydocs/CHANGELOG.md",
52
- "AGENTS.md"
53
+ "AGENTS.md",
54
+ ".env.example"
53
55
  ]
54
56
  },
55
57
 
@@ -88,7 +90,6 @@
88
90
  "template_files": {
89
91
  "description": "Initial scaffolding - created on setup, then maintained by user as project evolves",
90
92
  "paths": [
91
- ".env.example",
92
93
  "flydocs/context/project.md",
93
94
  "flydocs/knowledge/INDEX.md",
94
95
  "flydocs/knowledge/README.md",
@@ -122,6 +123,7 @@
122
123
  "close.md",
123
124
  "flydocs-setup.md",
124
125
  "flydocs-update.md",
126
+ "flydocs-upgrade.md",
125
127
  "implement.md",
126
128
  "new-project.md",
127
129
  "project-update.md",