@ship-cli/opencode 0.0.4 → 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/README.md +112 -0
- package/package.json +27 -10
- package/src/compaction.ts +78 -0
- package/src/plugin.ts +2553 -390
- package/src/services.ts +885 -0
- package/src/utils.ts +180 -0
- package/LICENSE +0 -21
package/README.md
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# @ship-cli/opencode
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@ship-cli/opencode)
|
|
4
|
+
[](../../LICENSE)
|
|
5
|
+
|
|
6
|
+
OpenCode plugin for [Ship](https://github.com/EduSantosBrito/ship-cli) - Linear task management and stacked changes for AI coding agents.
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
Add to your `opencode.json`:
|
|
11
|
+
|
|
12
|
+
```json
|
|
13
|
+
{
|
|
14
|
+
"plugins": ["@ship-cli/opencode"]
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Prerequisites
|
|
19
|
+
|
|
20
|
+
- [Ship CLI](https://www.npmjs.com/package/@ship-cli/core) installed and configured (`ship init`)
|
|
21
|
+
- [jj](https://martinvonz.github.io/jj) for VCS operations
|
|
22
|
+
- [Linear](https://linear.app) account
|
|
23
|
+
|
|
24
|
+
## What It Provides
|
|
25
|
+
|
|
26
|
+
This plugin exposes the `ship` tool to OpenCode, enabling AI agents to:
|
|
27
|
+
|
|
28
|
+
### Task Management
|
|
29
|
+
|
|
30
|
+
| Action | Description |
|
|
31
|
+
|--------|-------------|
|
|
32
|
+
| `ready` | Find tasks with no blockers |
|
|
33
|
+
| `list` | List all tasks with optional filters |
|
|
34
|
+
| `blocked` | List tasks waiting on dependencies |
|
|
35
|
+
| `show` | View task details |
|
|
36
|
+
| `start` | Mark task as in progress |
|
|
37
|
+
| `done` | Mark task as complete |
|
|
38
|
+
| `create` | Create new tasks |
|
|
39
|
+
| `update` | Modify task properties |
|
|
40
|
+
| `block` | Add task dependency |
|
|
41
|
+
| `unblock` | Remove task dependency |
|
|
42
|
+
| `relate` | Link related tasks |
|
|
43
|
+
| `status` | Check ship configuration status |
|
|
44
|
+
|
|
45
|
+
### Stacked Changes (jj)
|
|
46
|
+
|
|
47
|
+
| Action | Description |
|
|
48
|
+
|--------|-------------|
|
|
49
|
+
| `stack-create` | Create isolated workspace for a task |
|
|
50
|
+
| `stack-describe` | Update commit message (use `title` + `description` params for multi-line) |
|
|
51
|
+
| `stack-sync` | Fetch and rebase onto trunk |
|
|
52
|
+
| `stack-restack` | Rebase stack onto trunk (no fetch) |
|
|
53
|
+
| `stack-submit` | Push and create/update PR |
|
|
54
|
+
| `stack-status` | View current change info |
|
|
55
|
+
| `stack-log` | View stack of changes |
|
|
56
|
+
| `stack-squash` | Squash change into parent |
|
|
57
|
+
| `stack-abandon` | Abandon a change |
|
|
58
|
+
| `stack-up` | Navigate to parent change |
|
|
59
|
+
| `stack-down` | Navigate to child change |
|
|
60
|
+
| `stack-undo` | Undo last jj operation |
|
|
61
|
+
| `stack-update-stale` | Fix stale working copy |
|
|
62
|
+
| `stack-bookmark` | Create or move bookmark |
|
|
63
|
+
| `stack-workspaces` | List all workspaces |
|
|
64
|
+
| `stack-remove-workspace` | Remove a workspace |
|
|
65
|
+
|
|
66
|
+
### PR Reviews
|
|
67
|
+
|
|
68
|
+
| Action | Description |
|
|
69
|
+
|--------|-------------|
|
|
70
|
+
| `pr-reviews` | Fetch PR reviews in AI-friendly format |
|
|
71
|
+
|
|
72
|
+
### Webhooks
|
|
73
|
+
|
|
74
|
+
| Action | Description |
|
|
75
|
+
|--------|-------------|
|
|
76
|
+
| `webhook-daemon-status` | Check webhook daemon status |
|
|
77
|
+
| `webhook-subscribe` | Subscribe to PR events |
|
|
78
|
+
| `webhook-unsubscribe` | Unsubscribe from events |
|
|
79
|
+
| `webhook-cleanup` | Remove stale subscriptions |
|
|
80
|
+
|
|
81
|
+
### Milestones
|
|
82
|
+
|
|
83
|
+
| Action | Description |
|
|
84
|
+
|--------|-------------|
|
|
85
|
+
| `milestone-list` | List project milestones |
|
|
86
|
+
| `milestone-show` | View milestone details |
|
|
87
|
+
| `milestone-create` | Create new milestone |
|
|
88
|
+
| `milestone-update` | Modify milestone |
|
|
89
|
+
| `milestone-delete` | Delete milestone |
|
|
90
|
+
| `task-set-milestone` | Assign task to milestone |
|
|
91
|
+
| `task-unset-milestone` | Remove task from milestone |
|
|
92
|
+
|
|
93
|
+
## Skill Integration
|
|
94
|
+
|
|
95
|
+
For best results, pair this plugin with the ship-cli skill which provides workflow guidance:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
.opencode/skill/ship-cli/SKILL.md
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The skill teaches the agent the proper workflow:
|
|
102
|
+
1. Find ready tasks
|
|
103
|
+
2. Create isolated workspaces
|
|
104
|
+
3. Make changes and sync
|
|
105
|
+
4. Submit PRs with proper context
|
|
106
|
+
|
|
107
|
+
## Links
|
|
108
|
+
|
|
109
|
+
- [Ship CLI Documentation](https://github.com/EduSantosBrito/ship-cli#readme)
|
|
110
|
+
- [OpenCode](https://opencode.ai)
|
|
111
|
+
- [Linear](https://linear.app)
|
|
112
|
+
- [jj (Jujutsu)](https://martinvonz.github.io/jj)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ship-cli/opencode",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "OpenCode plugin for Ship - Linear task management integration",
|
|
6
6
|
"license": "MIT",
|
|
@@ -19,25 +19,42 @@
|
|
|
19
19
|
],
|
|
20
20
|
"repository": {
|
|
21
21
|
"type": "git",
|
|
22
|
-
"url": "https://github.com/
|
|
22
|
+
"url": "https://github.com/EduSantosBrito/ship-cli.git",
|
|
23
23
|
"directory": "packages/opencode-plugin"
|
|
24
24
|
},
|
|
25
|
+
"homepage": "https://github.com/EduSantosBrito/ship-cli#readme",
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/EduSantosBrito/ship-cli/issues"
|
|
28
|
+
},
|
|
29
|
+
"author": "Eduardo Santos de Brito",
|
|
25
30
|
"publishConfig": {
|
|
26
31
|
"access": "public"
|
|
27
32
|
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"check": "tsc --noEmit",
|
|
35
|
+
"lint": "oxlint",
|
|
36
|
+
"format": "oxfmt --write src/",
|
|
37
|
+
"format:check": "oxfmt src/",
|
|
38
|
+
"test": "vitest run",
|
|
39
|
+
"test:watch": "vitest",
|
|
40
|
+
"prepare": "effect-language-service patch --module typescript"
|
|
41
|
+
},
|
|
28
42
|
"dependencies": {
|
|
29
|
-
"@opencode-ai/plugin": "^1.0.
|
|
30
|
-
"@opencode-ai/sdk": "^1.0.
|
|
43
|
+
"@opencode-ai/plugin": "^1.0.208",
|
|
44
|
+
"@opencode-ai/sdk": "^1.0.208",
|
|
45
|
+
"effect": "^3.19.13"
|
|
31
46
|
},
|
|
32
47
|
"devDependencies": {
|
|
48
|
+
"@effect/language-service": "^0.62.4",
|
|
49
|
+
"@effect/vitest": "^0.25.1",
|
|
33
50
|
"@types/bun": "latest",
|
|
34
|
-
"@types/node": "^
|
|
35
|
-
"
|
|
51
|
+
"@types/node": "^25.0.3",
|
|
52
|
+
"oxfmt": "^0.21.0",
|
|
53
|
+
"oxlint": "^1.36.0",
|
|
54
|
+
"typescript": "~5.9.3",
|
|
55
|
+
"vitest": "^4.0.16"
|
|
36
56
|
},
|
|
37
57
|
"engines": {
|
|
38
58
|
"bun": ">=1.0.0"
|
|
39
|
-
},
|
|
40
|
-
"scripts": {
|
|
41
|
-
"typecheck": "tsc --noEmit"
|
|
42
59
|
}
|
|
43
|
-
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compaction context preservation module.
|
|
3
|
+
*
|
|
4
|
+
* This module provides utilities for tracking task state across sessions
|
|
5
|
+
* and preserving context during OpenCode session compaction.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import * as Option from "effect/Option";
|
|
9
|
+
import * as Schema from "effect/Schema";
|
|
10
|
+
|
|
11
|
+
// =============================================================================
|
|
12
|
+
// Types
|
|
13
|
+
// =============================================================================
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Session task state for compaction context preservation.
|
|
17
|
+
*/
|
|
18
|
+
export interface SessionTaskState {
|
|
19
|
+
taskId: string;
|
|
20
|
+
workdir?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// =============================================================================
|
|
24
|
+
// State Management
|
|
25
|
+
// =============================================================================
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Module-level state for tracking the current task per session.
|
|
29
|
+
*
|
|
30
|
+
* This is populated when tasks are started via the ship tool (action=start)
|
|
31
|
+
* and updated when workspaces are created (action=stack-create).
|
|
32
|
+
* Used during compaction to preserve task context.
|
|
33
|
+
*/
|
|
34
|
+
export const sessionTaskMap = new Map<string, SessionTaskState>();
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Track when a task is started or updated for a session.
|
|
38
|
+
*/
|
|
39
|
+
export const trackTask = (sessionId: string, state: Partial<SessionTaskState>): void => {
|
|
40
|
+
const existing = sessionTaskMap.get(sessionId);
|
|
41
|
+
if (existing) {
|
|
42
|
+
// Update existing state
|
|
43
|
+
sessionTaskMap.set(sessionId, { ...existing, ...state });
|
|
44
|
+
} else if (state.taskId) {
|
|
45
|
+
// New task started
|
|
46
|
+
sessionTaskMap.set(sessionId, { taskId: state.taskId, workdir: state.workdir });
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Get the tracked task for a session.
|
|
52
|
+
*/
|
|
53
|
+
export const getTrackedTask = (sessionId: string): Option.Option<SessionTaskState> => {
|
|
54
|
+
const task = sessionTaskMap.get(sessionId);
|
|
55
|
+
return task ? Option.some(task) : Option.none();
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Clear tracked task for a session. Used for cleanup or when task is completed.
|
|
60
|
+
*/
|
|
61
|
+
export const clearTrackedTask = (sessionId: string): void => {
|
|
62
|
+
sessionTaskMap.delete(sessionId);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// =============================================================================
|
|
66
|
+
// Schema Validation
|
|
67
|
+
// =============================================================================
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Schema for parsing ship tool args from metadata.
|
|
71
|
+
* Only includes fields needed for task tracking.
|
|
72
|
+
*/
|
|
73
|
+
export const ShipToolArgsSchema = Schema.Struct({
|
|
74
|
+
action: Schema.String,
|
|
75
|
+
taskId: Schema.optional(Schema.String),
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
export const decodeShipToolArgs = Schema.decodeUnknownOption(ShipToolArgsSchema);
|