Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Security vulnerability
url: https://github.com/davidprokopec/opencode-waits/security/advisories/new
url: https://github.com/davidprokopec/opencode-schedule/security/advisories/new
about: Report security issues privately
100 changes: 58 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,37 @@
# opencode-waits
# opencode-schedule

[![CI](https://github.com/davidprokopec/opencode-waits/actions/workflows/ci.yml/badge.svg)](https://github.com/davidprokopec/opencode-waits/actions/workflows/ci.yml)
[![npm](https://img.shields.io/npm/v/opencode-waits)](https://www.npmjs.com/package/opencode-waits)
[![license](https://img.shields.io/npm/l/opencode-waits)](LICENSE)
[![CI](https://github.com/davidprokopec/opencode-schedule/actions/workflows/ci.yml/badge.svg)](https://github.com/davidprokopec/opencode-schedule/actions/workflows/ci.yml)
[![npm](https://img.shields.io/npm/v/opencode-schedule)](https://www.npmjs.com/package/opencode-schedule)
[![license](https://img.shields.io/npm/l/opencode-schedule)](LICENSE)

Defer a prompt in [OpenCode V2](https://opencode.ai/v2/docs/). Say what you want
and when you want it, and OpenCode sends it to itself later.

```
/wait 1hour implement this
/wait 60s run the test suite again
/wait 2h30m check whether the deploy settled
/schedule 1hour implement this
/schedule 60s run the test suite again
/schedule 2h30m check whether the deploy settled
```

`/wait` returns straight away. Nothing runs, no context is held open, and no
`/schedule` returns straight away. Nothing runs, no context is held open, and no
tokens are burned while the timer is pending. When the delay elapses the plugin
submits the prompt text into the same session as an ordinary user prompt, and
OpenCode acts on it exactly as if you had typed it yourself.

Now that OpenCode V2 is official, this plugin is published as `opencode-waits`
again. It was published as `opencode2-waits` during the V2 preview; new
releases use `opencode-waits`. To migrate, replace `opencode2-waits` (or
`opencode2-waits@beta`) with `opencode-waits` in `opencode.json(c)` and remove
any old waits entry from `cli.json`.
Existing pending waits remain compatible and continue using the original data
directory. The source lives in the
[`davidprokopec/opencode-waits`](https://github.com/davidprokopec/opencode-waits)
repository.
Previously published as `opencode-waits` and `opencode2-waits`. To migrate,
replace the old package entry with `opencode-schedule` in `opencode.json(c)`
and remove any old waits entry from `cli.json`. Do not load both packages.
Existing pending schedules and `/wait` commands remain compatible; duration
syntax and behavior are unchanged. The original data directory and internal
plugin identity are retained, so OpenCode may still list the internal ID as
`opencode2-waits`.

## Install

Install globally with OpenCode's plugin manager:

```sh
opencode plugin add opencode-waits
opencode plugin add opencode-schedule
```

Or add the package to `plugins` in `opencode.json(c)`. One entry loads the
Expand All @@ -43,20 +41,20 @@ configuration:
```jsonc
// ~/.config/opencode/opencode.json(c)
{
"plugins": ["opencode-waits"],
"plugins": ["opencode-schedule"],
}
```

No separate waits entry in `cli.json` is needed. The server owns the timers,
so closing the TUI or Desktop window does not cancel pending waits.
No separate entry in `cli.json` is needed. The server owns the timers,
so closing the TUI or Desktop window does not cancel pending schedules.

With options:

```jsonc
{
"plugins": [
{
"package": "opencode-waits",
"package": "opencode-schedule",
"options": {
"delivery": "queue",
},
Expand All @@ -79,38 +77,41 @@ the current stable version.

## Commands

The TUI sidebar shows pending waits in an expanded Waits section. Click its
header to collapse or expand it; click a wait to open its actions.
The TUI sidebar shows pending prompts in an expanded Schedules section. Click
its header to collapse or expand it; click a schedule to open its actions.

### Desktop (experimental)

Open a session, then choose **Open Waits** from the command palette or use
`/wait-list` to open the Waits side panel. Schedule a prompt with a delay,
view pending waits and their countdowns, or cancel one wait or all waits in
the current session. `/wait` and `/wait-cancel` also run locally without a
model call.
Open a session and click **Schedules** in the side-panel toolbar, or choose
**Schedules** from the side panel's **+ / New tab** launcher. You can also
choose **Open Schedules** in the command palette or use `/schedule-list`.
Schedule a prompt with a delay, view pending schedules and their countdowns,
or cancel one or all schedules in the current session. `/schedule` and
`/schedule-cancel` also run locally without a model call.

The GUI API is experimental and targets OpenCode Desktop 2.2.0. Browser/web-app
plugin loading has not been verified. The Desktop panel currently supports
scheduling, listing and cancellation; the TUI's edit, reschedule and send-now
actions are not part of this GUI version.

OpenCode 2.2.0 may show both server fallback and GUI entries in slash
suggestions. Typing `/wait`, `/wait-list` or `/wait-cancel` and submitting
suggestions. Typing `/schedule`, `/schedule-list` or `/schedule-cancel` and submitting
directly uses the local GUI handler; the server entries remain available for
clients without GUI support.

### Slash commands

| Command | Effect |
| ----------------------- | ---------------------------------------------------------- |
| `/wait <duration> <prompt>` | Schedule `<prompt>` for delivery after `<duration>`. |
| `/wait-list` | Show the waits still pending in this session. |
| `/wait-cancel <id>` | Cancel one wait, e.g. `/wait-cancel w1`. |
| `/wait-cancel all` | Cancel every wait pending in this session. |
| `/schedule <duration> <prompt>` | Schedule `<prompt>` for delivery after `<duration>`. |
| `/schedule-list` | Show pending scheduled prompts. |
| `/schedule-cancel <id>` | Cancel one schedule, e.g. `/schedule-cancel w1`. |
| `/schedule-cancel all` | Cancel every schedule pending in this session. |

Waits are per session. `/wait-list` and `/wait-cancel` never see or touch waits
belonging to another session.
The old `/wait`, `/wait-list`, `/wait-cancel` commands remain compatibility
aliases with the same arguments. Cancellation is scoped to the current
session. Desktop lists schedules for the current session; the TUI manager
also groups schedules from other sessions as before.

## Durations

Expand All @@ -133,9 +134,9 @@ the prompt.
own, so `1h30` is rejected as ambiguous rather than guessed at. The maximum is
30 days.

## Waits survive restarts
## Schedules survive restarts

Each pending wait is a JSON file under
Each pending schedule is a JSON file under
`$XDG_DATA_HOME/opencode-waits/waits/` (the legacy-compatible directory, with one file per
wait, so the two halves never clobber each other's records). On startup the
server half arms everything it finds, and fires anything already overdue
Expand All @@ -155,7 +156,7 @@ A slash command defined by a *server* plugin is only a prompt template. Running
one submits a prompt and schedules model execution — so it fails exactly when
you are rate limited and most want to defer work.

A **TUI** slash command does not. The prompt matches `/wait …` and calls the
A **TUI** slash command does not. The prompt matches `/schedule …` and calls the
plugin before any model dispatch, so scheduling costs no model call at all. That
is why the terminal trigger lives in the TUI part. Desktop commands call the
server's typed RPC directly, also without submitting a model prompt.
Expand All @@ -164,8 +165,10 @@ Timers cannot live there, though: they would die when you close the TUI. So the
TUI half only records the wait to disk, and the **server** half — running in the
background service — owns the timers and delivers the prompt.

The server half always exposes `wait_schedule`, `wait_list` and `wait_cancel` as
tools and registers `/wait`, `/wait-list` and `/wait-cancel` as server-side
The server half exposes `schedule_create`, `schedule_list` and `schedule_cancel`
as tools, with `wait_schedule`, `wait_list` and `wait_cancel` compatibility
aliases, and registers `/schedule`, `/schedule-list` and `/schedule-cancel`
(plus their `/wait` aliases) as server-side
commands. Clients without the TUI or GUI part can use these server commands;
they ask the agent to call the tool and cost one model turn. The TUI and
Desktop GUI parts provide their own model-free command handlers instead.
Expand All @@ -174,6 +177,19 @@ Desktop GUI parts provide their own model-free command handlers instead.

Requires [Bun](https://bun.sh).

Source is grouped by plugin surface:

```text
src/
server/ # timers, commands, tools and RPC handlers
tui/ # terminal commands, manager and sidebar
gui/ # Desktop panel, launchers and local commands
shared/ # contracts, durations and server/TUI persistence
```

Package exports select each surface; the GUI bundle imports only its shared
RPC contract, not filesystem or timer implementations.

```sh
bun install
bun run check # typecheck + lint + test + GUI bundle build
Expand All @@ -184,7 +200,7 @@ bundle first, then configure the package directory:

```jsonc
{
"plugins": ["/absolute/path/to/opencode-waits"],
"plugins": ["/absolute/path/to/opencode-schedule"],
}
```

Expand Down
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
## Reporting a vulnerability

Report privately through
[GitHub Security Advisories](https://github.com/davidprokopec/opencode-waits/security/advisories/new).
[GitHub Security Advisories](https://github.com/davidprokopec/opencode-schedule/security/advisories/new).
Please do not open a public issue for a vulnerability.

## What this plugin can do
Expand Down
2 changes: 1 addition & 1 deletion bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 10 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
{
"name": "opencode-waits",
"version": "0.4.0",
"description": "OpenCode V2 plugin that defers a prompt: /wait 1hour implement this",
"name": "opencode-schedule",
"version": "0.5.0",
"description": "Schedule a prompt in OpenCode: /schedule 1hour implement this",
"license": "MIT",
"type": "module",
"repository": {
"type": "git",
"url": "git+https://github.com/davidprokopec/opencode-waits.git"
"url": "git+https://github.com/davidprokopec/opencode-schedule.git"
},
"homepage": "https://github.com/davidprokopec/opencode-waits#readme",
"bugs": "https://github.com/davidprokopec/opencode-waits/issues",
"homepage": "https://github.com/davidprokopec/opencode-schedule#readme",
"bugs": "https://github.com/davidprokopec/opencode-schedule/issues",
"exports": {
".": "./src/index.ts",
"./server": "./src/index.ts",
"./tui": "./src/tui.ts",
".": "./src/server/index.ts",
"./server": "./src/server/index.ts",
"./tui": "./src/tui/index.ts",
"./gui-experimental": "./dist/gui-experimental.cjs",
"./rpc": "./src/rpc.ts"
"./rpc": "./src/shared/rpc.ts"
},
"files": [
"src",
Expand Down
117 changes: 0 additions & 117 deletions src/gui-commands.ts

This file was deleted.

Loading
Loading