opencode-routines 0.1.0 → 0.1.2
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 +121 -50
- package/dist/index.d.ts +6 -0
- package/dist/index.js +18 -6
- package/package.json +7 -4
package/README.md
CHANGED
|
@@ -1,57 +1,102 @@
|
|
|
1
1
|
# opencode-routines
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/opencode-routines)
|
|
4
|
+
[](https://www.npmjs.com/package/opencode-routines)
|
|
5
|
+
[](https://github.com/EmilioEsposito/opencode-routines/blob/main/LICENSE)
|
|
6
|
+
[](https://github.com/EmilioEsposito/opencode-routines)
|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
Claude-Code-style routines for [OpenCode](https://opencode.ai): same-session loops, same-session cron prompts, and host-backed standalone scheduled agents.
|
|
9
|
+
|
|
10
|
+
Use it for things like:
|
|
11
|
+
|
|
12
|
+
```text
|
|
13
|
+
/loop 5m /babysit-prs
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
```text
|
|
17
|
+
Create a standalone scheduled run every weekday at 9am to summarize my open PRs
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
```text
|
|
21
|
+
Create a same-session cron prompt for 17 * * * * to check whether CI is done
|
|
22
|
+
```
|
|
6
23
|
|
|
7
24
|
## Install
|
|
8
25
|
|
|
9
|
-
|
|
26
|
+
Add the server plugin to your OpenCode config (`~/.config/opencode/opencode.jsonc` or project-level `.opencode/opencode.jsonc`):
|
|
10
27
|
|
|
11
|
-
```
|
|
28
|
+
```jsonc
|
|
12
29
|
{
|
|
13
|
-
"
|
|
30
|
+
"$schema": "https://opencode.ai/config.json",
|
|
31
|
+
"plugin": ["opencode-routines@latest"]
|
|
14
32
|
}
|
|
15
33
|
```
|
|
16
34
|
|
|
17
|
-
|
|
35
|
+
OpenCode installs the package from npm on next start. Use `@latest` if you want new versions on restart, or pin a version such as `"opencode-routines@0.1.1"`.
|
|
18
36
|
|
|
19
|
-
|
|
37
|
+
Optional TUI slash commands are published as a companion package:
|
|
38
|
+
|
|
39
|
+
```jsonc
|
|
20
40
|
{
|
|
21
|
-
"
|
|
41
|
+
"$schema": "https://opencode.ai/config.json",
|
|
42
|
+
"plugin": ["opencode-routines@latest", "opencode-routines-tui@latest"]
|
|
22
43
|
}
|
|
23
44
|
```
|
|
24
45
|
|
|
25
|
-
`opencode-routines
|
|
46
|
+
`opencode-routines-tui` is separate so OpenCode can explicitly install and load the TUI plugin entrypoint. The root package still ships a `./tui` export for advanced/manual loaders, but managed installs should use the companion package.
|
|
26
47
|
|
|
27
|
-
##
|
|
48
|
+
## What it provides
|
|
28
49
|
|
|
29
|
-
|
|
|
30
|
-
|
|
31
|
-
| Loop | Same conversation | Current
|
|
32
|
-
| Cron prompt | Same conversation | Current
|
|
33
|
-
| Standalone schedule | Fresh standalone opencode run | Host scheduler: launchd
|
|
50
|
+
| Capability | Session model | Where it runs | Persistence | Primary tools / commands |
|
|
51
|
+
|---|---|---|---|---|
|
|
52
|
+
| **Loop** | Same conversation | Current OpenCode host/process | Process-scoped | `LoopCreate`, `LoopList`, `LoopDelete`, `ScheduleWakeup`, `/loop` |
|
|
53
|
+
| **Cron prompt** | Same conversation | Current OpenCode host/process | Session-only for now | `CronCreate`, `CronList`, `CronDelete` |
|
|
54
|
+
| **Standalone schedule** | Fresh standalone `opencode run` | Host scheduler: launchd, systemd, Task Scheduler, or cron | Durable | `ScheduleCreate`, `ScheduleList`, `ScheduleDelete`, `ScheduleRun`, `ScheduleLogs` |
|
|
34
55
|
|
|
35
|
-
The ambiguous `/schedule` slash command is intentionally **not** registered. Use
|
|
56
|
+
The ambiguous `/schedule` slash command is intentionally **not** registered. Use `ScheduleCreate` for durable standalone schedules, or `/schedule-standalone-session` for TUI help.
|
|
36
57
|
|
|
37
|
-
## Same-session
|
|
58
|
+
## Same-session loops
|
|
38
59
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
60
|
+
Loops run prompts back into the current conversation.
|
|
61
|
+
|
|
62
|
+
### Fixed interval loop
|
|
63
|
+
|
|
64
|
+
```text
|
|
65
|
+
/loop 5m /babysit-prs
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Equivalent tool shape:
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"prompt": "/babysit-prs",
|
|
73
|
+
"interval": "5m"
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Dynamic loop
|
|
45
78
|
|
|
46
|
-
`ScheduleWakeup`
|
|
79
|
+
Dynamic loops are self-paced. The first prompt fires immediately, then the model can call `ScheduleWakeup` to decide when to resume.
|
|
80
|
+
|
|
81
|
+
```text
|
|
82
|
+
/loop /babysit-prs
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`ScheduleWakeup` parameters:
|
|
47
86
|
|
|
48
87
|
| Param | Type | Required | Description |
|
|
49
88
|
|---|---|---|---|
|
|
50
89
|
| `delaySeconds` | number | yes | Seconds until wake-up. Clamped to 60-3600. |
|
|
51
|
-
| `prompt` | string | yes | The loop prompt to fire on wake-up. |
|
|
90
|
+
| `prompt` | string | yes | The active loop prompt to fire on wake-up. |
|
|
52
91
|
| `reason` | string | yes | Short explanation for the wake-up. |
|
|
53
92
|
|
|
54
|
-
|
|
93
|
+
Omitting `ScheduleWakeup` ends a dynamic loop.
|
|
94
|
+
|
|
95
|
+
## Same-session cron prompts
|
|
96
|
+
|
|
97
|
+
Cron prompts enqueue prompts into the current session at wall-clock times. They are not standalone processes and do not run while OpenCode is closed.
|
|
98
|
+
|
|
99
|
+
Tools:
|
|
55
100
|
|
|
56
101
|
| Tool | Description |
|
|
57
102
|
|---|---|
|
|
@@ -65,48 +110,37 @@ The ambiguous `/schedule` slash command is intentionally **not** registered. Use
|
|
|
65
110
|
|---|---|---|---|---|
|
|
66
111
|
| `cron` | string | yes | — | 5-field cron in local timezone: `M H DoM Mon DoW`. |
|
|
67
112
|
| `prompt` | string | yes | — | Prompt to enqueue in the same session. |
|
|
68
|
-
| `recurring` | boolean | no | `true` | `false`
|
|
113
|
+
| `recurring` | boolean | no | `true` | `false` makes a one-shot cron prompt. |
|
|
69
114
|
| `durable` | boolean | no | `false` | Accepted for Claude compatibility, but currently session-only. |
|
|
70
115
|
|
|
71
|
-
## Durable standalone
|
|
116
|
+
## Durable standalone schedules
|
|
117
|
+
|
|
118
|
+
Standalone schedules are independent `opencode run` processes launched by the host scheduler. They survive terminal exit and machine restarts according to the host scheduler's behavior.
|
|
72
119
|
|
|
73
|
-
Claude-aligned
|
|
120
|
+
Claude-aligned tools:
|
|
74
121
|
|
|
75
122
|
| Tool | Description |
|
|
76
123
|
|---|---|
|
|
77
|
-
| `ScheduleCreate` | Create a durable host-backed standalone scheduled
|
|
124
|
+
| `ScheduleCreate` | Create a durable host-backed standalone scheduled OpenCode run. |
|
|
78
125
|
| `ScheduleList` | List standalone schedules. |
|
|
79
126
|
| `ScheduleDelete` | Delete a standalone schedule. |
|
|
80
127
|
| `ScheduleRun` | Run a standalone schedule immediately. |
|
|
81
128
|
| `ScheduleLogs` | View logs for a standalone schedule. |
|
|
82
129
|
|
|
83
|
-
Legacy compatibility
|
|
130
|
+
Legacy compatibility tools from `opencode-scheduler` are still present: `schedule_job`, `list_jobs`, `get_job`, `update_job`, `delete_job`, `run_job`, `job_logs`, and `cleanup_global`.
|
|
84
131
|
|
|
85
|
-
|
|
86
|
-
|---|---|
|
|
87
|
-
| `schedule_job` | Create a durable standalone schedule. |
|
|
88
|
-
| `list_jobs` | List durable standalone schedules. |
|
|
89
|
-
| `get_job` | Get schedule details. |
|
|
90
|
-
| `update_job` | Update a schedule. |
|
|
91
|
-
| `delete_job` | Delete a schedule. |
|
|
92
|
-
| `run_job` | Run a schedule immediately. |
|
|
93
|
-
| `job_logs` | View schedule logs. |
|
|
94
|
-
| `cleanup_global` | Clean up scheduler artifacts across all scopes. |
|
|
95
|
-
|
|
96
|
-
Durable standalone schedules use the host scheduler: launchd on macOS, systemd on Linux, Task Scheduler on Windows, or cron fallback. Each run starts a fresh standalone `opencode run` by default. Pass explicit `session`, `continue`, or `attachUrl` only when you intentionally want different behavior.
|
|
132
|
+
## TUI slash commands
|
|
97
133
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
Available when `opencode-routines/tui` is installed:
|
|
134
|
+
Available when `opencode-routines-tui` is installed:
|
|
101
135
|
|
|
102
136
|
| Command | Meaning |
|
|
103
137
|
|---|---|
|
|
104
|
-
| `/loop` | Start a same-session live loop. Fixed interval syntax: `5m /babysit-prs
|
|
138
|
+
| `/loop` | Start a same-session live loop. Fixed interval syntax: `5m /babysit-prs`; dynamic syntax: `/babysit-prs`. |
|
|
105
139
|
| `/loops` | List active loops. Selecting a loop stops it. |
|
|
106
140
|
| `/stop-loop` | Stop an active loop. |
|
|
107
141
|
| `/schedule-standalone-session` | Help entry for durable standalone schedules. |
|
|
108
142
|
|
|
109
|
-
## Storage
|
|
143
|
+
## Storage and platform support
|
|
110
144
|
|
|
111
145
|
Standalone schedule storage remains compatible with `opencode-scheduler`:
|
|
112
146
|
|
|
@@ -118,15 +152,52 @@ Standalone schedule storage remains compatible with `opencode-scheduler`:
|
|
|
118
152
|
| Logs | `~/.config/opencode/logs/scheduler/<scopeId>/*.log` |
|
|
119
153
|
| Supervisor script | `~/.config/opencode/scheduler/supervisor.pl` |
|
|
120
154
|
|
|
155
|
+
Standalone schedule backends:
|
|
156
|
+
|
|
157
|
+
| Platform | Backend |
|
|
158
|
+
|---|---|
|
|
159
|
+
| macOS | `launchd` |
|
|
160
|
+
| Linux with systemd | `systemd --user` |
|
|
161
|
+
| Linux / POSIX fallback | `cron` |
|
|
162
|
+
| Windows | Task Scheduler (`schtasks`) |
|
|
163
|
+
|
|
164
|
+
## Compatibility notes
|
|
165
|
+
|
|
166
|
+
- Requires OpenCode `1.17.3` or newer.
|
|
167
|
+
- OpenCode loads config once at startup. Restart OpenCode after changing plugin configuration.
|
|
168
|
+
- `opencode-routines-tui` requires OpenCode's TUI plugin runtime. If your OpenCode build does not support TUI plugins, install only `opencode-routines`.
|
|
169
|
+
- `CronCreate({ durable: true })` is accepted for Claude Code compatibility but currently behaves as session-only.
|
|
170
|
+
|
|
171
|
+
## Debugging
|
|
172
|
+
|
|
173
|
+
- Use `LoopList` and `CronList` for live same-session state.
|
|
174
|
+
- Use `ScheduleList` and `ScheduleLogs` for durable standalone schedules.
|
|
175
|
+
- Standalone run logs live under `~/.config/opencode/logs/scheduler/<scopeId>/`.
|
|
176
|
+
|
|
177
|
+
## Development
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
npm install
|
|
181
|
+
npm test
|
|
182
|
+
npm run typecheck
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
For local development, point OpenCode at this repo's built files or source path. Do not load both a local shim and the npm package at the same time, or tools may register twice.
|
|
186
|
+
|
|
121
187
|
## Publishing
|
|
122
188
|
|
|
123
189
|
```bash
|
|
124
190
|
npm login
|
|
191
|
+
npm test
|
|
125
192
|
npm publish
|
|
126
193
|
```
|
|
127
194
|
|
|
128
|
-
Bump `version` in `package.json` before
|
|
195
|
+
The package is public and unscoped. Bump `version` in `package.json` before every publish.
|
|
196
|
+
|
|
197
|
+
## Credits
|
|
198
|
+
|
|
199
|
+
`opencode-routines` is a hard fork / successor of [`opencode-scheduler`](https://github.com/different-ai/opencode-scheduler) by Benjamin Shafii. The host-backed standalone scheduling implementation is derived from that project; this fork adds the routines-oriented model, same-session loops, cron prompts, and Claude-aligned tool names.
|
|
129
200
|
|
|
130
201
|
## License
|
|
131
202
|
|
|
132
|
-
MIT
|
|
203
|
+
[MIT](LICENSE)
|
package/dist/index.d.ts
CHANGED
|
@@ -53,6 +53,12 @@ interface Job {
|
|
|
53
53
|
lastRunSource?: "manual" | "scheduled";
|
|
54
54
|
lastRunStatus?: "running" | "success" | "failed";
|
|
55
55
|
}
|
|
56
|
+
type RoutinePromptClient = {
|
|
57
|
+
session?: {
|
|
58
|
+
prompt?: (input: unknown) => Promise<unknown>;
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
export declare function __testSubmitSessionPrompt(client: RoutinePromptClient, sessionID: string, prompt: string): Promise<void>;
|
|
56
62
|
export declare function __testBuildOpencodeArgs(job: Job): {
|
|
57
63
|
command: string;
|
|
58
64
|
args: string[];
|
package/dist/index.js
CHANGED
|
@@ -12963,16 +12963,27 @@ function nextCronRun(cron, after = new Date) {
|
|
|
12963
12963
|
}
|
|
12964
12964
|
throw new Error(`Could not find next run for cron: ${cron}`);
|
|
12965
12965
|
}
|
|
12966
|
+
function promptResultError(result) {
|
|
12967
|
+
const error45 = result?.error;
|
|
12968
|
+
if (!error45)
|
|
12969
|
+
return;
|
|
12970
|
+
return typeof error45 === "string" ? error45 : JSON.stringify(error45);
|
|
12971
|
+
}
|
|
12972
|
+
async function __testSubmitSessionPrompt(client, sessionID, prompt) {
|
|
12973
|
+
await submitSessionPrompt(client, sessionID, prompt);
|
|
12974
|
+
}
|
|
12966
12975
|
async function submitSessionPrompt(client, sessionID, prompt) {
|
|
12967
|
-
const
|
|
12976
|
+
const session = client.session;
|
|
12977
|
+
const send = session?.prompt;
|
|
12968
12978
|
if (!send)
|
|
12969
12979
|
throw new Error("Current opencode client does not expose session.prompt");
|
|
12970
|
-
const result = await send({
|
|
12971
|
-
|
|
12972
|
-
|
|
12980
|
+
const result = await send.call(session, {
|
|
12981
|
+
sessionID,
|
|
12982
|
+
parts: [{ type: "text", text: prompt }]
|
|
12973
12983
|
});
|
|
12974
|
-
|
|
12975
|
-
|
|
12984
|
+
const error45 = promptResultError(result);
|
|
12985
|
+
if (error45)
|
|
12986
|
+
throw new Error(error45);
|
|
12976
12987
|
}
|
|
12977
12988
|
function stopLoop(id) {
|
|
12978
12989
|
const loop = loops.get(id);
|
|
@@ -15378,6 +15389,7 @@ ${logs}`, { job, logPath, logs });
|
|
|
15378
15389
|
var src_default = SchedulerPlugin;
|
|
15379
15390
|
export {
|
|
15380
15391
|
src_default as default,
|
|
15392
|
+
__testSubmitSessionPrompt,
|
|
15381
15393
|
__testBuildOpencodeArgs,
|
|
15382
15394
|
SchedulerPlugin
|
|
15383
15395
|
};
|
package/package.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-routines",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "OpenCode routines: same-session loops, cron prompts, and host-backed standalone scheduled agents",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"files": [
|
|
9
|
-
"dist"
|
|
9
|
+
"dist",
|
|
10
|
+
"README.md",
|
|
11
|
+
"LICENSE"
|
|
10
12
|
],
|
|
11
13
|
"exports": {
|
|
12
14
|
".": {
|
|
@@ -30,6 +32,7 @@
|
|
|
30
32
|
},
|
|
31
33
|
"keywords": [
|
|
32
34
|
"opencode",
|
|
35
|
+
"opencode-plugin",
|
|
33
36
|
"plugin",
|
|
34
37
|
"routines",
|
|
35
38
|
"scheduler",
|
|
@@ -51,13 +54,13 @@
|
|
|
51
54
|
},
|
|
52
55
|
"homepage": "https://github.com/EmilioEsposito/opencode-routines#readme",
|
|
53
56
|
"dependencies": {
|
|
54
|
-
"@opencode-ai/plugin": "^1.
|
|
57
|
+
"@opencode-ai/plugin": "^1.1.1"
|
|
55
58
|
},
|
|
56
59
|
"devDependencies": {
|
|
57
60
|
"bun-types": "latest",
|
|
58
61
|
"typescript": "^5.7.3"
|
|
59
62
|
},
|
|
60
63
|
"peerDependencies": {
|
|
61
|
-
"@opencode-ai/plugin": ">=1.
|
|
64
|
+
"@opencode-ai/plugin": ">=1.1.1"
|
|
62
65
|
}
|
|
63
66
|
}
|