diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index f611a82..54c39bf 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -50,6 +50,7 @@ jobs:
run: |
set -euo pipefail
if [[ -n "$INPUT_VERSION" ]]; then
+ # Validate semver
if ! echo "$INPUT_VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$'; then
echo "Error: version must be in semver format X.Y.Z"
exit 1
@@ -65,6 +66,12 @@ jobs:
esac
fi
+ - name: Show version info
+ run: |
+ echo "Current version: ${{ steps.current_version.outputs.version }}"
+ echo "New version: ${{ steps.version.outputs.version }}"
+ echo "Dry run: ${{ github.event.inputs.dry_run == 'true' && 'yes' || 'no' }}"
+
- name: Update package.json version
run: |
node -e "
@@ -121,3 +128,59 @@ jobs:
name: v${{ steps.version.outputs.version }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Send Discord notification
+ if: ${{ github.event.inputs.dry_run != 'true' }}
+ env:
+ DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ VERSION: ${{ steps.version.outputs.version }}
+ REPOSITORY: ${{ github.repository }}
+ run: |
+ if [ -z "$DISCORD_WEBHOOK_URL" ]; then
+ echo "DISCORD_WEBHOOK_URL not set; skipping Discord notification."
+ exit 0
+ fi
+ node - <<'NODE'
+ (async () => {
+ const tag = `v${process.env.VERSION}`;
+ const repo = process.env.REPOSITORY;
+ const releaseRes = await fetch(`https://api.github.com/repos/${repo}/releases/tags/${tag}`, {
+ headers: {
+ Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
+ Accept: 'application/vnd.github+json',
+ },
+ });
+ if (!releaseRes.ok) {
+ const body = await releaseRes.text();
+ throw new Error(`Failed to fetch release ${tag}: ${releaseRes.status} ${body}`);
+ }
+ const release = await releaseRes.json();
+ const description = (release.body || `opencode-commandcode ${tag} released.`).slice(0, 4096);
+ const payload = {
+ username: 'opencode-commandcode Releases',
+ embeds: [
+ {
+ title: release.name || `opencode-commandcode ${tag}`,
+ url: release.html_url,
+ description,
+ color: 8244896,
+ footer: { text: 'opencode-commandcode Changelog' },
+ },
+ ],
+ };
+ const discordRes = await fetch(process.env.DISCORD_WEBHOOK_URL, {
+ method: 'POST',
+ headers: { 'content-type': 'application/json' },
+ body: JSON.stringify(payload),
+ });
+ if (!discordRes.ok) {
+ const body = await discordRes.text();
+ throw new Error(`Failed to send Discord notification: ${discordRes.status} ${body}`);
+ }
+ console.log('Discord notification sent successfully');
+ })().catch((error) => {
+ console.error(error);
+ process.exit(1);
+ });
+ NODE
diff --git a/README.md b/README.md
index a13c3bd..0b073a2 100644
--- a/README.md
+++ b/README.md
@@ -4,8 +4,10 @@
+
+
@@ -13,6 +15,14 @@
gateway proxy, free Laguna S 2.1, tools/MCP, attachments, compact, usage.
+
+ Install ·
+ Authenticate ·
+ Why this plugin ·
+ Architecture ·
+ Changelog
+
+
---
Run [Command Code](https://commandcode.ai) models from OpenCode by proxying the same gateway that `npm i -g command-code@latest` uses (`POST /alpha/generate`). Default and exclusive live-test target: **Laguna S 2.1 free** (`poolside/laguna-s-2.1-free`, 256k context, $0).
@@ -21,15 +31,18 @@ Plugin shape mirrors [@otto-assistant/opencode-claude](https://github.com/otto-a
## Install
+`command-code` is **not** a built-in OpenCode provider. Install the plugin first, or
+`opencode auth login --provider command-code` fails with `Unknown provider "command-code"`.
+
```bash
# global (recommended)
opencode plugin @otto-assistant/opencode-commandcode -g
-# or project-local
+# or project-local (writes .opencode/opencode.json)
opencode plugin @otto-assistant/opencode-commandcode
```
-Optional provider naming:
+Optional provider naming (also seeded when the plugin loads):
```jsonc
{
@@ -41,7 +54,7 @@ Optional provider naming:
}
```
-From source:
+Or build from source:
```bash
git clone https://github.com/otto-assistant/opencode-commandcode.git
@@ -52,17 +65,21 @@ opencode plugin file://$PWD
## Authenticate
-Uses the **Command Code Go plan ($1/mo)** — same browser login as `cmd login`. No Studio API key.
+Requires the plugin to be installed (see above). Uses the **Command Code Go plan ($1/mo)** — same browser login as `cmd login`. No Studio API key.
```bash
+# Option A — sync from Command Code CLI (recommended)
npm i -g command-code@latest
cmd login # browser → Studio CLI auth (Go plan). Laguna S 2.1 is $0 credits.
+opencode auth login --provider command-code
+# pick "Use existing cmd login session"
+# Option B — browser OAuth (Go $1)
opencode auth login --provider command-code
-# pick "Login with Command Code (Go $1)" — or "Use existing cmd login session"
+# pick "Login with Command Code (Go $1)"
```
-Then:
+Then start OpenCode, pick provider **command-code**, and choose Laguna S 2.1 free:
```bash
opencode run "Summarise this repository in five bullets." --model command-code/laguna-s-2.1-free
@@ -74,12 +91,12 @@ Laguna S 2.1 free requires an active Go (or higher) account with credits on file
| | |
|---|---|
-| **Gateway proxy** | Talks to `api.commandcode.ai/alpha/generate` — same transport as the `cmd` CLI. |
-| **Laguna S 2.1 free** | 256k context, reasoning, $0 while the deal lasts. |
-| **Go-plan auth** | Browser OAuth like `cmd login` ($1/mo). Syncs `~/.commandcode/auth.json`. No API key. |
+| **Gateway proxy** | Talks to `api.commandcode.ai/alpha/generate` — same transport as the `cmd` CLI (`mode=agent`). |
+| **Laguna S 2.1 free** | 256k context, reasoning, $0 while the deal lasts. Default aliases resolve here. |
+| **Go-plan auth** | Browser OAuth like `cmd login` ($1/mo). Syncs `~/.commandcode/auth.json`. No Studio API key. |
| **Agent-grade tools** | OpenCode tool calls park and resume; MCP-prefixed tools are tracked separately. |
| **Attachments** | Images, PDFs, text/binary files from OpenCode. Text-only models get image placeholders (Command Code behavior). |
-| **Compact** | Context-fraction tips + tiered client compact before the 256k window overflows. |
+| **Auto-compact** | Context-fraction tips + tiered client compact before the 256k window overflows. |
| **Usage** | Per-turn and session totals via SSE `usage` + `GET /v1/usage`. |
## Architecture
@@ -87,15 +104,19 @@ Laguna S 2.1 free requires an active Go (or higher) account with credits on file
```text
OpenCode
└─ /v1/chat/completions
- └─ Bun.serve proxy (port 8797)
+ └─ Bun.serve proxy (dynamic port, prefer 8797)
└─ POST https://api.commandcode.ai/alpha/generate
└─ poolside/laguna-s-2.1-free (default)
```
+Model catalog: aliases `laguna-s-2.1-free` / `laguna` / `default` (and siblings) map to
+`poolside/laguna-s-2.1-free`. Auth credentials are mirrored between OpenCode `auth.json`
+and `~/.commandcode/auth.json`.
+
## Requirements
- [OpenCode](https://opencode.ai)
-- [Command Code CLI](https://www.npmjs.com/package/command-code) (`npm i -g command-code@latest`) and a free account
+- [Command Code CLI](https://www.npmjs.com/package/command-code) (`npm i -g command-code@latest`) and a Go-plan account
- Bun (plugin runtime) · Node.js ≥ 18 (CLI needs ≥ 22)
## Development
@@ -107,13 +128,45 @@ bun run test # mocked gateway — attachments, tools, compact, usage
bun run test:live # live Laguna S 2.1 (needs `cmd login` / Go plan session)
```
-Debug: `OPENCODE_COMMANDCODE_DEBUG=1`.
+Debug logging: `OPENCODE_COMMANDCODE_DEBUG=1`.
Optional knobs:
-- `OPENCODE_COMMANDCODE_PROXY_PORT` — fixed local proxy port (default `8797`)
+- `OPENCODE_COMMANDCODE_PROXY_PORT` — pin a fixed local proxy port (otherwise dynamic: prefer `8797`, then scan upward / ephemeral)
- `OPENCODE_COMMANDCODE_CWD` — working directory reported to the gateway
-- `COMMANDCODE_API_URL` — override API base (default `https://api.commandcode.ai`)
+- `COMMANDCODE_API_URL` / `OPENCODE_COMMANDCODE_API_URL` — override API base (default `https://api.commandcode.ai`)
+
+## Release
+
+Publish via GitHub Actions → **Actions → Release → Run workflow**:
+
+| Input | Purpose |
+|---|---|
+| `version` | Explicit semver (`0.2.0`). Empty → use bump |
+| `bump` | `minor` (default) / `patch` / `major` |
+| `dry_run` | Skip npm publish; create a draft GitHub release |
+
+Requires repo secrets: `NPM_TOKEN`, optional `DISCORD_WEBHOOK_URL`.
+
+Local pin refresh after a release:
+
+```bash
+./scripts/update-plugin.sh
+```
+
+## FAQ
+
+**Do I need a Studio API key?**
+No. Use Go-plan browser login (or sync from `cmd login`).
+
+**Is Laguna free?**
+Yes — `poolside/laguna-s-2.1-free` is the default free model ($0 while the deal lasts).
+
+**Why isn’t Command Code listed without the plugin?**
+OpenCode doesn’t ship Command Code as a built-in provider; this plugin registers it.
+
+**Where are releases?**
+[GitHub Releases](https://github.com/otto-assistant/opencode-commandcode/releases) · [npm](https://www.npmjs.com/package/@otto-assistant/opencode-commandcode) · [Changelog](CHANGELOG.md)
## License
diff --git a/docs/header.svg b/docs/header.svg
index f8a6a0c..f5fce75 100644
--- a/docs/header.svg
+++ b/docs/header.svg
@@ -1,19 +1,90 @@
-