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 CHANGED
@@ -1,57 +1,102 @@
1
1
  # opencode-routines
2
2
 
3
- Claude-Code-style routines for [opencode](https://opencode.ai): same-session loops, same-session cron prompts, and host-backed standalone scheduled agents.
3
+ [![npm](https://img.shields.io/npm/v/opencode-routines)](https://www.npmjs.com/package/opencode-routines)
4
+ [![npm downloads](https://img.shields.io/npm/dm/opencode-routines)](https://www.npmjs.com/package/opencode-routines)
5
+ [![license](https://img.shields.io/npm/l/opencode-routines)](https://github.com/EmilioEsposito/opencode-routines/blob/main/LICENSE)
6
+ [![GitHub](https://img.shields.io/badge/GitHub-source-black?logo=github)](https://github.com/EmilioEsposito/opencode-routines)
4
7
 
5
- This package is a hard fork / successor of `opencode-scheduler` by Benjamin Shafii. The durable host scheduler implementation is derived from that project; this fork changes the product model around routines and adds Claude-aligned tool names.
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
- Server tools only:
26
+ Add the server plugin to your OpenCode config (`~/.config/opencode/opencode.jsonc` or project-level `.opencode/opencode.jsonc`):
10
27
 
11
- ```json
28
+ ```jsonc
12
29
  {
13
- "plugin": ["opencode-routines"]
30
+ "$schema": "https://opencode.ai/config.json",
31
+ "plugin": ["opencode-routines@latest"]
14
32
  }
15
33
  ```
16
34
 
17
- Server tools plus optional TUI slash commands:
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
- ```json
37
+ Optional TUI slash commands are published as a companion package:
38
+
39
+ ```jsonc
20
40
  {
21
- "plugin": ["opencode-routines", "opencode-routines/tui"]
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/tui` is a subpath export from the same npm package, not a separate package.
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
- ## Concepts
48
+ ## What it provides
28
49
 
29
- | Concept | Session model | Where it runs | Persistence |
30
- |---|---|---|---|
31
- | Loop | Same conversation | Current opencode host/process | Process-scoped |
32
- | Cron prompt | Same conversation | Current opencode host/process | Session-only for now |
33
- | Standalone schedule | Fresh standalone opencode run | Host scheduler: launchd/systemd/Task Scheduler/cron | Durable |
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 `/schedule-standalone-session` for help with durable standalone schedules, or use the `ScheduleCreate` tool directly.
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 loop tools
58
+ ## Same-session loops
38
59
 
39
- | Tool | Description |
40
- |---|---|
41
- | `LoopCreate` | Start a same-session loop. Fixed interval when `interval` is provided; dynamic mode otherwise. |
42
- | `LoopList` | List active loops in this plugin process. |
43
- | `LoopDelete` | Stop an active loop. |
44
- | `ScheduleWakeup` | Dynamic-loop wake-up tool. Only works for an active dynamic loop in the same session and prompt. |
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` parameters align with Claude Code:
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
- ## Same-session cron tools
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` = one-shot. |
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 schedule tools
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 aliases:
120
+ Claude-aligned tools:
74
121
 
75
122
  | Tool | Description |
76
123
  |---|---|
77
- | `ScheduleCreate` | Create a durable host-backed standalone scheduled opencode run. |
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 aliases are still present:
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
- | Tool | Description |
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
- ## Optional TUI commands
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`. Dynamic syntax: `/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 each release.
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 send = client.session?.prompt;
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
- path: { sessionID },
12972
- body: { parts: [{ type: "text", text: prompt }] }
12980
+ const result = await send.call(session, {
12981
+ sessionID,
12982
+ parts: [{ type: "text", text: prompt }]
12973
12983
  });
12974
- if (result?.error)
12975
- throw new Error(typeof result.error === "string" ? result.error : JSON.stringify(result.error));
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.0",
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.0.162"
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.0.0"
64
+ "@opencode-ai/plugin": ">=1.1.1"
62
65
  }
63
66
  }