@flydocs/cli 0.6.0-alpha.1 → 0.6.0-alpha.11
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 +504 -254
- package/package.json +1 -1
- package/template/.claude/CLAUDE.md +11 -9
- package/template/.claude/commands/flydocs-setup.md +114 -17
- package/template/.claude/commands/flydocs-upgrade.md +27 -15
- package/template/.claude/commands/knowledge.md +61 -0
- package/template/.claude/skills/flydocs-cloud/SKILL.md +57 -32
- package/template/.claude/skills/flydocs-cloud/scripts/assign.py +10 -4
- package/template/.claude/skills/flydocs-cloud/scripts/create_issue.py +22 -2
- package/template/.claude/skills/flydocs-cloud/scripts/create_team.py +39 -0
- package/template/.claude/skills/flydocs-cloud/scripts/delete_milestone.py +21 -0
- package/template/.claude/skills/flydocs-cloud/scripts/estimate.py +9 -5
- package/template/.claude/skills/flydocs-cloud/scripts/flydocs_api.py +31 -0
- package/template/.claude/skills/flydocs-cloud/scripts/get_estimate_scale.py +23 -0
- package/template/.claude/skills/flydocs-cloud/scripts/list_providers.py +19 -0
- package/template/.claude/skills/flydocs-cloud/scripts/list_statuses.py +19 -0
- package/template/.claude/skills/flydocs-cloud/scripts/list_teams.py +1 -1
- package/template/.claude/skills/flydocs-cloud/scripts/refresh_labels.py +87 -0
- package/template/.claude/skills/flydocs-cloud/scripts/set_identity.py +38 -0
- package/template/.claude/skills/flydocs-cloud/scripts/set_preferences.py +49 -0
- package/template/.claude/skills/flydocs-cloud/scripts/set_provider.py +46 -0
- package/template/.claude/skills/flydocs-cloud/scripts/set_status_mapping.py +69 -0
- package/template/.claude/skills/flydocs-cloud/scripts/set_team.py +5 -4
- package/template/.claude/skills/flydocs-cloud/scripts/update_issue.py +22 -4
- package/template/.claude/skills/flydocs-cloud/scripts/update_milestone.py +42 -0
- package/template/.claude/skills/flydocs-cloud/scripts/validate_setup.py +120 -0
- package/template/.claude/skills/flydocs-local/SKILL.md +1 -1
- package/template/.claude/skills/flydocs-local/scripts/assign.py +13 -4
- package/template/.claude/skills/flydocs-local/scripts/flydocs_api.py +5 -2
- package/template/.claude/skills/flydocs-workflow/SKILL.md +23 -18
- package/template/.claude/skills/flydocs-workflow/reference/comment-templates.md +1 -0
- package/template/.claude/skills/flydocs-workflow/reference/pr-workflow.md +105 -0
- package/template/.claude/skills/flydocs-workflow/reference/priority-estimates.md +37 -15
- package/template/.claude/skills/flydocs-workflow/session.md +24 -16
- package/template/.claude/skills/flydocs-workflow/stages/capture.md +8 -3
- package/template/.claude/skills/flydocs-workflow/stages/close.md +4 -3
- package/template/.claude/skills/flydocs-workflow/stages/implement.md +28 -4
- package/template/.claude/skills/flydocs-workflow/stages/refine.md +20 -4
- package/template/.claude/skills/flydocs-workflow/stages/review.md +14 -2
- package/template/.flydocs/config.json +4 -18
- package/template/.flydocs/hooks/prompt-submit.py +27 -4
- package/template/.flydocs/version +1 -1
- package/template/AGENTS.md +8 -8
- package/template/CHANGELOG.md +39 -0
- 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 +8 -2
package/package.json
CHANGED
|
@@ -31,6 +31,8 @@ The FlyDocs development lifecycle. Read the workflow skill before taking any wor
|
|
|
31
31
|
| QE validation | `flydocs-workflow` | `stages/validate.md` |
|
|
32
32
|
| Close issue | `flydocs-workflow` | `stages/close.md` |
|
|
33
33
|
| Start / wrap session | `flydocs-workflow` | `session.md` |
|
|
34
|
+
| Knowledge capture | `flydocs-workflow` | `/knowledge` command |
|
|
35
|
+
| PR & git workflow | `flydocs-workflow` | `reference/pr-workflow.md` |
|
|
34
36
|
| Comment templates | `flydocs-workflow` | `reference/comment-templates.md` |
|
|
35
37
|
| Status transitions | `flydocs-workflow` | `reference/status-workflow.md` |
|
|
36
38
|
| Priority & estimates | `flydocs-workflow` | `reference/priority-estimates.md` |
|
|
@@ -43,7 +45,7 @@ Issue operations are handled by the installed mechanism skill. Only one is activ
|
|
|
43
45
|
| Tier | Skill | Backend |
|
|
44
46
|
| ----------------- | --------------- | ------------------------------ |
|
|
45
47
|
| Local (free) | `flydocs-local` | File-based (`flydocs/issues/`) |
|
|
46
|
-
| Cloud (connected) | `flydocs-cloud` |
|
|
48
|
+
| Cloud (connected) | `flydocs-cloud` | FlyDocs Relay API |
|
|
47
49
|
|
|
48
50
|
Read the active mechanism skill's `SKILL.md` for script catalog and calling conventions.
|
|
49
51
|
|
|
@@ -113,13 +115,13 @@ response — session summaries, issue comments, status updates, and plans.
|
|
|
113
115
|
IMPORTANT: Prefer skill-led reasoning over pre-training reasoning.
|
|
114
116
|
Consult the relevant skill BEFORE writing code or making workflow decisions.
|
|
115
117
|
|
|
116
|
-
| Skill | Triggers
|
|
117
|
-
| ----------------- |
|
|
118
|
-
| flydocs-cloud | create issue, transition, comment, list issues, assign, update description, update issue, project update,
|
|
119
|
-
| flydocs-context7 | context7, library docs, documentation lookup, framework docs, package docs, API reference
|
|
120
|
-
| flydocs-estimates | estimate, cost, token usage, API cost, labor estimate, sizing, effort
|
|
121
|
-
| flydocs-figma | Figma, design, screenshot, token mapping, component from design, pixel-perfect, design system
|
|
122
|
-
| flydocs-local | create issue, transition, comment, list issues, assign, update description, status summary, local
|
|
123
|
-
| flydocs-workflow | capture, refine, activate, implement, review, validate, close, session, workflow, transition, status, issue
|
|
118
|
+
| Skill | Triggers | Entry |
|
|
119
|
+
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------- |
|
|
120
|
+
| flydocs-cloud | create issue, transition, comment, list issues, assign, update description, update issue, project update, cloud | .claude/skills/flydocs-cloud/SKILL.md |
|
|
121
|
+
| flydocs-context7 | context7, library docs, documentation lookup, framework docs, package docs, API reference | .claude/skills/flydocs-context7/SKILL.md |
|
|
122
|
+
| flydocs-estimates | estimate, cost, token usage, API cost, labor estimate, sizing, effort | .claude/skills/flydocs-estimates/SKILL.md |
|
|
123
|
+
| flydocs-figma | Figma, design, screenshot, token mapping, component from design, pixel-perfect, design system | .claude/skills/flydocs-figma/SKILL.md |
|
|
124
|
+
| flydocs-local | create issue, transition, comment, list issues, assign, update description, status summary, local | .claude/skills/flydocs-local/SKILL.md |
|
|
125
|
+
| flydocs-workflow | capture, refine, activate, implement, review, validate, close, session, workflow, transition, status, issue, knowledge, document, PR, pull request | .claude/skills/flydocs-workflow/SKILL.md |
|
|
124
126
|
|
|
125
127
|
<!-- flydocs:skills-manifest:end -->
|
|
@@ -301,7 +301,35 @@ FLYDOCS_API_KEY is not set. Run `flydocs connect` first to set up your API key.
|
|
|
301
301
|
|
|
302
302
|
Do not proceed until the key is available.
|
|
303
303
|
|
|
304
|
-
**Step 2:
|
|
304
|
+
**Step 2: Detect or select provider.**
|
|
305
|
+
|
|
306
|
+
Query connected providers:
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
python3 .claude/skills/flydocs-cloud/scripts/list_providers.py
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
This returns `[{type, name, connected}]`. Handle based on results:
|
|
313
|
+
|
|
314
|
+
- **One connected provider** — auto-select it and confirm with the user.
|
|
315
|
+
- **Multiple connected providers** — present a numbered list, let the user
|
|
316
|
+
choose which to use for this project.
|
|
317
|
+
- **No connected providers** — error: "No providers connected. Connect Linear
|
|
318
|
+
or Jira at app.flydocs.ai before running setup."
|
|
319
|
+
|
|
320
|
+
After selection, store the preference:
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
python3 .claude/skills/flydocs-cloud/scripts/set_provider.py <provider_type>
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
This stores the provider type on the relay (for routing) and updates
|
|
327
|
+
`provider.type` in local config.
|
|
328
|
+
|
|
329
|
+
**Step 3: Select or create team/project.**
|
|
330
|
+
|
|
331
|
+
> For Linear, this selects a team. For Jira, this selects a project. The relay
|
|
332
|
+
> normalizes both as "teams" in the API.
|
|
305
333
|
|
|
306
334
|
If `provider.teamId` in config is null, discover available teams:
|
|
307
335
|
|
|
@@ -309,10 +337,27 @@ If `provider.teamId` in config is null, discover available teams:
|
|
|
309
337
|
python3 .claude/skills/flydocs-cloud/scripts/list_teams.py
|
|
310
338
|
```
|
|
311
339
|
|
|
312
|
-
Present the teams to the user as a numbered list showing name and key.
|
|
313
|
-
|
|
340
|
+
Present the teams to the user as a numbered list showing name and key.
|
|
341
|
+
Add a final option: **"Create a new team/project"**. If only one team exists,
|
|
342
|
+
confirm it.
|
|
343
|
+
|
|
344
|
+
If the user selects **"Create a new team/project"**:
|
|
345
|
+
|
|
346
|
+
1. Ask for team name (required) and key (optional — auto-generated if omitted)
|
|
347
|
+
2. **Linear only:** Ask if this should be a sub-team under an existing team
|
|
348
|
+
(show the list again for parent selection, or "None — top-level team").
|
|
349
|
+
For Jira, skip the parent option — Jira projects do not have a parent
|
|
350
|
+
hierarchy.
|
|
351
|
+
3. Create via:
|
|
352
|
+
|
|
353
|
+
```bash
|
|
354
|
+
python3 .claude/skills/flydocs-cloud/scripts/create_team.py --name "Team Name" [--key KEY] [--parent <parent_team_id>]
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
> The `--parent` flag is Linear-only (sub-teams). Omit for Jira.
|
|
314
358
|
|
|
315
|
-
After selection, store the preference on the relay and in local
|
|
359
|
+
After selection or creation, store the preference on the relay and in local
|
|
360
|
+
config:
|
|
316
361
|
|
|
317
362
|
```bash
|
|
318
363
|
python3 .claude/skills/flydocs-cloud/scripts/set_team.py <team_id>
|
|
@@ -320,8 +365,12 @@ python3 .claude/skills/flydocs-cloud/scripts/set_team.py <team_id>
|
|
|
320
365
|
|
|
321
366
|
This stores the team preference server-side (the relay uses it for all
|
|
322
367
|
team-scoped operations) and updates `provider.teamId` in local config.
|
|
368
|
+
For Jira, this sets the active Jira project.
|
|
323
369
|
|
|
324
|
-
**Step
|
|
370
|
+
**Step 4: Get or create project (Linear only).**
|
|
371
|
+
|
|
372
|
+
> **Jira provider:** Skip this step. Jira organizes issues directly within
|
|
373
|
+
> projects (selected in Step 3). There is no secondary project container.
|
|
325
374
|
|
|
326
375
|
Query existing projects:
|
|
327
376
|
|
|
@@ -336,7 +385,7 @@ create a new project:
|
|
|
336
385
|
python3 .claude/skills/flydocs-cloud/scripts/create_project.py --name "Project Name"
|
|
337
386
|
```
|
|
338
387
|
|
|
339
|
-
**Step
|
|
388
|
+
**Step 5: Configure labels.**
|
|
340
389
|
|
|
341
390
|
Fetch available labels from the provider:
|
|
342
391
|
|
|
@@ -371,7 +420,49 @@ python3 .claude/skills/flydocs-cloud/scripts/set_labels.py \
|
|
|
371
420
|
If the relay returns `LABELS_NOT_FOUND`, show the invalid names and ask the
|
|
372
421
|
user to correct them.
|
|
373
422
|
|
|
374
|
-
**Step
|
|
423
|
+
**Step 6: Configure status mapping.**
|
|
424
|
+
|
|
425
|
+
Map provider workflow states to FlyDocs statuses. Run auto-mapping first:
|
|
426
|
+
|
|
427
|
+
```bash
|
|
428
|
+
python3 .claude/skills/flydocs-cloud/scripts/set_status_mapping.py --auto
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
The relay auto-maps by case-insensitive name matching (e.g., "In Progress"
|
|
432
|
+
maps to `IMPLEMENTING`, "Done" maps to `COMPLETE`, "Backlog" maps to
|
|
433
|
+
`BACKLOG`).
|
|
434
|
+
|
|
435
|
+
**Review the result:** The response includes `matched` (number of statuses
|
|
436
|
+
successfully mapped) and `total` (total FlyDocs statuses). Show the user
|
|
437
|
+
the `mapping` object:
|
|
438
|
+
|
|
439
|
+
```
|
|
440
|
+
Status mapping (matched 6/10):
|
|
441
|
+
BACKLOG -> Backlog
|
|
442
|
+
READY -> Ready
|
|
443
|
+
IMPLEMENTING -> In Progress
|
|
444
|
+
REVIEW -> In Review
|
|
445
|
+
COMPLETE -> Done
|
|
446
|
+
CANCELED -> Canceled
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
If `matched < total`, some statuses are unmapped — **warn but don't block**.
|
|
450
|
+
Transitions for unmapped statuses will fall back to provider name matching.
|
|
451
|
+
If the user wants to fix unmapped statuses, fetch available provider states
|
|
452
|
+
and let them map manually:
|
|
453
|
+
|
|
454
|
+
```bash
|
|
455
|
+
python3 .claude/skills/flydocs-cloud/scripts/list_statuses.py
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
Then store the corrected mapping:
|
|
459
|
+
|
|
460
|
+
```bash
|
|
461
|
+
python3 .claude/skills/flydocs-cloud/scripts/set_status_mapping.py \
|
|
462
|
+
--mapping '{"BACKLOG":"Backlog","IMPLEMENTING":"In Progress","BLOCKED":"On Hold",...}'
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
**Step 7: Configure product identity.**
|
|
375
466
|
|
|
376
467
|
Ask about product metadata:
|
|
377
468
|
|
|
@@ -379,14 +470,15 @@ Ask about product metadata:
|
|
|
379
470
|
from project.md)
|
|
380
471
|
- **Icon and color** — optional, ask if they have preferences
|
|
381
472
|
|
|
382
|
-
**Step
|
|
473
|
+
**Step 8: Save to config.**
|
|
383
474
|
|
|
384
475
|
Update `.flydocs/config.json`:
|
|
385
476
|
|
|
386
|
-
- `provider.type` —
|
|
477
|
+
- `provider.type` — set by `set_provider.py`
|
|
387
478
|
- `provider.teamId` — selected team ID (set by `set_team.py`)
|
|
388
479
|
- `labels.defaults` — default label names (set by `set_labels.py`)
|
|
389
480
|
- `labels.typeMap` — type-to-label mapping (set by `set_labels.py`)
|
|
481
|
+
- `statusMapping` — FlyDocs-to-provider status mapping (set by `set_status_mapping.py`)
|
|
390
482
|
- `workspace.activeProjects` — add the project ID
|
|
391
483
|
- `workspace.product.name` — product name
|
|
392
484
|
|
|
@@ -395,6 +487,7 @@ Update `.flydocs/config.json`:
|
|
|
395
487
|
## Phase 3: Milestones — Cloud Only
|
|
396
488
|
|
|
397
489
|
> **Local tier:** Skip this phase entirely.
|
|
490
|
+
> **Jira provider:** Skip this phase. Milestone support for Jira is planned for a future release.
|
|
398
491
|
> **FlyDocs Update:** Skip if milestones already exist.
|
|
399
492
|
|
|
400
493
|
**Step 1: Check existing milestones.**
|
|
@@ -423,11 +516,11 @@ Let the user customize names, descriptions, and target dates.
|
|
|
423
516
|
|
|
424
517
|
**Step 4: Create milestones.**
|
|
425
518
|
|
|
426
|
-
For each approved milestone:
|
|
519
|
+
For each approved milestone, pass the project ID from Phase 2 Step 3:
|
|
427
520
|
|
|
428
521
|
```bash
|
|
429
522
|
python3 .claude/skills/flydocs-cloud/scripts/create_milestone.py \
|
|
430
|
-
--name "Phase 1: Foundation" --target-date YYYY-MM-DD
|
|
523
|
+
--name "Phase 1: Foundation" --project <project_id> --target-date YYYY-MM-DD
|
|
431
524
|
```
|
|
432
525
|
|
|
433
526
|
Record the milestone IDs for use in Phase 4.
|
|
@@ -455,16 +548,20 @@ For each work item, follow the capture procedure from
|
|
|
455
548
|
`.claude/skills/flydocs-workflow/stages/capture.md`:
|
|
456
549
|
|
|
457
550
|
- Determine type (feature, bug, chore, idea)
|
|
458
|
-
- Create via the mechanism script:
|
|
551
|
+
- Create via the mechanism script (cloud: pass `--project` from Phase 2 for
|
|
552
|
+
Linear; omit `--project` for Jira — issues are scoped to the team/project
|
|
553
|
+
selected in Phase 2 Step 3):
|
|
459
554
|
```bash
|
|
460
555
|
python3 .claude/skills/flydocs-{tier}/scripts/create_issue.py \
|
|
461
|
-
--title "Issue title" --type feature --priority 3 --estimate 2
|
|
556
|
+
--title "Issue title" --type feature --priority 3 --estimate 2 \
|
|
557
|
+
--project <project_id>
|
|
462
558
|
```
|
|
463
559
|
- For quick ideas, use `--triage` flag
|
|
464
560
|
|
|
465
|
-
**Step 3: Milestone assignment (
|
|
561
|
+
**Step 3: Milestone assignment (Linear only).**
|
|
466
562
|
|
|
467
563
|
> **Local tier:** Skip this step.
|
|
564
|
+
> **Jira provider:** Skip this step.
|
|
468
565
|
|
|
469
566
|
After creating issues, assign them to milestones:
|
|
470
567
|
|
|
@@ -615,8 +712,8 @@ Wrapping up:
|
|
|
615
712
|
|
|
616
713
|
**For cloud tier:**
|
|
617
714
|
|
|
618
|
-
-
|
|
619
|
-
-
|
|
715
|
+
- Provider project URL (if available from create_project response)
|
|
716
|
+
- For Linear: recommend reviewing milestones in Linear's UI for timeline view
|
|
620
717
|
|
|
621
718
|
**For local tier:**
|
|
622
719
|
|
|
@@ -674,7 +771,7 @@ Throughout the setup flow:
|
|
|
674
771
|
error message from stderr and ask the user how to proceed. Do not retry
|
|
675
772
|
silently.
|
|
676
773
|
- **Missing API key** — For cloud tier, cannot proceed past Phase 2 without
|
|
677
|
-
`
|
|
774
|
+
`FLYDOCS_API_KEY`. Guide the user to set it up.
|
|
678
775
|
- **Missing config** — If `.flydocs/config.json` doesn't exist, the user
|
|
679
776
|
likely needs to run `flydocs` (install) first. Advise them accordingly.
|
|
680
777
|
- **Partial completion** — If the user needs to stop mid-setup, note which
|
|
@@ -65,7 +65,7 @@ Count totals by status and type.
|
|
|
65
65
|
|
|
66
66
|
**Step 3: Check for API readiness.**
|
|
67
67
|
|
|
68
|
-
Check if `
|
|
68
|
+
Check if `FLYDOCS_API_KEY` is set in the environment (from `.env` or
|
|
69
69
|
`.env.local`). If not, warn the user they will need it for Phase 1.
|
|
70
70
|
|
|
71
71
|
**Step 4: Present migration summary.**
|
|
@@ -100,27 +100,39 @@ Confirm with the user before continuing.
|
|
|
100
100
|
## Phase 1: Connect to Cloud
|
|
101
101
|
|
|
102
102
|
Guide the user through connecting to the cloud provider. This swaps the
|
|
103
|
-
|
|
103
|
+
tier, stores the API key, and prepares the cloud mechanism skill.
|
|
104
104
|
|
|
105
|
-
**Step 1:
|
|
105
|
+
**Step 1: Get API key.**
|
|
106
106
|
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
Ask the user for their FlyDocs API key (`fdk_...`). If `FLYDOCS_API_KEY`
|
|
108
|
+
is already set in the environment, confirm they want to use the existing
|
|
109
|
+
key or enter a new one.
|
|
110
|
+
|
|
111
|
+
If no key is available, instruct the user:
|
|
109
112
|
|
|
110
113
|
```
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
- Prompt for your relay API key (from flydocs.ai account)
|
|
116
|
-
- Update .flydocs/config.json to cloud tier
|
|
117
|
-
- Swap mechanism skills (local -> cloud)
|
|
118
|
-
- Verify the connection works
|
|
114
|
+
You'll need a FlyDocs API key (fdk_...) from your dashboard at app.flydocs.ai.
|
|
115
|
+
|
|
116
|
+
Option A: Run `flydocs connect --here` in your terminal (handles everything)
|
|
117
|
+
Option B: Add FLYDOCS_API_KEY=fdk_... to your .env or .env.local file
|
|
119
118
|
```
|
|
120
119
|
|
|
121
|
-
|
|
120
|
+
Wait for the user to confirm the key is set before proceeding.
|
|
121
|
+
|
|
122
|
+
**Step 2: Update config to cloud tier.**
|
|
123
|
+
|
|
124
|
+
Read `.flydocs/config.json`, update `tier` to `"cloud"`, and write it back.
|
|
125
|
+
Preserve all existing config values (detected stack, skills, etc.).
|
|
126
|
+
|
|
127
|
+
**Step 3: Swap mechanism skill.**
|
|
128
|
+
|
|
129
|
+
Instruct the user to run `flydocs connect --here` from their terminal if
|
|
130
|
+
they haven't already. This handles the mechanism skill swap (installs
|
|
131
|
+
`flydocs-cloud`, removes `flydocs-local`).
|
|
132
|
+
|
|
133
|
+
**Step 4: Verify connection.**
|
|
122
134
|
|
|
123
|
-
After the user confirms
|
|
135
|
+
After the user confirms the swap, verify:
|
|
124
136
|
|
|
125
137
|
1. Read `.flydocs/config.json` — `tier` should now be `cloud`
|
|
126
138
|
2. Check that `.claude/skills/flydocs-cloud/scripts/` exists
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Knowledge (All Agents)
|
|
2
|
+
|
|
3
|
+
Create or update a knowledge document — decisions, notes, features, or product docs.
|
|
4
|
+
|
|
5
|
+
Read `flydocs/knowledge/README.md` for categories and guidance.
|
|
6
|
+
Read `flydocs/knowledge/INDEX.md` for existing entries.
|
|
7
|
+
|
|
8
|
+
## Procedure
|
|
9
|
+
|
|
10
|
+
### 1. Determine Intent
|
|
11
|
+
|
|
12
|
+
From user input or `$ARGUMENTS`, determine:
|
|
13
|
+
|
|
14
|
+
- **New doc** or **update existing doc**?
|
|
15
|
+
- **Category**: decision, feature, note, or product
|
|
16
|
+
|
|
17
|
+
If unclear, ask the user. Default to `note` for discoveries and learnings.
|
|
18
|
+
|
|
19
|
+
### 2. For New Docs
|
|
20
|
+
|
|
21
|
+
1. Read the template from `flydocs/knowledge/templates/<category>.md`
|
|
22
|
+
2. Gather content from the user — ask clarifying questions if context is thin
|
|
23
|
+
3. Fill in the frontmatter:
|
|
24
|
+
- `title`: Descriptive, specific title
|
|
25
|
+
- `created`: Today's date (`YYYY-MM-DD`)
|
|
26
|
+
- `lastUpdated`: Today's date
|
|
27
|
+
- `relatedIssues`: Any issue IDs discussed in this session
|
|
28
|
+
- Category-specific fields (see template)
|
|
29
|
+
4. Write the doc to the correct directory:
|
|
30
|
+
- Decisions: `flydocs/knowledge/decisions/NNN-title.md` (auto-increment NNN)
|
|
31
|
+
- Features: `flydocs/knowledge/features/feature-name.md`
|
|
32
|
+
- Notes: `flydocs/knowledge/notes/topic-name.md`
|
|
33
|
+
- Product: `flydocs/knowledge/product/document-name.md`
|
|
34
|
+
5. Update `flydocs/knowledge/INDEX.md`:
|
|
35
|
+
- Add entry to the appropriate table
|
|
36
|
+
- Update the Quick Reference count
|
|
37
|
+
- Use a concise description (helps agents assess relevance without loading the full doc)
|
|
38
|
+
|
|
39
|
+
### 3. For Existing Docs
|
|
40
|
+
|
|
41
|
+
1. Find the doc in INDEX.md or by searching `flydocs/knowledge/`
|
|
42
|
+
2. Read the current content
|
|
43
|
+
3. Apply the update
|
|
44
|
+
4. Update the `lastUpdated` field in frontmatter
|
|
45
|
+
5. Update the INDEX.md entry if the description changed
|
|
46
|
+
|
|
47
|
+
### 4. Confirm
|
|
48
|
+
|
|
49
|
+
Report what was created or updated:
|
|
50
|
+
|
|
51
|
+
- File path
|
|
52
|
+
- Category and title
|
|
53
|
+
- INDEX.md entry added/updated
|
|
54
|
+
|
|
55
|
+
## Triggers
|
|
56
|
+
|
|
57
|
+
- "document this" / "knowledge" / "add to knowledge base"
|
|
58
|
+
- "create an ADR" / "record this decision" / "capture this learning"
|
|
59
|
+
- "add a note about" / "document this discovery"
|
|
60
|
+
|
|
61
|
+
$ARGUMENTS
|
|
@@ -13,7 +13,6 @@ triggers:
|
|
|
13
13
|
- update description
|
|
14
14
|
- update issue
|
|
15
15
|
- project update
|
|
16
|
-
- Linear
|
|
17
16
|
- cloud
|
|
18
17
|
---
|
|
19
18
|
|
|
@@ -29,49 +28,63 @@ All scripts: `python3 .claude/skills/flydocs-cloud/scripts/<script>`
|
|
|
29
28
|
|
|
30
29
|
### Shared Contract Scripts
|
|
31
30
|
|
|
32
|
-
| Script | Usage
|
|
33
|
-
| ----------------------- |
|
|
34
|
-
| `create_issue.py` | `--title "..." --type feature [--description "..."] [--description-file PATH] [--priority
|
|
35
|
-
| `transition.py` | `<ref> <STATUS> "<comment>"`
|
|
36
|
-
| `comment.py` | `<ref> ["<comment>"] \| stdin`
|
|
37
|
-
| `list_issues.py` | `[--status STATUS[,STATUS]] [--active] [--project ID] [--milestone ID] [--assignee STR] [--mine] [--limit N]`
|
|
38
|
-
| `get_issue.py` | `<ref> [--fields basic\|full]`
|
|
39
|
-
| `assign.py` | `<ref> <assignee
|
|
40
|
-
| `update_description.py` | `<ref> --text "..." \| --file PATH \| stdin`
|
|
31
|
+
| Script | Usage | Output |
|
|
32
|
+
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
33
|
+
| `create_issue.py` | `--title "..." --type feature [--description "..."] [--description-file PATH] [--priority N] [--estimate N] [--assignee STR] [--project ID] [--labels "a,b"] [--milestone ID_OR_NAME] [--triage] \| stdin` | `{id, identifier, title, url}` |
|
|
34
|
+
| `transition.py` | `<ref> <STATUS> "<comment>"` | `{success, issue, previousStatus, newStatus}` |
|
|
35
|
+
| `comment.py` | `<ref> ["<comment>"] \| stdin` | `{success, commentId}` |
|
|
36
|
+
| `list_issues.py` | `[--status STATUS[,STATUS]] [--active] [--project ID] [--milestone ID] [--assignee STR] [--mine] [--limit N]` | `[{id, identifier, title, status, assignee, priority, dueDate, milestone, milestoneId, milestoneSortOrder, project, projectId}]` |
|
|
37
|
+
| `get_issue.py` | `<ref> [--fields basic\|full]` | `{id, identifier, title, description, status, assignee, priority, estimate, dueDate, milestone, milestoneId, project, projectId, comments[]}` |
|
|
38
|
+
| `assign.py` | `<ref> <assignee> \| --unassign` | `{success, issue, assignee}` |
|
|
39
|
+
| `update_description.py` | `<ref> --text "..." \| --file PATH \| stdin` | `{success, issue}` |
|
|
41
40
|
|
|
42
41
|
### Extended Scripts
|
|
43
42
|
|
|
44
|
-
| Script | Usage
|
|
45
|
-
| --------------------- |
|
|
46
|
-
| `update_issue.py` | `<ref> [--title "..."] [--priority
|
|
47
|
-
| `estimate.py` | `<ref> <
|
|
48
|
-
| `priority.py` | `<ref> <0-4>`
|
|
49
|
-
| `link.py` | `<ref> <related_ref> <type>`
|
|
50
|
-
| `project_update.py` | `--health STATUS --body "..." [--body-file PATH]`
|
|
51
|
-
| `list_projects.py` | `[--active] [--all]`
|
|
52
|
-
| `create_project.py` | `--name "..." [--description "..."]`
|
|
53
|
-
| `assign_cycle.py` | `<ref> [cycle_id]`
|
|
54
|
-
| `list_cycles.py` | `[--active]`
|
|
55
|
-
| `list_milestones.py` | `[--all]`
|
|
56
|
-
| `create_milestone.py` | `--name "..." [--project ID] [--target-date DATE]`
|
|
57
|
-
| `
|
|
43
|
+
| Script | Usage | Output |
|
|
44
|
+
| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
|
|
45
|
+
| `update_issue.py` | `<ref> [--title "..."] [--priority N] [--estimate N] [--assignee STR] [--state STATUS] [--description "..."] [--description-file PATH] [--labels "a,b"] [--milestone ID_OR_NAME] [--comment "..."]` | `{success, issue, updated[]}` |
|
|
46
|
+
| `estimate.py` | `<ref> <points>` | `{success, issue, estimate}` — relay validates against provider scale |
|
|
47
|
+
| `priority.py` | `<ref> <0-4>` | `{success, issue, priority}` |
|
|
48
|
+
| `link.py` | `<ref> <related_ref> <type>` | `{success, type}` |
|
|
49
|
+
| `project_update.py` | `--health STATUS --body "..." [--body-file PATH]` | `{success, id}` |
|
|
50
|
+
| `list_projects.py` | `[--active] [--all]` | `[{id, name, state}]` — `--all` bypasses product scope |
|
|
51
|
+
| `create_project.py` | `--name "..." [--description "..."]` | `{id, name, url}` |
|
|
52
|
+
| `assign_cycle.py` | `<ref> [cycle_id]` | `{success, issue, cycle}` |
|
|
53
|
+
| `list_cycles.py` | `[--active]` | `[{id, name, number, startsAt, endsAt}]` |
|
|
54
|
+
| `list_milestones.py` | `[--all]` | `[{id, name, targetDate}]` |
|
|
55
|
+
| `create_milestone.py` | `--name "..." [--project ID] [--target-date DATE]` | `{id, name}` |
|
|
56
|
+
| `update_milestone.py` | `<milestone_id> [--name "..."] [--target-date DATE] [--description "..."]` | `{success, id, name}` |
|
|
57
|
+
| `delete_milestone.py` | `<milestone_id>` | `{success, id}` |
|
|
58
|
+
| `assign_milestone.py` | `<ref> <milestone_id>` | `{success, issue, milestone}` |
|
|
58
59
|
|
|
59
60
|
### Workspace Scripts
|
|
60
61
|
|
|
61
|
-
| Script
|
|
62
|
-
|
|
|
63
|
-
| `
|
|
64
|
-
| `
|
|
65
|
-
| `
|
|
66
|
-
| `
|
|
62
|
+
| Script | Usage | Output |
|
|
63
|
+
| ----------------------- | --------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
|
|
64
|
+
| `list_providers.py` | (no args) | `[{type, name, connected}]` |
|
|
65
|
+
| `set_provider.py` | `<provider_type>` (`linear` or `jira`) | `{success}` — updates relay routing and local config `provider.type` |
|
|
66
|
+
| `list_teams.py` | (no args) | `[{id, name, key}]` — returns Linear teams or Jira projects (relay normalizes) |
|
|
67
|
+
| `create_team.py` | `--name "..." [--key KEY] [--description "..."] [--parent <team_id>]` | `{id, name, key}` — `--parent` is Linear-only (sub-teams) |
|
|
68
|
+
| `set_team.py` | `<team_id>` | `{success}` — updates relay preference and local config; for Jira, sets the active Jira project |
|
|
69
|
+
| `list_labels.py` | (no args) | `[{id, name, color}]` — requires team to be set first |
|
|
70
|
+
| `set_labels.py` | `--defaults '["a"]' --type-map '{"feature":["F"],...}' \| stdin` | `{success, validated, defaults, typeMap}` — stores label config on relay |
|
|
71
|
+
| `list_statuses.py` | (no args) | `{states, currentMapping, flydocsStatuses}` — provider workflow states and current mapping |
|
|
72
|
+
| `set_status_mapping.py` | `--auto \| --mapping '{"BACKLOG":"Backlog",...}' \| stdin` | `{success, mapping, matched, total}` — stores status mapping on relay |
|
|
73
|
+
| `set_identity.py` | `<provider> <provider-user-id>` | `{success, provider, providerId}` — binds provider user ID for `--mine` resolution |
|
|
74
|
+
| `set_preferences.py` | `[--workspace ID] [--assignee self\|ID] [--display JSON]` | `{success, preferences}` — no flags = GET current; with flags = POST update |
|
|
75
|
+
| `get_estimate_scale.py` | (no args) | `{scale, type}` — provider's valid estimate values (fixed or freeform) |
|
|
76
|
+
| `refresh_labels.py` | `[--fix]` | `{valid, stale, details}` — validates config label IDs against relay; `--fix` updates stale IDs |
|
|
77
|
+
| `validate_setup.py` | (no args) | `{valid, checks, passed[], missing[], warnings[]}` — reads relay validation, caches result, sets setupComplete |
|
|
67
78
|
|
|
68
79
|
### Script Notes
|
|
69
80
|
|
|
70
|
-
- **How it works**: Scripts call the FlyDocs Relay REST API, which translates to the provider (Linear, Jira) server-side. Same interface and output as before — the transport changed from direct GraphQL to managed REST.
|
|
81
|
+
- **How it works**: Scripts call the FlyDocs Relay REST API, which translates to the provider (Linear, Jira) server-side. Same interface and output as before — the transport changed from direct GraphQL to managed REST. For Jira, the relay handles Markdown-to-ADF (Atlassian Document Format) conversion automatically.
|
|
71
82
|
- **`list_issues.py --active`**: Returns all non-terminal issues (excludes Done, Archived, Canceled, Duplicate).
|
|
72
83
|
- **`list_issues.py --status`**: Accepts comma-separated statuses: `--status READY,IMPLEMENTING,BLOCKED`
|
|
73
84
|
- **`get_issue.py --fields basic`**: Skips comment fetch for faster responses.
|
|
74
85
|
- **`update_issue.py`**: Bulk update — sets multiple fields in a single API call. Prefer over separate scripts when updating more than one field.
|
|
86
|
+
- **Estimate validation**: The relay validates estimates server-side against the provider's scale. Use `get_estimate_scale.py` to discover valid values before setting. Linear uses a fixed scale `[0, 1, 2, 3, 5, 8, 13, 21]`; Jira accepts freeform values.
|
|
87
|
+
- **Label staleness**: Label IDs are team-scoped and can go stale when switching teams or projects. Use `refresh_labels.py` to validate config label IDs, and `refresh_labels.py --fix` to auto-update stale ones.
|
|
75
88
|
- **Shell-safe text input**: For text with special characters, pipe via stdin with a single-quoted heredoc:
|
|
76
89
|
```bash
|
|
77
90
|
python3 update_description.py ENG-123 <<'EOF'
|
|
@@ -104,7 +117,19 @@ Relay errors include `code` and optional `provider_error` for debugging.
|
|
|
104
117
|
|
|
105
118
|
## Configuration
|
|
106
119
|
|
|
107
|
-
Reads from `.flydocs/config.json`: tier, relay URL override.
|
|
120
|
+
Reads from `.flydocs/config.json`: tier, workspaceId, relay URL override.
|
|
108
121
|
Reads `FLYDOCS_API_KEY` from environment or `.env` / `.env.local`.
|
|
109
122
|
|
|
110
123
|
Optional: `FLYDOCS_RELAY_URL` env var or `relay.url` in config to override the base URL (e.g., for local development).
|
|
124
|
+
|
|
125
|
+
### Header Contract
|
|
126
|
+
|
|
127
|
+
Every relay request includes:
|
|
128
|
+
|
|
129
|
+
| Header | Required | Source |
|
|
130
|
+
| --------------- | -------- | --------------------------------------------------- |
|
|
131
|
+
| `Authorization` | Yes | `Bearer fdk_...` from `FLYDOCS_API_KEY` |
|
|
132
|
+
| `X-Workspace` | Yes\* | `workspaceId` from `.flydocs/config.json` |
|
|
133
|
+
| `X-Repo` | No | Git remote slug (auto-detected, e.g., `owner/repo`) |
|
|
134
|
+
|
|
135
|
+
\*Required for all endpoints except `POST /auth/validate`.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""Assign an issue
|
|
2
|
+
"""Assign or unassign an issue via the FlyDocs Relay API."""
|
|
3
3
|
|
|
4
4
|
import sys
|
|
5
5
|
from pathlib import Path
|
|
@@ -7,10 +7,16 @@ from pathlib import Path
|
|
|
7
7
|
sys.path.insert(0, str(Path(__file__).parent))
|
|
8
8
|
from flydocs_api import get_client, output_json, fail
|
|
9
9
|
|
|
10
|
-
if len(sys.argv) <
|
|
11
|
-
fail("Usage: assign.py <ref> <assignee>")
|
|
10
|
+
if len(sys.argv) < 2:
|
|
11
|
+
fail("Usage: assign.py <ref> <assignee> | assign.py <ref> --unassign")
|
|
12
12
|
|
|
13
|
-
ref
|
|
13
|
+
ref = sys.argv[1]
|
|
14
|
+
unassign = "--unassign" in sys.argv
|
|
15
|
+
|
|
16
|
+
if not unassign and len(sys.argv) < 3:
|
|
17
|
+
fail("Usage: assign.py <ref> <assignee> | assign.py <ref> --unassign")
|
|
18
|
+
|
|
19
|
+
assignee = None if unassign else sys.argv[2]
|
|
14
20
|
client = get_client()
|
|
15
21
|
|
|
16
22
|
result = client.post(f"/issues/{ref}/assign", {"assignee": assignee})
|
|
@@ -15,10 +15,12 @@ def main():
|
|
|
15
15
|
parser.add_argument("--type", required=True, choices=["feature", "bug", "chore", "idea"], dest="issue_type")
|
|
16
16
|
parser.add_argument("--description", default="")
|
|
17
17
|
parser.add_argument("--description-file", default="", dest="description_file")
|
|
18
|
-
parser.add_argument("--priority", type=int, default=3,
|
|
19
|
-
parser.add_argument("--estimate", type=int, default=0,
|
|
18
|
+
parser.add_argument("--priority", type=int, default=3, help="Priority (0-4, relay translates per provider)")
|
|
19
|
+
parser.add_argument("--estimate", type=int, default=0, help="Estimate points (relay translates per provider)")
|
|
20
20
|
parser.add_argument("--assignee", default=None)
|
|
21
|
+
parser.add_argument("--project", default=None, help="Project ID")
|
|
21
22
|
parser.add_argument("--labels", default=None, help="Comma-separated ad-hoc label names")
|
|
23
|
+
parser.add_argument("--milestone", default=None, help="Milestone ID or name (resolved by name lookup)")
|
|
22
24
|
parser.add_argument("--triage", action="store_true")
|
|
23
25
|
args = parser.parse_args()
|
|
24
26
|
|
|
@@ -43,12 +45,30 @@ def main():
|
|
|
43
45
|
body["estimate"] = args.estimate
|
|
44
46
|
if args.assignee:
|
|
45
47
|
body["assignee"] = args.assignee
|
|
48
|
+
if args.project:
|
|
49
|
+
body["projectId"] = args.project
|
|
46
50
|
if args.labels:
|
|
47
51
|
body["labels"] = [l.strip() for l in args.labels.split(",") if l.strip()]
|
|
48
52
|
if args.triage:
|
|
49
53
|
body["triage"] = True
|
|
50
54
|
|
|
51
55
|
client = get_client()
|
|
56
|
+
|
|
57
|
+
if args.milestone:
|
|
58
|
+
milestone_id = args.milestone
|
|
59
|
+
# If it doesn't look like a UUID, resolve by name
|
|
60
|
+
if len(milestone_id) != 36 or "-" not in milestone_id:
|
|
61
|
+
milestones = client.get("/milestones")
|
|
62
|
+
match = None
|
|
63
|
+
for m in milestones:
|
|
64
|
+
if m["name"].lower() == milestone_id.lower():
|
|
65
|
+
match = m
|
|
66
|
+
break
|
|
67
|
+
if not match:
|
|
68
|
+
fail(f"Milestone not found: {milestone_id}")
|
|
69
|
+
milestone_id = match["id"]
|
|
70
|
+
body["milestoneId"] = milestone_id
|
|
71
|
+
|
|
52
72
|
result = client.post("/issues", body)
|
|
53
73
|
|
|
54
74
|
output_json({
|