@sven1103/opencode-worktree-workflow 0.6.1 → 0.6.3
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/README.md +20 -1
- package/package.json +1 -1
- package/skills/worktree-workflow/SKILL.md +22 -1
- package/src/cli.js +13 -10
- package/src/index.js +42 -23
package/README.md
CHANGED
|
@@ -42,6 +42,11 @@ In practice:
|
|
|
42
42
|
- if the native tools are unavailable, use the local CLI fallback from the same installed package
|
|
43
43
|
- if the package is not installed, no CLI fallback is available
|
|
44
44
|
|
|
45
|
+
Important distinction:
|
|
46
|
+
|
|
47
|
+
- `worktree_prepare` and `worktree_cleanup` are native OpenCode tools, not shell commands
|
|
48
|
+
- from a terminal, use `npx opencode-worktree-workflow ...` or `./node_modules/.bin/opencode-worktree-workflow ...`
|
|
49
|
+
|
|
45
50
|
## Install in an OpenCode project
|
|
46
51
|
|
|
47
52
|
Add the package as a project dependency, following the official docs style:
|
|
@@ -145,9 +150,11 @@ If your setup uses installed skill files, copy the released `SKILL.md` into a `w
|
|
|
145
150
|
|
|
146
151
|
This package now ships the plugin capability, a CLI fallback surface, thin slash commands, and a co-shipped policy skill.
|
|
147
152
|
|
|
153
|
+
These native tools are exposed inside OpenCode after the plugin is loaded. They are not terminal commands.
|
|
154
|
+
|
|
148
155
|
## Structured contract
|
|
149
156
|
|
|
150
|
-
The
|
|
157
|
+
The package now exposes a versioned structured contract with a `schema_version` field. Native tools return human-readable text and publish the structured result in tool metadata, while CLI `--json` prints the same structured object directly.
|
|
151
158
|
|
|
152
159
|
- current `schema_version`: `1.0.0`
|
|
153
160
|
- contract overview: `docs/contract.md`
|
|
@@ -163,21 +170,33 @@ Human-readable output remains available through the result `message`, but caller
|
|
|
163
170
|
|
|
164
171
|
The npm package also exposes a local CLI so agents can fall back to the same installed package when the native plugin tools are unavailable.
|
|
165
172
|
|
|
173
|
+
Use the CLI from a terminal when you want to run the workflow manually. Run it inside a real git repository. By default, the workflow expects a normal remote and base-branch setup such as `origin` plus the repository default branch, unless you override that in `.opencode/worktree-workflow.json`.
|
|
174
|
+
|
|
166
175
|
Examples:
|
|
167
176
|
|
|
168
177
|
```sh
|
|
178
|
+
npx opencode-worktree-workflow --help
|
|
179
|
+
npx opencode-worktree-workflow wt-clean --help
|
|
169
180
|
npx opencode-worktree-workflow wt-new "Improve checkout retry logic"
|
|
170
181
|
npx opencode-worktree-workflow wt-new "Improve checkout retry logic" --json
|
|
171
182
|
npx opencode-worktree-workflow wt-clean preview
|
|
172
183
|
npx opencode-worktree-workflow wt-clean apply feature/foo --json
|
|
173
184
|
```
|
|
174
185
|
|
|
186
|
+
Direct local bin examples:
|
|
187
|
+
|
|
188
|
+
```sh
|
|
189
|
+
./node_modules/.bin/opencode-worktree-workflow --help
|
|
190
|
+
./node_modules/.bin/opencode-worktree-workflow wt-clean preview
|
|
191
|
+
```
|
|
192
|
+
|
|
175
193
|
Defaults:
|
|
176
194
|
|
|
177
195
|
- human-readable output by default
|
|
178
196
|
- structured output with `--json`
|
|
179
197
|
- the CLI shares the same underlying implementation and result contract as the native tools
|
|
180
198
|
- the CLI fallback depends on the package already being installed in the project
|
|
199
|
+
- if you run it outside a git repo or without the expected remote context, the CLI returns an actionable error
|
|
181
200
|
|
|
182
201
|
## Compatibility model
|
|
183
202
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: worktree-workflow
|
|
3
|
-
description: Use this skill when
|
|
3
|
+
description: Use this skill when working on changes that should be isolated from the main repo, such as refactoring multiple files, making risky edits, experimenting, creating parallel work (like branches or worktrees), or when you are unsure whether it is safe to edit directly in the repo root. Use it when you are orchestrating tasks for implementation and review. Not needed for small, simple one-file edits.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
## When to use me
|
|
@@ -49,6 +49,27 @@ description: Use this skill when you need to decide whether a task should move i
|
|
|
49
49
|
- Use cleanup apply only when deletion is clearly intended and controlled by the orchestrating runtime.
|
|
50
50
|
- Treat slash commands as manual human entry points, not as the canonical agent interface.
|
|
51
51
|
|
|
52
|
+
## Result reporting
|
|
53
|
+
|
|
54
|
+
- Always surface the concrete outcome of worktree operations to the user.
|
|
55
|
+
- Do not summarize away important details.
|
|
56
|
+
|
|
57
|
+
When a worktree is created, include:
|
|
58
|
+
- The worktree path
|
|
59
|
+
- The branch name (if created or used)
|
|
60
|
+
- The base branch
|
|
61
|
+
- Whether it was newly created or reused
|
|
62
|
+
|
|
63
|
+
When cleanup is run:
|
|
64
|
+
- Show the preview or the list of affected worktrees
|
|
65
|
+
- Clearly distinguish preview vs applied changes
|
|
66
|
+
|
|
67
|
+
When commands are executed inside a worktree:
|
|
68
|
+
- Mention that the worktree path is the active working directory
|
|
69
|
+
- Include relevant command results (status, diff summary, errors)
|
|
70
|
+
|
|
71
|
+
Prefer structured, explicit output over vague summaries.
|
|
72
|
+
|
|
52
73
|
## Boundaries
|
|
53
74
|
|
|
54
75
|
- Do not encode runtime storage, session artifact, or orchestration file-layout details here.
|
package/src/cli.js
CHANGED
|
@@ -121,6 +121,15 @@ export async function run(argv = process.argv.slice(2)) {
|
|
|
121
121
|
});
|
|
122
122
|
|
|
123
123
|
let result;
|
|
124
|
+
let structuredResult = null;
|
|
125
|
+
const toolContext = {
|
|
126
|
+
metadata(input) {
|
|
127
|
+
if (input?.metadata?.result) {
|
|
128
|
+
structuredResult = input.metadata.result;
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
worktree: process.cwd(),
|
|
132
|
+
};
|
|
124
133
|
|
|
125
134
|
if (command === "wt-new") {
|
|
126
135
|
const title = rest.join(" ").trim();
|
|
@@ -129,26 +138,20 @@ export async function run(argv = process.argv.slice(2)) {
|
|
|
129
138
|
throw new Error("wt-new requires a descriptive title.");
|
|
130
139
|
}
|
|
131
140
|
|
|
132
|
-
result = await plugin.tool.worktree_prepare.execute(
|
|
133
|
-
{ title },
|
|
134
|
-
{ metadata() {}, worktree: process.cwd() },
|
|
135
|
-
);
|
|
141
|
+
result = await plugin.tool.worktree_prepare.execute({ title }, toolContext);
|
|
136
142
|
} else if (command === "wt-clean") {
|
|
137
143
|
const raw = rest.join(" ").trim();
|
|
138
|
-
result = await plugin.tool.worktree_cleanup.execute(
|
|
139
|
-
{ raw, selectors: [] },
|
|
140
|
-
{ metadata() {}, worktree: process.cwd() },
|
|
141
|
-
);
|
|
144
|
+
result = await plugin.tool.worktree_cleanup.execute({ raw, selectors: [] }, toolContext);
|
|
142
145
|
} else {
|
|
143
146
|
throw new Error(`Unknown command: ${command}`);
|
|
144
147
|
}
|
|
145
148
|
|
|
146
149
|
if (outputJson) {
|
|
147
|
-
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
150
|
+
process.stdout.write(`${JSON.stringify(structuredResult ?? { ok: true, message: result }, null, 2)}\n`);
|
|
148
151
|
return;
|
|
149
152
|
}
|
|
150
153
|
|
|
151
|
-
process.stdout.write(`${result
|
|
154
|
+
process.stdout.write(`${result}\n`);
|
|
152
155
|
}
|
|
153
156
|
|
|
154
157
|
export function isInvokedAsScript(argvPath = process.argv[1]) {
|
package/src/index.js
CHANGED
|
@@ -261,6 +261,16 @@ function buildPrepareResult({ title, branch, worktreePath, defaultBranch, baseBr
|
|
|
261
261
|
};
|
|
262
262
|
}
|
|
263
263
|
|
|
264
|
+
function publishStructuredResult(context, result) {
|
|
265
|
+
context.metadata({
|
|
266
|
+
metadata: {
|
|
267
|
+
result,
|
|
268
|
+
},
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
return result.message || JSON.stringify(result, null, 2);
|
|
272
|
+
}
|
|
273
|
+
|
|
264
274
|
function buildCleanupPreviewResult({ defaultBranch, baseBranch, baseRef, grouped }) {
|
|
265
275
|
const structuredGroups = {
|
|
266
276
|
safe: grouped.safe.map(toStructuredCleanupItem),
|
|
@@ -662,15 +672,18 @@ export const WorktreeWorkflowPlugin = async ({ $, directory }) => {
|
|
|
662
672
|
);
|
|
663
673
|
}
|
|
664
674
|
|
|
665
|
-
return
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
675
|
+
return publishStructuredResult(
|
|
676
|
+
context,
|
|
677
|
+
buildPrepareResult({
|
|
678
|
+
title: args.title,
|
|
679
|
+
branch: branchName,
|
|
680
|
+
worktreePath,
|
|
681
|
+
defaultBranch,
|
|
682
|
+
baseBranch,
|
|
683
|
+
baseRef,
|
|
684
|
+
baseCommit,
|
|
685
|
+
}),
|
|
686
|
+
);
|
|
674
687
|
},
|
|
675
688
|
}),
|
|
676
689
|
worktree_cleanup: tool({
|
|
@@ -726,12 +739,15 @@ export const WorktreeWorkflowPlugin = async ({ $, directory }) => {
|
|
|
726
739
|
}
|
|
727
740
|
|
|
728
741
|
if (normalizedArgs.mode !== "apply") {
|
|
729
|
-
return
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
742
|
+
return publishStructuredResult(
|
|
743
|
+
context,
|
|
744
|
+
buildCleanupPreviewResult({
|
|
745
|
+
defaultBranch,
|
|
746
|
+
baseBranch,
|
|
747
|
+
baseRef,
|
|
748
|
+
grouped,
|
|
749
|
+
}),
|
|
750
|
+
);
|
|
735
751
|
}
|
|
736
752
|
|
|
737
753
|
const requestedSelectors = [...new Set(normalizedArgs.selectors || [])];
|
|
@@ -818,14 +834,17 @@ export const WorktreeWorkflowPlugin = async ({ $, directory }) => {
|
|
|
818
834
|
allowFailure: true,
|
|
819
835
|
});
|
|
820
836
|
|
|
821
|
-
return
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
837
|
+
return publishStructuredResult(
|
|
838
|
+
context,
|
|
839
|
+
buildCleanupApplyResult({
|
|
840
|
+
defaultBranch,
|
|
841
|
+
baseBranch,
|
|
842
|
+
baseRef,
|
|
843
|
+
removed,
|
|
844
|
+
failed,
|
|
845
|
+
requestedSelectors,
|
|
846
|
+
}),
|
|
847
|
+
);
|
|
829
848
|
},
|
|
830
849
|
}),
|
|
831
850
|
},
|