devflow-agent-cli 0.1.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/LICENSE +21 -0
- package/README.md +313 -0
- package/bin/devflow.js +2 -0
- package/dist/cli.js +52 -0
- package/dist/commands/add.js +137 -0
- package/dist/commands/doctor.js +246 -0
- package/dist/commands/explain.js +204 -0
- package/dist/commands/init.js +91 -0
- package/dist/constants.js +120 -0
- package/dist/install.js +176 -0
- package/dist/plugins.js +184 -0
- package/dist/types.js +2 -0
- package/package.json +51 -0
- package/templates/adapters/claude/.claude/commands/build.md +15 -0
- package/templates/adapters/claude/.claude/commands/commit.md +74 -0
- package/templates/adapters/claude/.claude/commands/plan.md +15 -0
- package/templates/adapters/claude/.claude/commands/review.md +16 -0
- package/templates/adapters/claude/.claude/commands/tests.md +14 -0
- package/templates/adapters/claude/.claude/commands/verify.md +16 -0
- package/templates/adapters/codex/README.md +14 -0
- package/templates/adapters/cursor/.cursor/commands/build.md +15 -0
- package/templates/adapters/cursor/.cursor/commands/plan.md +15 -0
- package/templates/adapters/cursor/.cursor/commands/review.md +16 -0
- package/templates/adapters/cursor/.cursor/commands/tests.md +14 -0
- package/templates/adapters/cursor/.cursor/commands/verify.md +16 -0
- package/templates/adapters/cursor/.cursor/rules/typescript.md +15 -0
- package/templates/adapters/gemini/README.md +16 -0
- package/templates/adapters/generic/README.md +14 -0
- package/templates/core/.devflow/workflows.yml +21 -0
- package/templates/core/AGENTS.md +44 -0
- package/templates/core/DEVFLOW.md +138 -0
- package/templates/prompts/build.txt +13 -0
- package/templates/prompts/plan.txt +13 -0
- package/templates/prompts/review.txt +14 -0
- package/templates/prompts/tests.txt +18 -0
- package/templates/prompts/verify.txt +15 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 mayordomoespejo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
# Devflow
|
|
2
|
+
|
|
3
|
+
Devflow is a universal AI development workflow for real software projects.
|
|
4
|
+
|
|
5
|
+
It gives you three things:
|
|
6
|
+
|
|
7
|
+
- a shared workflow: `PLAN -> BUILD -> TEST -> REVIEW -> VERIFY`
|
|
8
|
+
- portable prompts you can reuse in any chat, IDE, or terminal workflow
|
|
9
|
+
- optional adapters that map the workflow into specific tool conventions when that mapping is clear
|
|
10
|
+
|
|
11
|
+
Devflow is designed to be model-agnostic and harness-agnostic. It works with any model, including Claude, Gemini, GPT, and similar systems, without making your project depend on one vendor or one interface.
|
|
12
|
+
|
|
13
|
+
## What Devflow installs
|
|
14
|
+
|
|
15
|
+
Devflow has two layers:
|
|
16
|
+
|
|
17
|
+
- Core: always installed
|
|
18
|
+
- Adapters: optional
|
|
19
|
+
|
|
20
|
+
The core is the source of truth. Adapters are thin additions on top.
|
|
21
|
+
|
|
22
|
+
### Core
|
|
23
|
+
|
|
24
|
+
Every installation includes:
|
|
25
|
+
|
|
26
|
+
- `AGENTS.md` - universal instructions for the agent working in the repo
|
|
27
|
+
- `DEVFLOW.md` - the workflow reference for `PLAN -> BUILD -> TEST -> REVIEW -> VERIFY`
|
|
28
|
+
- `devflow/prompts/` - reusable prompts for `plan`, `build`, `tests`, `review`, and `verify`
|
|
29
|
+
- `.devflow/workflows.yml` - optional workflow customization contract for this project
|
|
30
|
+
|
|
31
|
+
This is the stable part of the product. If a user changes model or tool, the core still works.
|
|
32
|
+
|
|
33
|
+
## Workflow Customization
|
|
34
|
+
|
|
35
|
+
Devflow also installs an optional project file:
|
|
36
|
+
|
|
37
|
+
```txt
|
|
38
|
+
.devflow/workflows.yml
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
This file lets a project declare preferred workflow behavior without editing the shared prompts directly.
|
|
42
|
+
|
|
43
|
+
Example uses:
|
|
44
|
+
|
|
45
|
+
- define review focus areas such as bugs, regressions, missing tests, and security
|
|
46
|
+
- declare what a plan should include
|
|
47
|
+
- declare what verify should check before sign-off
|
|
48
|
+
|
|
49
|
+
Today, `workflows.yml` is a configuration contract for:
|
|
50
|
+
|
|
51
|
+
- humans working in the repository
|
|
52
|
+
- agents that read project files directly
|
|
53
|
+
- future Devflow versions that may interpret this config more deeply
|
|
54
|
+
|
|
55
|
+
Current behavior:
|
|
56
|
+
|
|
57
|
+
- Devflow installs the file as part of the core
|
|
58
|
+
- you can edit it safely per project
|
|
59
|
+
- the CLI does not yet parse it to rewrite prompts
|
|
60
|
+
|
|
61
|
+
That is intentional. The file exists now so projects can establish stable local workflow expectations before deeper automation is added.
|
|
62
|
+
|
|
63
|
+
### Adapters
|
|
64
|
+
|
|
65
|
+
Adapters are optional and exist only to make the core easier to use in a specific environment.
|
|
66
|
+
|
|
67
|
+
- `cursor` installs Cursor-facing command and rule files
|
|
68
|
+
- `claude` installs Claude Code slash commands under `.claude/commands/`
|
|
69
|
+
- `generic` installs usage instructions for any unsupported chat or IDE
|
|
70
|
+
- `codex` and `gemini` install guidance under `.devflow/adapters/` without inventing unsupported config
|
|
71
|
+
|
|
72
|
+
If Devflow does not know a tool's official integration format, it does not fake one.
|
|
73
|
+
|
|
74
|
+
## Works With Any Model
|
|
75
|
+
|
|
76
|
+
Devflow is not tied to a specific model provider.
|
|
77
|
+
|
|
78
|
+
You can use the same workflow with:
|
|
79
|
+
|
|
80
|
+
- Claude
|
|
81
|
+
- Gemini
|
|
82
|
+
- GPT
|
|
83
|
+
- local models
|
|
84
|
+
- any future model that can read instructions and generate code
|
|
85
|
+
|
|
86
|
+
The model can change. The engineering process should not.
|
|
87
|
+
|
|
88
|
+
## Installation
|
|
89
|
+
|
|
90
|
+
Install into the current repository:
|
|
91
|
+
|
|
92
|
+
```sh
|
|
93
|
+
npx devflow-agent-cli init
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Install with the Cursor adapter:
|
|
97
|
+
|
|
98
|
+
```sh
|
|
99
|
+
npx devflow-agent-cli init --adapter cursor
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Install with the generic adapter:
|
|
103
|
+
|
|
104
|
+
```sh
|
|
105
|
+
npx devflow-agent-cli init --adapter generic
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Default behavior:
|
|
109
|
+
|
|
110
|
+
- if the target already uses `.cursor/`, Devflow defaults to `cursor`
|
|
111
|
+
- otherwise Devflow defaults to `generic`
|
|
112
|
+
|
|
113
|
+
Useful flags:
|
|
114
|
+
|
|
115
|
+
- `--target <path>` installs into another directory
|
|
116
|
+
- `--merge` keeps existing files and only adds missing Devflow-managed files
|
|
117
|
+
- `--force` overwrites only Devflow-managed paths: `AGENTS.md`, `DEVFLOW.md`, `devflow/`, `.cursor/`, `.devflow/`
|
|
118
|
+
- `--dry-run` previews what would change
|
|
119
|
+
|
|
120
|
+
## Plugins
|
|
121
|
+
|
|
122
|
+
Plugins extend Devflow with additional workflow capabilities beyond the built-in adapters. Where adapters connect Devflow to AI tools, plugins add new integrations: CI configuration, security audits, company-specific rules, and more.
|
|
123
|
+
|
|
124
|
+
```sh
|
|
125
|
+
# Install a plugin from npm
|
|
126
|
+
npx devflow-agent-cli add devflow-plugin-github
|
|
127
|
+
|
|
128
|
+
# Install from a local path
|
|
129
|
+
npx devflow-agent-cli add ./path/to/my-plugin
|
|
130
|
+
|
|
131
|
+
# Remove a plugin
|
|
132
|
+
npx devflow-agent-cli remove plugin-name
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Installed plugins are tracked in `.devflow/plugins.yml` and their health is reported by `devflow doctor`. See [docs/plugins.md](docs/plugins.md) and [docs/plugin-authoring.md](docs/plugin-authoring.md) for full details.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Doctor
|
|
140
|
+
|
|
141
|
+
Use `devflow doctor` to inspect the current repository or another target and report:
|
|
142
|
+
|
|
143
|
+
- whether the core is installed correctly
|
|
144
|
+
- which adapters and plugins are present
|
|
145
|
+
- missing files
|
|
146
|
+
- recommended next commands
|
|
147
|
+
|
|
148
|
+
Examples:
|
|
149
|
+
|
|
150
|
+
```sh
|
|
151
|
+
npx devflow-agent-cli doctor
|
|
152
|
+
npx devflow-agent-cli doctor --target ../other-repo
|
|
153
|
+
npx devflow-agent-cli doctor --json
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Useful flags:
|
|
157
|
+
|
|
158
|
+
- `--target <path>` inspects another directory
|
|
159
|
+
- `--json` prints JSON only
|
|
160
|
+
- `--verbose` includes adapter-level missing files
|
|
161
|
+
- `--fix` prints safe fix guidance without making destructive changes
|
|
162
|
+
|
|
163
|
+
## Explain
|
|
164
|
+
|
|
165
|
+
Use `devflow explain` to show what Devflow has installed in a repository and where the working rules come from.
|
|
166
|
+
|
|
167
|
+
It reports:
|
|
168
|
+
|
|
169
|
+
- CLI version
|
|
170
|
+
- installed core files and adapters
|
|
171
|
+
- available workflows such as `plan`, `tests`, `review`, and `verify`
|
|
172
|
+
- the project files that define Devflow behavior
|
|
173
|
+
|
|
174
|
+
Examples:
|
|
175
|
+
|
|
176
|
+
```sh
|
|
177
|
+
npx devflow-agent-cli explain
|
|
178
|
+
npx devflow-agent-cli explain --target ../other-repo
|
|
179
|
+
npx devflow-agent-cli explain --json
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Useful flags:
|
|
183
|
+
|
|
184
|
+
- `--target <path>` inspects another directory
|
|
185
|
+
- `--json` prints JSON only
|
|
186
|
+
- `--verbose` includes exact source paths and adapter checks
|
|
187
|
+
|
|
188
|
+
## Quick Start In 30 Seconds
|
|
189
|
+
|
|
190
|
+
1. Run:
|
|
191
|
+
|
|
192
|
+
```sh
|
|
193
|
+
npx devflow-agent-cli init
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
2. Open the installed files:
|
|
197
|
+
|
|
198
|
+
- `AGENTS.md`
|
|
199
|
+
- `DEVFLOW.md`
|
|
200
|
+
- `devflow/prompts/plan.txt`
|
|
201
|
+
|
|
202
|
+
3. Start every non-trivial task with the workflow:
|
|
203
|
+
|
|
204
|
+
- `PLAN` - understand the task, touched files, tests, and risks
|
|
205
|
+
- `BUILD` - implement the smallest correct change
|
|
206
|
+
- `TEST` - cover happy path, edge cases, and failures
|
|
207
|
+
- `REVIEW` - inspect for bugs, security issues, duplication, and unnecessary complexity
|
|
208
|
+
- `VERIFY` - confirm the result matches the plan and is ready to ship
|
|
209
|
+
|
|
210
|
+
4. If your tool supports native commands, install an adapter. If not, copy the prompts into your normal chat or IDE flow.
|
|
211
|
+
|
|
212
|
+
That is the whole point of Devflow: one process, many tools.
|
|
213
|
+
|
|
214
|
+
## How Adapters Work
|
|
215
|
+
|
|
216
|
+
Adapters do not replace the core. They only package it for a specific environment.
|
|
217
|
+
|
|
218
|
+
Current adapter model:
|
|
219
|
+
|
|
220
|
+
| Adapter | Type | Installed path |
|
|
221
|
+
| --- | --- | --- |
|
|
222
|
+
| `cursor` | config-backed adapter | `.cursor/commands/`, `.cursor/rules/` |
|
|
223
|
+
| `claude` | config-backed adapter | `.claude/commands/` |
|
|
224
|
+
| `generic` | documentation adapter | `.devflow/README.md` |
|
|
225
|
+
| `codex` | documentation adapter | `.devflow/adapters/codex/README.md` |
|
|
226
|
+
| `gemini` | documentation adapter | `.devflow/adapters/gemini/README.md` |
|
|
227
|
+
|
|
228
|
+
This keeps the product honest:
|
|
229
|
+
|
|
230
|
+
- the workflow is universal
|
|
231
|
+
- integrations are optional
|
|
232
|
+
- unsupported formats stay as documentation until there is a clear contract
|
|
233
|
+
|
|
234
|
+
## Why This Exists
|
|
235
|
+
|
|
236
|
+
AI-assisted development often degrades because teams keep changing prompts, models, and tools without keeping the engineering process stable.
|
|
237
|
+
|
|
238
|
+
Typical failure modes:
|
|
239
|
+
|
|
240
|
+
- coding starts before the problem is understood
|
|
241
|
+
- tests are skipped or generated too late
|
|
242
|
+
- review becomes optional
|
|
243
|
+
- quality depends on the current chat session
|
|
244
|
+
- every repository grows its own inconsistent prompt folklore
|
|
245
|
+
|
|
246
|
+
Devflow gives the repo a stable process instead of relying on one person's memory or one tool's defaults.
|
|
247
|
+
|
|
248
|
+
## Repository Structure
|
|
249
|
+
|
|
250
|
+
```txt
|
|
251
|
+
src/ TypeScript source modules
|
|
252
|
+
dist/ Compiled output (generated by tsc)
|
|
253
|
+
templates/
|
|
254
|
+
core/ Core files installed by every init
|
|
255
|
+
adapters/ Adapter files (cursor, claude, generic, ...)
|
|
256
|
+
scripts/ Build validation, smoke tests, unit tests
|
|
257
|
+
docs/ User guides
|
|
258
|
+
examples/ Sample projects and usage examples
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
`templates/` is the source of truth for what `devflow init` installs.
|
|
262
|
+
|
|
263
|
+
## Roadmap
|
|
264
|
+
|
|
265
|
+
Near term:
|
|
266
|
+
|
|
267
|
+
- keep the core stable and minimal
|
|
268
|
+
- improve adapter documentation quality
|
|
269
|
+
- harden CLI validation and smoke coverage
|
|
270
|
+
- align docs and examples around the same contract
|
|
271
|
+
|
|
272
|
+
Later, if clearly supported by each tool:
|
|
273
|
+
|
|
274
|
+
- add more config-backed adapters only when the integration format is verified
|
|
275
|
+
- improve adapter auto-detection where it is low-risk
|
|
276
|
+
- expand prompt packs for common repo workflows without bloating the core
|
|
277
|
+
|
|
278
|
+
Not planned:
|
|
279
|
+
|
|
280
|
+
- vendor lock-in
|
|
281
|
+
- model-specific workflow forks
|
|
282
|
+
- hidden automation that rewrites arbitrary project files
|
|
283
|
+
|
|
284
|
+
## Verification
|
|
285
|
+
|
|
286
|
+
Run the local checks:
|
|
287
|
+
|
|
288
|
+
```sh
|
|
289
|
+
npm test
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
This validates the template contract and runs the CLI smoke test.
|
|
293
|
+
|
|
294
|
+
## Releases
|
|
295
|
+
|
|
296
|
+
- Current version: `0.1.0`
|
|
297
|
+
- Changelog: [CHANGELOG.md](CHANGELOG.md)
|
|
298
|
+
- Contribution guide: [CONTRIBUTING.md](CONTRIBUTING.md)
|
|
299
|
+
- Security policy: [SECURITY.md](SECURITY.md)
|
|
300
|
+
|
|
301
|
+
## Tool Guides
|
|
302
|
+
|
|
303
|
+
- [Anywhere](docs/anywhere.md)
|
|
304
|
+
- [Cursor](docs/cursor.md)
|
|
305
|
+
- [Claude Code](docs/claude.md)
|
|
306
|
+
- [Codex](docs/codex.md)
|
|
307
|
+
- [Monorepo setup](docs/monorepo.md)
|
|
308
|
+
- [Plugins](docs/plugins.md)
|
|
309
|
+
- [Plugin authoring](docs/plugin-authoring.md)
|
|
310
|
+
|
|
311
|
+
## License
|
|
312
|
+
|
|
313
|
+
MIT
|
package/bin/devflow.js
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const commander_1 = require("commander");
|
|
4
|
+
const constants_1 = require("./constants");
|
|
5
|
+
const init_1 = require("./commands/init");
|
|
6
|
+
const doctor_1 = require("./commands/doctor");
|
|
7
|
+
const explain_1 = require("./commands/explain");
|
|
8
|
+
const add_1 = require("./commands/add");
|
|
9
|
+
const pkg = require('../package.json');
|
|
10
|
+
commander_1.program
|
|
11
|
+
.name('devflow')
|
|
12
|
+
.description('Universal AI development workflow toolkit — install the core plus optional adapters')
|
|
13
|
+
.version(pkg.version, '-v, --version');
|
|
14
|
+
commander_1.program
|
|
15
|
+
.command('init')
|
|
16
|
+
.description('Install Devflow core and optional adapters into the current project')
|
|
17
|
+
.option('-f, --force', 'overwrite existing Devflow-managed files')
|
|
18
|
+
.option('-m, --merge', 'install only files that do not yet exist (skip conflicts)')
|
|
19
|
+
.option('-n, --dry-run', 'preview operations without writing')
|
|
20
|
+
.option('-t, --target <path>', 'install into a different directory', process.cwd())
|
|
21
|
+
.option('--adapter <adapter>', `single adapter: ${constants_1.ALL_ADAPTERS.join(', ')}, none (default: cursor if .cursor exists, claude if .claude exists, otherwise generic)`)
|
|
22
|
+
.option('--adapters <adapters>', `comma-separated adapters: ${constants_1.ALL_ADAPTERS.join(', ')}, none, all`)
|
|
23
|
+
.option('--tool <tools>', 'deprecated alias for --adapter')
|
|
24
|
+
.action(init_1.runInit);
|
|
25
|
+
commander_1.program
|
|
26
|
+
.command('doctor')
|
|
27
|
+
.description('Diagnose the Devflow installation in the current project or another target')
|
|
28
|
+
.option('-t, --target <path>', 'inspect a different directory', process.cwd())
|
|
29
|
+
.option('-j, --json', 'output JSON only')
|
|
30
|
+
.option('-f, --fix', 'show safe fix guidance when issues are found')
|
|
31
|
+
.option('--verbose', 'include adapter details and missing files')
|
|
32
|
+
.action(doctor_1.runDoctor);
|
|
33
|
+
commander_1.program
|
|
34
|
+
.command('explain')
|
|
35
|
+
.description('Explain what parts of Devflow are installed and where the project rules come from')
|
|
36
|
+
.option('-t, --target <path>', 'inspect a different directory', process.cwd())
|
|
37
|
+
.option('-j, --json', 'output JSON only')
|
|
38
|
+
.option('--verbose', 'include exact paths and extra checks')
|
|
39
|
+
.action(explain_1.runExplain);
|
|
40
|
+
commander_1.program
|
|
41
|
+
.command('add <source>')
|
|
42
|
+
.description('Install a Devflow plugin from a local path or npm package')
|
|
43
|
+
.option('-f, --force', 'reinstall even if the plugin is already present')
|
|
44
|
+
.option('-n, --dry-run', 'preview operations without writing')
|
|
45
|
+
.option('-t, --target <path>', 'install into a different directory', process.cwd())
|
|
46
|
+
.action(add_1.runAdd);
|
|
47
|
+
commander_1.program
|
|
48
|
+
.command('remove <name>')
|
|
49
|
+
.description('Remove an installed Devflow plugin')
|
|
50
|
+
.option('-t, --target <path>', 'target directory containing the plugin', process.cwd())
|
|
51
|
+
.action(add_1.runRemove);
|
|
52
|
+
commander_1.program.parse(process.argv);
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.runAdd = runAdd;
|
|
37
|
+
exports.runRemove = runRemove;
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const install_1 = require("../install");
|
|
41
|
+
const plugins_1 = require("../plugins");
|
|
42
|
+
function runAdd(source, options) {
|
|
43
|
+
const targetDir = (0, install_1.resolveTarget)(options.target ?? process.cwd());
|
|
44
|
+
const dryRun = Boolean(options.dryRun);
|
|
45
|
+
const force = Boolean(options.force);
|
|
46
|
+
// Resolve source → local plugin directory
|
|
47
|
+
const { pluginDir, cleanup } = (0, plugins_1.resolvePluginSource)(source);
|
|
48
|
+
try {
|
|
49
|
+
const manifest = (0, plugins_1.loadPluginManifest)(pluginDir);
|
|
50
|
+
const { destDir, keyFile } = (0, plugins_1.resolvePluginPaths)(manifest);
|
|
51
|
+
// Check if already installed (unless --force)
|
|
52
|
+
const pluginsData = (0, plugins_1.readPluginsFile)(targetDir);
|
|
53
|
+
const alreadyIndex = pluginsData.plugins.findIndex((p) => p.name === manifest.name);
|
|
54
|
+
const alreadyInstalled = alreadyIndex !== -1;
|
|
55
|
+
if (alreadyInstalled && !force) {
|
|
56
|
+
console.log(`Plugin "${manifest.name}" is already installed. Use --force to reinstall.`);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
// Build install list
|
|
60
|
+
const items = (0, plugins_1.buildPluginInstallList)(pluginDir);
|
|
61
|
+
if (items.length === 0) {
|
|
62
|
+
console.error(`Error: plugin "${manifest.name}" has no files to install.`);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
if (dryRun) {
|
|
66
|
+
const action = alreadyInstalled ? 'reinstall' : 'install';
|
|
67
|
+
console.log(`Devflow: dry run — ${action} plugin "${manifest.name}" into ${targetDir}`);
|
|
68
|
+
for (const { dest } of items) {
|
|
69
|
+
const fileExists = (0, install_1.exists)(dest, targetDir);
|
|
70
|
+
const tag = !fileExists ? '[create] ' : force ? '[overwrite]' : '[skip] ';
|
|
71
|
+
console.log(` ${tag} ${dest}`);
|
|
72
|
+
}
|
|
73
|
+
console.log('\nDry run complete. Run without --dry-run to apply.');
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const action = alreadyInstalled ? 'reinstalling' : 'installing';
|
|
77
|
+
console.log(`Devflow: ${action} plugin "${manifest.name}" into ${targetDir}\n`);
|
|
78
|
+
for (const item of items) {
|
|
79
|
+
const existed = (0, install_1.exists)(item.dest, targetDir);
|
|
80
|
+
// Safety: never overwrite files outside Devflow-managed paths without --force
|
|
81
|
+
if (existed && !force && !(0, install_1.isManaged)(item.dest)) {
|
|
82
|
+
console.log(` – ${item.dest} (skipped – not Devflow-managed)`);
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
(0, install_1.copyItem)(item, targetDir);
|
|
87
|
+
const suffix = existed ? ' (overwritten)' : '';
|
|
88
|
+
console.log(` ✓ ${item.dest}${suffix}`);
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
92
|
+
console.error(` ✗ ${item.dest} → ${msg}`);
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Update plugins.yml
|
|
97
|
+
const entry = {
|
|
98
|
+
name: manifest.name,
|
|
99
|
+
source,
|
|
100
|
+
version: manifest.version,
|
|
101
|
+
destDir,
|
|
102
|
+
keyFile,
|
|
103
|
+
};
|
|
104
|
+
if (alreadyInstalled) {
|
|
105
|
+
pluginsData.plugins[alreadyIndex] = entry;
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
pluginsData.plugins.push(entry);
|
|
109
|
+
}
|
|
110
|
+
(0, plugins_1.writePluginsFile)(targetDir, pluginsData);
|
|
111
|
+
console.log(`\nPlugin "${manifest.name}" installed. Recorded in .devflow/plugins.yml`);
|
|
112
|
+
}
|
|
113
|
+
finally {
|
|
114
|
+
cleanup?.();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function runRemove(name, options) {
|
|
118
|
+
const targetDir = (0, install_1.resolveTarget)(options.target ?? process.cwd());
|
|
119
|
+
const pluginsData = (0, plugins_1.readPluginsFile)(targetDir);
|
|
120
|
+
const index = pluginsData.plugins.findIndex((p) => p.name === name);
|
|
121
|
+
if (index === -1) {
|
|
122
|
+
console.error(`Error: plugin "${name}" is not recorded in .devflow/plugins.yml`);
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
const plugin = pluginsData.plugins[index];
|
|
126
|
+
const pluginDestDir = path.join(targetDir, plugin.destDir);
|
|
127
|
+
if (fs.existsSync(pluginDestDir)) {
|
|
128
|
+
fs.rmSync(pluginDestDir, { recursive: true, force: true });
|
|
129
|
+
console.log(`Removed: ${plugin.destDir}`);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
console.log(`Note: ${plugin.destDir} was not found on disk (already removed)`);
|
|
133
|
+
}
|
|
134
|
+
pluginsData.plugins.splice(index, 1);
|
|
135
|
+
(0, plugins_1.writePluginsFile)(targetDir, pluginsData);
|
|
136
|
+
console.log(`Plugin "${name}" removed from .devflow/plugins.yml`);
|
|
137
|
+
}
|