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
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ All notable changes to SkillOpt are documented here. This project adheres to
## [Unreleased]

### Added
- **OpenCode transcript source** (`--source opencode`) for SkillOpt-Sleep. It
reads visible user/assistant text and tool names from OpenCode's local SQLite
history without requiring its CLI, login, or a provider connection.
- **OpenCode CLI backend** (`--backend opencode`) for SkillOpt-Sleep model calls,
including plain task replay, using an installed OpenCode CLI with the user's
existing login and file-based global configuration. Calls parse OpenCode's
JSONL output and disable project configuration, tool use, external plugins,
and configured MCP servers. Transcript harvesting and tool-aware replay
remain follow-up work.
and configured MCP servers. Tool-aware replay remains follow-up work.
- **GitHub Copilot CLI backend**, in two forms: `copilot_chat` (usable as both
optimizer and target) and `copilot_exec` (target-only execution harness).
Because the Copilot CLI carries its own sign-in, `--backend copilot` selects
Expand Down
61 changes: 45 additions & 16 deletions docs/reference/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
> include the generic research `openai_compatible` backend, Sleep handoff,
> Sleep support for non-Azure OpenAI-compatible endpoints, the Sleep
> `--preferences` flag, the research `cursor_exec` target harness, or Cursor
> source/backend/plugin support, Pi source/backend support, the OpenCode Sleep
> backend, or VS Code Copilot transcript harvesting; use a source install from
> `main` for those features until the next release.
> source/backend/plugin support, Pi source/backend support, OpenCode Sleep
> source/backend support, or VS Code Copilot transcript harvesting; use a source
> install from `main` for those features until the next release.

## Training

Expand Down Expand Up @@ -129,7 +129,7 @@ Actions are `run`, `dry-run`, `status`, `adopt`, `harvest`, `schedule`, and
|---|---|
| `--project PATH` | Project used for transcript scope, targets, state, and staging (default: current directory) |
| `--scope invoked\|all` | Harvest this project or all projects |
| `--source claude\|codex\|copilot\|cursor\|pi\|auto` | Transcript source; `auto` keeps Codex-then-Claude precedence and does not select Copilot, Cursor, or Pi |
| `--source claude\|codex\|copilot\|cursor\|pi\|opencode\|auto` | Transcript source; `auto` keeps Codex-then-Claude precedence and does not select Copilot, Cursor, Pi, or OpenCode |
| `--backend mock\|claude\|codex\|copilot\|cursor\|pi\|opencode\|handoff\|azure_openai` | Replay/optimizer backend |
| `--model NAME` | Backend-specific model override |
| `--cursor-home PATH` | Override `~/.cursor` for Cursor transcript harvesting |
Expand All @@ -138,6 +138,7 @@ Actions are `run`, `dry-run`, `status`, `adopt`, `harvest`, `schedule`, and
| `--cursor-path PATH` | Path to the installed Cursor Agent CLI |
| `--pi-path PATH` | Path to the installed Pi coding-agent CLI |
| `--opencode-path PATH` | Path to the installed OpenCode CLI |
| `--opencode-db PATH` | Path to the OpenCode SQLite history database |
| `--preferences TEXT` | House rules supplied to reflection |
| `--lookback-hours N` | Initial transcript lookback; `0` scans all history |
| `--max-sessions N` / `--max-tasks N` | Bound the harvested workload |
Expand Down Expand Up @@ -214,18 +215,46 @@ The managed `schedule` command preserves the backend but not `--source`,
`~/.skillopt-sleep/config.json`; use an absolute `pi_path` and verify
authentication for the scheduled account.

### OpenCode backend
### OpenCode source and backend

