@mhd-ghaith-abtah/flow 0.7.2-beta.0
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/CHANGELOG.md +87 -0
- package/LICENSE +21 -0
- package/README.md +162 -0
- package/adapters/e2e/_interface.md +42 -0
- package/adapters/e2e/none.md +15 -0
- package/adapters/e2e/playwright-mcp.md +86 -0
- package/adapters/issue-tracker/_interface.md +46 -0
- package/adapters/issue-tracker/github-issues.md +103 -0
- package/adapters/issue-tracker/linear.md +65 -0
- package/adapters/issue-tracker/none.md +26 -0
- package/adapters/pr/_interface.md +29 -0
- package/adapters/pr/github.md +61 -0
- package/adapters/pr/none.md +32 -0
- package/adapters/verify/_interface.md +26 -0
- package/adapters/verify/custom.md +27 -0
- package/adapters/verify/make.md +30 -0
- package/adapters/verify/pnpm.md +27 -0
- package/bin/flow.js +129 -0
- package/catalog.yaml +364 -0
- package/docs/adapters.md +99 -0
- package/docs/migrate-from-bmad.md +95 -0
- package/docs/profiles.md +81 -0
- package/docs/quickstart.md +82 -0
- package/lib/catalog.js +164 -0
- package/lib/commands/add.js +147 -0
- package/lib/commands/doctor.js +392 -0
- package/lib/commands/init.js +86 -0
- package/lib/commands/install.js +181 -0
- package/lib/commands/plan.js +108 -0
- package/lib/commands/remove.js +87 -0
- package/lib/commands/uninstall.js +157 -0
- package/lib/repo-root.js +53 -0
- package/package.json +62 -0
- package/schemas/catalog.schema.json +155 -0
- package/schemas/flow-config.schema.json +85 -0
- package/schemas/install-state.schema.json +79 -0
- package/skills/flow-doctor/SKILL.md +15 -0
- package/skills/flow-doctor/workflow.md +157 -0
- package/skills/flow-init/SKILL.md +10 -0
- package/skills/flow-init/workflow.md +420 -0
- package/skills/flow-sprint/SKILL.md +10 -0
- package/skills/flow-sprint/workflow.md +394 -0
- package/skills/flow-story/SKILL.md +12 -0
- package/skills/flow-story/workflow.md +531 -0
- package/templates/claude-md-section.md.tmpl +55 -0
- package/templates/flow-readme.md.tmpl +34 -0
- package/templates/flow.config.yaml.tmpl +94 -0
- package/templates/pr.md.tmpl +40 -0
- package/templates/retro.md.tmpl +58 -0
- package/templates/sprint.yaml.tmpl +18 -0
- package/templates/story.md.tmpl +35 -0
- package/tools/fix-caveman-shrink.sh +68 -0
- package/tools/lint-changelog.js +98 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# No issue tracker adapter
|
|
2
|
+
|
|
3
|
+
All issue-tracker operations are no-ops. sprint.yaml is the source of truth.
|
|
4
|
+
|
|
5
|
+
Story ids use the internal scheme `E<epic>-<NNN>` (e.g. `E1-001`).
|
|
6
|
+
|
|
7
|
+
## create_issue(title, body, labels)
|
|
8
|
+
|
|
9
|
+
Returns `{ skipped: true, issue_id: null, url: null }`. Flow uses the internal story id.
|
|
10
|
+
|
|
11
|
+
## transition_to_doing(issue_id)
|
|
12
|
+
Returns `ok`.
|
|
13
|
+
|
|
14
|
+
## transition_to_review(issue_id, pr_url)
|
|
15
|
+
Returns `ok`.
|
|
16
|
+
|
|
17
|
+
## transition_to_done(issue_id)
|
|
18
|
+
Returns `ok`.
|
|
19
|
+
|
|
20
|
+
## verify_merged(issue_id)
|
|
21
|
+
|
|
22
|
+
Returns `true` (no external check). User is responsible for confirming PR is merged before `/flow-sprint done`.
|
|
23
|
+
|
|
24
|
+
## get_state(issue_id)
|
|
25
|
+
|
|
26
|
+
Returns the `status` field from sprint.yaml for the matching story.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# PR Platform Adapter Interface
|
|
2
|
+
|
|
3
|
+
Every pr adapter MUST implement these operations.
|
|
4
|
+
|
|
5
|
+
## Required operations
|
|
6
|
+
|
|
7
|
+
### `open_pr(title, body, base, head) → { pr_id, pr_number, url }`
|
|
8
|
+
|
|
9
|
+
Called by `/flow-story` at the commit-pr phase. Open a PR from `head` (current branch) to `base` (default `main`).
|
|
10
|
+
|
|
11
|
+
### `get_pr_state(pr_id) → { state, mergedAt, reviewDecision }`
|
|
12
|
+
|
|
13
|
+
- `state` ∈ `{open, closed, merged}`
|
|
14
|
+
- `mergedAt` ISO timestamp or null
|
|
15
|
+
- `reviewDecision` ∈ `{approved, changes_requested, review_required, null}`
|
|
16
|
+
|
|
17
|
+
### `merge_pr(pr_id, method) → ok | { error }`
|
|
18
|
+
|
|
19
|
+
Method ∈ `{squash, merge, rebase}`. flow-sprint done uses `squash` by default.
|
|
20
|
+
|
|
21
|
+
## Optional operations
|
|
22
|
+
|
|
23
|
+
### `branch_name(story_id, slug) → string`
|
|
24
|
+
|
|
25
|
+
Convention for branch naming. Default: `flow/<story_id>-<slug>`. Adapters can override (e.g., Linear-style `PLA-42-feature-name`).
|
|
26
|
+
|
|
27
|
+
### `pr_template(story) → string`
|
|
28
|
+
|
|
29
|
+
Return the body template for a new PR. Default reads `templates/pr.md.tmpl`. Adapters can substitute platform-specific tokens.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# GitHub PR adapter
|
|
2
|
+
|
|
3
|
+
Uses `gh` CLI. Same auth as the github-issues adapter.
|
|
4
|
+
|
|
5
|
+
**Dependencies:** `gh` authenticated; remote `origin` is a GitHub repo.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## open_pr(title, body, base, head)
|
|
10
|
+
|
|
11
|
+
1. Push branch if not pushed: `git push -u origin {{head}}`.
|
|
12
|
+
2. Run:
|
|
13
|
+
```bash
|
|
14
|
+
gh pr create \
|
|
15
|
+
--title "{{title}}" \
|
|
16
|
+
--body "$(cat <<'EOF'
|
|
17
|
+
{{body}}
|
|
18
|
+
EOF
|
|
19
|
+
)" \
|
|
20
|
+
--base "{{base}}" \
|
|
21
|
+
--head "{{head}}"
|
|
22
|
+
```
|
|
23
|
+
3. Parse stdout — last non-empty line is the PR URL.
|
|
24
|
+
4. Extract `pr_number` from URL.
|
|
25
|
+
5. Return `{ pr_id: pr_number, pr_number, url }`.
|
|
26
|
+
|
|
27
|
+
## get_pr_state(pr_id)
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
gh pr view {{pr_id}} --json state,mergedAt,reviewDecision
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Map:
|
|
34
|
+
- `state` from GitHub: `OPEN` → `open`, `CLOSED` (no merge) → `closed`, `MERGED` → `merged`
|
|
35
|
+
- `reviewDecision`: `APPROVED` / `CHANGES_REQUESTED` / `REVIEW_REQUIRED` lowercased
|
|
36
|
+
|
|
37
|
+
## merge_pr(pr_id, method)
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
gh pr merge {{pr_id}} \
|
|
41
|
+
--{{method}} # --squash | --merge | --rebase
|
|
42
|
+
--delete-branch \
|
|
43
|
+
--auto # waits for required checks if needed
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
If `--auto` is rejected (no required checks configured), retry without `--auto`.
|
|
47
|
+
|
|
48
|
+
## branch_name(story_id, slug)
|
|
49
|
+
|
|
50
|
+
`flow/{{story_id}}-{{slug}}` (e.g. `flow/E1-001-tokens-base-layout`).
|
|
51
|
+
|
|
52
|
+
If the active issue-tracker is `linear`, override to `{{issue_id}}-{{story_id}}-{{slug}}` so Linear's auto-link recognition works (`PLA-42-...`).
|
|
53
|
+
|
|
54
|
+
## pr_template(story)
|
|
55
|
+
|
|
56
|
+
Reads `{repo_root}/templates/pr.md.tmpl`. Substitutes:
|
|
57
|
+
- `{{story.title}}`
|
|
58
|
+
- `{{story.id}}`
|
|
59
|
+
- `{{issue_ref}}` — `Fixes #N` (github-issues) or `Closes PLA-42` (linear) or empty
|
|
60
|
+
- `{{summary}}` — first sentence of story's `Why`
|
|
61
|
+
- `{{test_plan}}` — rendered from story's ACs (each AC becomes a `- [ ]` line)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# No PR platform adapter
|
|
2
|
+
|
|
3
|
+
All PR operations are no-ops. Commits go straight to `main` (or whatever the default branch is). Flow uses local branches per story but `flow-sprint done` merges via `git merge --ff-only` instead of opening a PR.
|
|
4
|
+
|
|
5
|
+
Use when:
|
|
6
|
+
- Solo project with no review needed
|
|
7
|
+
- Internal scripts / experiments
|
|
8
|
+
- Pre-publish prototypes
|
|
9
|
+
|
|
10
|
+
## open_pr(title, body, base, head)
|
|
11
|
+
|
|
12
|
+
1. Switch to base: `git checkout {{base}}`.
|
|
13
|
+
2. Merge feature branch fast-forward: `git merge --ff-only {{head}}`.
|
|
14
|
+
3. Push: `git push origin {{base}}`.
|
|
15
|
+
4. Delete local branch: `git branch -d {{head}}`.
|
|
16
|
+
5. Return `{ pr_id: "local-merge", pr_number: null, url: null }`.
|
|
17
|
+
|
|
18
|
+
## get_pr_state(pr_id)
|
|
19
|
+
|
|
20
|
+
Returns `{ state: "merged", mergedAt: <ISO timestamp of local merge>, reviewDecision: null }`.
|
|
21
|
+
|
|
22
|
+
## merge_pr(pr_id, method)
|
|
23
|
+
|
|
24
|
+
No-op — merge happened at `open_pr` time. Returns `ok`.
|
|
25
|
+
|
|
26
|
+
## branch_name(story_id, slug)
|
|
27
|
+
|
|
28
|
+
`flow/{{story_id}}-{{slug}}`. Same as github.
|
|
29
|
+
|
|
30
|
+
## pr_template(story)
|
|
31
|
+
|
|
32
|
+
Returns empty string (no body needed).
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Verify Adapter Interface
|
|
2
|
+
|
|
3
|
+
Runs the project's build + test gate. Returns a single pass/fail signal plus the raw output for triage.
|
|
4
|
+
|
|
5
|
+
## Required operations
|
|
6
|
+
|
|
7
|
+
### `verify_cmd → string`
|
|
8
|
+
|
|
9
|
+
Return the shell command Flow should execute as the verification gate. Examples:
|
|
10
|
+
- make adapter: `make verify`
|
|
11
|
+
- pnpm adapter: `pnpm verify` (or whatever script name was configured)
|
|
12
|
+
- custom adapter: user-defined command from config
|
|
13
|
+
|
|
14
|
+
### `run() → { passed, duration_ms, exit_code, stdout, stderr }`
|
|
15
|
+
|
|
16
|
+
Execute `verify_cmd`. Capture exit code + output. Stream to terminal so user sees progress.
|
|
17
|
+
|
|
18
|
+
## Optional operations
|
|
19
|
+
|
|
20
|
+
### `on_failure(exit_code, stderr) → string`
|
|
21
|
+
|
|
22
|
+
Return a one-line suggestion for the user (e.g., "Run `/build-fix` to triage the type error").
|
|
23
|
+
|
|
24
|
+
### `precheck() → ok | { error }`
|
|
25
|
+
|
|
26
|
+
Sanity check before running verify (e.g., for make adapter: confirm Makefile exists and has a `verify` target).
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Custom verify adapter
|
|
2
|
+
|
|
3
|
+
User-defined shell command. Use for non-JS stacks or when verify is a one-off compound command.
|
|
4
|
+
|
|
5
|
+
**Config:** `integrations.verify.command` — required, free-form shell string. Examples:
|
|
6
|
+
- Go: `go vet ./... && go test ./... && go build ./...`
|
|
7
|
+
- Rust: `cargo check && cargo clippy --all-targets && cargo test`
|
|
8
|
+
- Python: `ruff check . && pytest && mypy .`
|
|
9
|
+
- Mixed monorepo: `make -C web verify && pytest api/`
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## verify_cmd
|
|
14
|
+
|
|
15
|
+
`{{config.integrations.verify.command}}`
|
|
16
|
+
|
|
17
|
+
## precheck
|
|
18
|
+
|
|
19
|
+
`test -n "{{config.integrations.verify.command}}"` → if empty, halt: "Set `integrations.verify.command` in `flow.config.yaml`."
|
|
20
|
+
|
|
21
|
+
## run
|
|
22
|
+
|
|
23
|
+
Execute via Bash. Stream output. Return `{ passed, duration_ms, exit_code, stdout, stderr }`.
|
|
24
|
+
|
|
25
|
+
## on_failure(exit_code, stderr)
|
|
26
|
+
|
|
27
|
+
Generic: "Verify command failed. Run directly to see full output: `{{verify_cmd}}`."
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Make verify adapter
|
|
2
|
+
|
|
3
|
+
Runs `make verify` (or another target). Standard for repos that wrap their build/test/lint in a Makefile.
|
|
4
|
+
|
|
5
|
+
**Config:** none required. Optional override: `integrations.verify.target` (default `verify`).
|
|
6
|
+
|
|
7
|
+
**Dependencies:** `make` CLI in `$PATH`; `Makefile` at repo root with the configured target.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## verify_cmd
|
|
12
|
+
|
|
13
|
+
`make {{config.integrations.verify.target || "verify"}}`
|
|
14
|
+
|
|
15
|
+
## precheck
|
|
16
|
+
|
|
17
|
+
1. `test -f Makefile` → if false, halt: "No Makefile at repo root. Either create one with a `{{target}}:` target or switch to `flow adapter swap verify pnpm` / `custom`."
|
|
18
|
+
2. `grep -q '^{{target}}:' Makefile` → if false, halt: "Makefile is present but has no `{{target}}:` target."
|
|
19
|
+
|
|
20
|
+
## run
|
|
21
|
+
|
|
22
|
+
1. Execute `make {{target}}` via Bash, capturing exit code + streaming output.
|
|
23
|
+
2. Record `duration_ms` from start to finish.
|
|
24
|
+
3. Return `{ passed: exit_code == 0, duration_ms, exit_code, stdout, stderr }`.
|
|
25
|
+
|
|
26
|
+
## on_failure(exit_code, stderr)
|
|
27
|
+
|
|
28
|
+
- If stderr contains `error TS` or `Type error`, suggest: "TypeScript errors — try `/build-fix` or run `make typecheck` directly."
|
|
29
|
+
- If stderr contains `eslint`, suggest: "Lint errors — run `make lint --fix` or `pnpm lint --fix`."
|
|
30
|
+
- Otherwise generic: "Verify failed — run `make {{target}}` directly to see full output."
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# pnpm verify adapter
|
|
2
|
+
|
|
3
|
+
Runs a pnpm script (default `verify`). Use when the project doesn't have a Makefile but exposes a verification chain via package.json scripts.
|
|
4
|
+
|
|
5
|
+
**Config:** `integrations.verify.script` (default `verify`).
|
|
6
|
+
|
|
7
|
+
**Dependencies:** `pnpm` in `$PATH`; `package.json > scripts > {{script}}` defined.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## verify_cmd
|
|
12
|
+
|
|
13
|
+
`pnpm {{config.integrations.verify.script || "verify"}}`
|
|
14
|
+
|
|
15
|
+
## precheck
|
|
16
|
+
|
|
17
|
+
1. `test -f package.json` → if false, halt.
|
|
18
|
+
2. `jq -e '.scripts["{{script}}"]' package.json` → if missing, halt: "No `{{script}}` script in package.json. Add one (typical: `\"verify\": \"pnpm typecheck && pnpm lint && pnpm test\"`) or switch verify adapter."
|
|
19
|
+
|
|
20
|
+
## run
|
|
21
|
+
|
|
22
|
+
Execute `pnpm {{script}}` via Bash, stream output, return `{ passed, duration_ms, exit_code, stdout, stderr }`.
|
|
23
|
+
|
|
24
|
+
## on_failure(exit_code, stderr)
|
|
25
|
+
|
|
26
|
+
Same suggestion logic as make.md adapter. Plus:
|
|
27
|
+
- If stderr contains `pnpm: command not found`, halt: "Install pnpm: https://pnpm.io/installation."
|
package/bin/flow.js
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Flow CLI entry — dispatches to lib/commands/<cmd>.js
|
|
3
|
+
//
|
|
4
|
+
// Detects whether we're running inside a Claude Code session (CLAUDECODE=1 env)
|
|
5
|
+
// or from a terminal. The slash-command path uses the same lib/ functions; this
|
|
6
|
+
// binary is the headless / scriptable / CI path.
|
|
7
|
+
|
|
8
|
+
import { fileURLToPath } from 'node:url';
|
|
9
|
+
import { dirname, resolve } from 'node:path';
|
|
10
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
11
|
+
import yargsParser from 'yargs-parser';
|
|
12
|
+
import chalk from 'chalk';
|
|
13
|
+
|
|
14
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
const REPO_ROOT = resolve(__dirname, '..');
|
|
16
|
+
|
|
17
|
+
const PKG = JSON.parse(readFileSync(resolve(REPO_ROOT, 'package.json'), 'utf-8'));
|
|
18
|
+
|
|
19
|
+
const USAGE = `${chalk.bold('flow')} — ${PKG.description}
|
|
20
|
+
|
|
21
|
+
${chalk.bold('Usage:')}
|
|
22
|
+
flow <command> [options]
|
|
23
|
+
|
|
24
|
+
${chalk.bold('Commands:')}
|
|
25
|
+
init Interactive first-time setup (same as /flow-init in Claude Code)
|
|
26
|
+
install Non-interactive install with flags
|
|
27
|
+
plan Dry-run: show the resolved install plan
|
|
28
|
+
status What's installed where
|
|
29
|
+
doctor [--mcp <id>] Health check
|
|
30
|
+
add <component-id> Add a single component
|
|
31
|
+
remove <component-id> Remove a single component
|
|
32
|
+
uninstall Remove Flow from this project (or --scope home for global)
|
|
33
|
+
list-profiles List available profiles
|
|
34
|
+
list-components [--family X] List available components
|
|
35
|
+
list-mcps List MCP servers Flow tracks
|
|
36
|
+
mcp <add|remove|reauth> ... Manage MCP servers
|
|
37
|
+
adapter <swap|list> ... Manage active adapters
|
|
38
|
+
help [command] Show help
|
|
39
|
+
|
|
40
|
+
${chalk.bold('Common flags:')}
|
|
41
|
+
--profile <name> mini | standard | team | minimal | full
|
|
42
|
+
--bmad-subset <name> none | planning-only | planning-plus-research | creative-thinking | test-architecture | full | passthrough
|
|
43
|
+
--ecc-subset <name> none | flow-essentials | flow-essentials-plus-tdd | security-heavy | research-heavy | use-ecc-default | passthrough
|
|
44
|
+
--with <component> Add a component on top of the profile
|
|
45
|
+
--without <component> Remove a component from the profile
|
|
46
|
+
--scope home|project|both Install scope (default: both)
|
|
47
|
+
--dry-run Print the plan, don't execute
|
|
48
|
+
--json Machine-readable output
|
|
49
|
+
--yes Skip prompts (for CI)
|
|
50
|
+
--catalog-source <url|path> Use an alternate catalog (advanced)
|
|
51
|
+
|
|
52
|
+
${chalk.bold('Examples:')}
|
|
53
|
+
flow init # interactive
|
|
54
|
+
flow install --profile standard --yes # scripted
|
|
55
|
+
flow install --profile mini --with adapter:e2e-playwright-mcp --yes
|
|
56
|
+
flow plan --profile team --json
|
|
57
|
+
flow status
|
|
58
|
+
flow doctor
|
|
59
|
+
flow uninstall --scope project
|
|
60
|
+
|
|
61
|
+
${chalk.bold('Inside Claude Code (slash commands — hyphenated):')}
|
|
62
|
+
/flow-init first-time setup (interactive)
|
|
63
|
+
/flow-sprint <subcommand> [args] add | next | status | done | retro | ...
|
|
64
|
+
/flow-story [story-id] advance the active story
|
|
65
|
+
|
|
66
|
+
Version ${PKG.version} · ${chalk.dim(PKG.homepage)}
|
|
67
|
+
`;
|
|
68
|
+
|
|
69
|
+
const COMMANDS = [
|
|
70
|
+
'init', 'install', 'plan', 'status', 'doctor', 'add', 'remove', 'uninstall',
|
|
71
|
+
'list-profiles', 'list-components', 'list-mcps', 'mcp', 'adapter', 'help', 'version', '--version'
|
|
72
|
+
];
|
|
73
|
+
|
|
74
|
+
async function main() {
|
|
75
|
+
const argv = process.argv.slice(2);
|
|
76
|
+
|
|
77
|
+
if (argv.length === 0 || argv[0] === 'help' || argv[0] === '--help' || argv[0] === '-h') {
|
|
78
|
+
console.log(USAGE);
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (argv[0] === 'version' || argv[0] === '--version' || argv[0] === '-v') {
|
|
83
|
+
console.log(PKG.version);
|
|
84
|
+
return 0;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const cmd = argv[0];
|
|
88
|
+
if (!COMMANDS.includes(cmd)) {
|
|
89
|
+
console.error(chalk.red(`Unknown command: ${cmd}`));
|
|
90
|
+
console.error(`Run ${chalk.bold('flow help')} for usage.`);
|
|
91
|
+
return 1;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Parse remaining args. Note: no global `scope` default — each command sets
|
|
95
|
+
// its own (install: both; uninstall: project, for safety).
|
|
96
|
+
const args = yargsParser(argv.slice(1), {
|
|
97
|
+
string: ['profile', 'bmad-subset', 'ecc-subset', 'with', 'without', 'scope', 'catalog-source', 'mcp', 'family', 'repair-upstream'],
|
|
98
|
+
boolean: ['dry-run', 'json', 'yes', 'execute', 'remove-stories', 'remove-backups', 'archive-unused', 'migrate-bmad', 'verbose'],
|
|
99
|
+
array: ['with', 'without'],
|
|
100
|
+
alias: { y: 'yes' }
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// Dispatch — each command module exports a default async function(args, ctx)
|
|
104
|
+
const modulePath = resolve(__dirname, '..', 'lib', 'commands', `${cmd}.js`);
|
|
105
|
+
if (!existsSync(modulePath)) {
|
|
106
|
+
console.error(chalk.yellow(`⚠ Command ${chalk.bold(cmd)} not implemented yet (v0.0.1 scaffold).`));
|
|
107
|
+
console.error(` File ${chalk.dim(modulePath)} is missing.`);
|
|
108
|
+
console.error(` Track progress: https://github.com/mhd-ghaith-abtah/flow/issues`);
|
|
109
|
+
return 2;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
const mod = await import(modulePath);
|
|
114
|
+
const ctx = {
|
|
115
|
+
repoRoot: REPO_ROOT,
|
|
116
|
+
pkg: PKG,
|
|
117
|
+
cwd: process.cwd(),
|
|
118
|
+
home: process.env.HOME,
|
|
119
|
+
insideClaudeCode: Boolean(process.env.CLAUDECODE || process.env.CLAUDE_CODE),
|
|
120
|
+
};
|
|
121
|
+
return await mod.default(args, ctx);
|
|
122
|
+
} catch (err) {
|
|
123
|
+
console.error(chalk.red(`✗ ${cmd} failed: ${err.message}`));
|
|
124
|
+
if (process.env.FLOW_DEBUG) console.error(err.stack);
|
|
125
|
+
return 1;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
main().then(code => process.exit(code ?? 0));
|