Install and configure OpenCode using its
[official documentation](https://opencode.ai/docs/), then confirm the CLI is
available with `opencode --version`.
`--source opencode` reads OpenCode's local SQLite history directly in read-only
mode. The source does not launch OpenCode, require the OpenCode CLI, use its
login, or contact a model provider. Source selection remains explicit:
`--source auto` keeps Codex-then-Claude precedence and does not select OpenCode.

The database path is selected from `--opencode-db` or the `opencode_db` config
key, then `OPENCODE_DB`, then
`${XDG_DATA_HOME:-~/.local/share}/opencode/opencode.db`. A relative
`OPENCODE_DB` value is resolved below OpenCode's data directory;
`OPENCODE_DB=:memory:` has no persistent history to harvest.

The harvester keeps visible user and assistant text, short tool names, the
recorded project directory, Git branch, and session timestamps. It excludes
reasoning, tool arguments and results, file contents, patches, and
provider/model/account metadata. Only root sessions are considered, and
sessions produced by SkillOpt's own OpenCode backend are excluded. Known
secret-shaped strings in retained text are redacted as defense in depth;
inspect harvested tasks before sending them to a real backend. The database is
opened read-only, although SQLite may still update its transient `-shm` file
while coordinating an active WAL database.

The transcript source and model backend are independent. For example, export
OpenCode-derived tasks for review before using any configured backend:

```bash
skillopt-sleep harvest --project "$(pwd)" \
--source opencode --output reviewed-tasks.json --progress
```

`--backend opencode` runs SkillOpt's model calls for mining, plain task replay,
judging, and reflection through an installed OpenCode CLI. It uses the user's
existing OpenCode login, provider environment variables, and file-based global
configuration; SkillOpt does not manage OpenCode accounts or provider
credentials. Transcript sources remain independent, and there is not yet a
`--source opencode` harvester.
credentials.

Install and configure OpenCode using its
[official documentation](https://opencode.ai/docs/), then confirm the CLI is
available with `opencode --version`.

If OpenCode is on `PATH`, no path option is needed. Otherwise use
`--opencode-path`, the `opencode_path` config key, or
Expand All @@ -234,7 +263,7 @@ If OpenCode is on `PATH`, no path option is needed. Otherwise use

```bash
skillopt-sleep run --project "$(pwd)" \
--source codex --backend opencode \
--source opencode --backend opencode \
--opencode-path /absolute/path/to/opencode \
--model provider/model --max-sessions 5 --max-tasks 3 --progress
```
Expand All @@ -256,11 +285,11 @@ unavailable. Calls may appear in the user's normal OpenCode session history;
these controls are invocation settings, not complete account or process
isolation.

The managed scheduler stores the backend but not `--opencode-path`, `--model`,
or the transcript source. Before scheduling OpenCode, put `opencode_path`,
`model`, and `transcript_source` in `~/.skillopt-sleep/config.json` as needed.
Prefer an absolute executable path and verify OpenCode access for the account
that runs the scheduled job.
The managed scheduler stores the backend but not `--source`, `--opencode-db`,
`--opencode-path`, or `--model`. Put `transcript_source`, `opencode_db`,
`opencode_path`, and `model` in `~/.skillopt-sleep/config.json` as needed. Use
absolute database and executable paths, and verify OpenCode access when the
scheduled run uses the backend.

### Cursor source and backend

Expand Down
27 changes: 17 additions & 10 deletions docs/sleep/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ normal agent requests.
One "night":

```
harvest Claude Code / Codex / VS Code Copilot / Cursor / Pi transcripts → mine recurring tasks → replay via the configured backend (isolation varies by backend; mock/handoff make no network calls)
harvest Claude Code / Codex / VS Code Copilot / Cursor / Pi / OpenCode transcripts → mine recurring tasks → replay via the configured backend (isolation varies by backend; mock/handoff make no network calls)
→ consolidate (reflect → bounded edit → GATE on real held-out tasks)
→ stage proposal → (you) adopt
```
Expand Down Expand Up @@ -90,8 +90,9 @@ skillopt-sleep schedule # install a nightly cron entry for this project
> **Version note.** This page tracks `main`. PyPI 0.2.0 provides the base
> commands above. Cursor source/backend/plugin support, VS Code Copilot
> transcript harvesting, Pi source/backend support, Sleep handoff, non-Azure
> OpenAI-compatible endpoints, the OpenCode Sleep backend, and `--preferences`
> landed later and require a source install from `main` until the next release.
> OpenAI-compatible endpoints, OpenCode Sleep source/backend support, and
> `--preferences` landed later and require a source install from `main` until
> the next release.

The per-agent integrations below still come from the repo; the CLI above is the
standalone, pip-only way to run a cycle. Claude Code, Codex, Cursor, Copilot, and
Expand Down Expand Up @@ -172,7 +173,13 @@ scheduled account's Pi authentication.

### OpenCode

Install and configure OpenCode using its
Use `--source opencode` to read local OpenCode SQLite history without launching
the CLI or requiring login or provider access. It is not selected by
`--source auto`. See the
[CLI reference](../reference/cli.md#opencode-source-and-backend) for database
selection and the retained-data boundary.

For model calls, install and configure OpenCode using its
[official documentation](https://opencode.ai/docs/), then confirm the CLI is
available with `opencode --version`.

Expand All @@ -184,7 +191,7 @@ not suitable:

```bash
skillopt-sleep run --project "$(pwd)" \
--source codex --backend opencode \
--source opencode --backend opencode \
--opencode-path /absolute/path/to/opencode --model provider/model
```

Expand All @@ -198,11 +205,11 @@ the user's existing value in that child process, so settings supplied only
through that value are unavailable; use file-based global configuration or
provider environment variables instead.

OpenCode transcript harvesting and tool-aware replay are not implemented yet.
For scheduling, put `opencode_path`, `model`, and the desired
`transcript_source` in `~/.skillopt-sleep/config.json` as needed, and verify the
scheduled account can run OpenCode. See the
[CLI reference](../reference/cli.md#opencode-backend) for full details.
Tool-aware replay and a native OpenCode plugin or command are not implemented
yet. For scheduled runs, configure the source, database, executable, and model
in `~/.skillopt-sleep/config.json` as needed; the
[CLI reference](../reference/cli.md#opencode-source-and-backend) has the full
scheduler details.

### Cursor

Expand Down
16 changes: 10 additions & 6 deletions plugins/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ an importable `skillopt_sleep` module. Install with `uv tool install skillopt` o
> **Version note.** This integration reference tracks `main`. PyPI 0.2.0
> supports the base Sleep CLI, while Cursor source/backend/plugin support,
> Pi source/backend support, handoff, Sleep support for non-Azure
> OpenAI-compatible endpoints, the OpenCode Sleep backend, and `--preferences`
> require a source checkout from `main` until the next release.
> OpenAI-compatible endpoints, OpenCode Sleep source/backend support, and
> `--preferences` require a source checkout from `main` until the next release.

## One sleep cycle

Expand Down Expand Up @@ -93,12 +93,15 @@ optimization.
retained for scope filtering and may appear in miner prompts sent to a real
backend and its provider. Known secret-shaped strings in retained message text
are redacted only as defense in depth.
- The core `opencode` source reads local OpenCode SQLite history without the
CLI, authentication, or provider access. See
[the CLI reference](../docs/reference/cli.md#opencode-source-and-backend) for
its retained-data boundary.
- The core `opencode` backend uses the installed OpenCode CLI for plain model
calls. It keeps the user's login and file-based global configuration
while disabling project configuration, tool use, external plugins, and
configured MCP servers for those calls. OpenCode transcript harvesting,
tool-aware replay, and a native OpenCode plugin or command are not included
yet.
configured MCP servers for those calls. Tool-aware replay and a native
OpenCode plugin or command are not included yet.
- Outbound prompts are not currently guaranteed to be free of secrets. Do not
use a third-party provider on sensitive transcripts without reviewing the data
source and the provider's retention policy.
Expand Down Expand Up @@ -136,12 +139,13 @@ Common implemented flags include:
|---|---|---|
| `--backend mock\|claude\|codex\|cursor\|copilot\|pi\|opencode\|handoff\|azure_openai` | `mock` | select who performs model calls |
| `--model NAME` | backend default | select a backend-specific model |
| `--source claude\|codex\|copilot\|cursor\|pi\|auto` | `claude` | select the transcript source; `auto` retains Codex-then-Claude precedence and does not select Copilot, Cursor, or Pi |
| `--source claude\|codex\|copilot\|cursor\|pi\|opencode\|auto` | `claude` | select the transcript source; `auto` retains Codex-then-Claude precedence and does not select Copilot, Cursor, Pi, or OpenCode |
| `--cursor-home PATH` | `~/.cursor` | override the Cursor transcript home |
| `--cursor-path PATH` | auto-detect `cursor-agent` | select the Cursor Agent CLI executable |
| `--pi-home PATH` | `~/.pi` | select the parent directory containing `agent/sessions` |
| `--pi-path PATH` | auto-detect `pi` | select the Pi coding-agent CLI executable |
| `--opencode-path PATH` | `SKILLOPT_SLEEP_OPENCODE_PATH`, then `opencode` on `PATH`/`PATHEXT` | select the OpenCode CLI executable |
| `--opencode-db PATH` | `OPENCODE_DB`, then `${XDG_DATA_HOME:-~/.local/share}/opencode/opencode.db` | select the OpenCode SQLite history database |
| `--project PATH` | current directory | select the project and invoked harvest scope |
| `--scope invoked\|all` | `invoked` | limit transcript harvesting |
| `--target-skill-path PATH` | managed skill | select a specific `SKILL.md` to stage/adopt |
Expand Down
13 changes: 11 additions & 2 deletions skillopt_sleep/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
--target-skill-path PATH explicit live SKILL.md to stage/adopt
--tasks-file PATH reviewed TaskRecord JSON file to replay instead of harvesting
--backend mock|claude|codex|copilot|cursor|pi|opencode|handoff|azure_openai
--source claude|codex|copilot|copilot_cli|cursor|pi|auto
--source claude|codex|copilot|copilot_cli|cursor|pi|opencode|auto
--vscode-workspace-storage PATH
--copilot-cli-session-store PATH
--opencode-db PATH
--model NAME
--lookback-hours N
--auto-adopt
Expand Down Expand Up @@ -85,12 +86,14 @@ def _add_common(p: argparse.ArgumentParser) -> None:
p.add_argument("--cursor-home", default="", help="override ~/.cursor for Cursor session harvest")
p.add_argument("--pi-home", default="", help="override ~/.pi for Pi session harvest")
p.add_argument("--source", default="",
choices=["", "claude", "codex", "copilot", "copilot_cli", "cursor", "pi", "auto"],
choices=["", "claude", "codex", "copilot", "copilot_cli", "cursor", "pi", "opencode", "auto"],
help="session transcript source")
p.add_argument("--vscode-workspace-storage", default="",
help="override VS Code User/workspaceStorage root for copilot source")
p.add_argument("--copilot-cli-session-store", default="",
help="override ~/.copilot/session-store.db for copilot_cli source")
p.add_argument("--opencode-db", default="",
help="override the local OpenCode transcript database")
p.add_argument("--lookback-hours", type=int, default=None,
help="harvest window in hours; 0 = scan full history")
p.add_argument("--edit-budget", type=int, default=0)
Expand Down Expand Up @@ -147,6 +150,12 @@ def _cfg_from_args(args, task_meta: Dict[str, Any] | None = None) -> Any:
overrides["copilot_cli_session_store"] = os.path.abspath(
os.path.expanduser(args.copilot_cli_session_store)
)
if getattr(args, "opencode_db", ""):
overrides["opencode_db"] = (
":memory:"
if args.opencode_db == ":memory:"
else os.path.abspath(os.path.expanduser(args.opencode_db))
)
lh = getattr(args, "lookback_hours", None)
if lh is not None: # --lookback-hours was explicitly passed (0 = full history)
overrides["lookback_hours"] = lh
Expand Down
15 changes: 12 additions & 3 deletions skillopt_sleep/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@
"cursor_home": CURSOR_HOME,
"vscode_workspace_storage": "", # "" => auto-detect platform defaults
"copilot_cli_session_store": "", # "" => ~/.copilot/session-store.db
# Explicit sources also include copilot, copilot_cli, cursor, and pi.
# ``auto`` keeps
# the established Codex-then-Claude precedence for backward compatibility.
"opencode_db": "", # "" => OPENCODE_DB or the OpenCode XDG data path
# Explicit sources also include copilot, copilot_cli, cursor, pi, and opencode.
# ``auto`` keeps the established Codex-then-Claude precedence.
"transcript_source": "claude",
"projects": "invoked", # "invoked" | "all" | [list of abs paths]
"invoked_project": "", # filled at runtime (cwd) when projects == "invoked"
Expand Down Expand Up @@ -149,6 +149,15 @@ def copilot_cli_session_store(self) -> str:
return ""
return os.path.abspath(os.path.expanduser(str(value)))

@property
def opencode_db_path(self) -> str:
value = self.data.get("opencode_db", "") or ""
if not value:
return ""
if str(value) == ":memory:":
return ":memory:"
return os.path.abspath(os.path.expanduser(str(value)))

@property
def vscode_workspace_storage(self) -> str:
value = self.data.get("vscode_workspace_storage", "") or ""
Expand Down
Loading