Skip to content

Commit 611fb87

Browse files
authored
Merge pull request #1 from otto-assistant/feat/opencode-commandcode-36eb
feat: Command Code OpenCode plugin — Go ($1) OAuth, Laguna S 2.1
2 parents 48a08d7 + 7e6bbe9 commit 611fb87

31 files changed

Lines changed: 5114 additions & 1 deletion

‎.cursor/environment.json‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"name": "opencode-commandcode",
3+
"install": "export PATH=\"$HOME/.local/bin:$HOME/.bun/bin:$HOME/.opencode/bin:$PATH\" && (command -v bun >/dev/null || curl -fsSL https://bun.sh/install | bash) && (command -v opencode >/dev/null || curl -fsSL https://opencode.ai/install | bash) && npm config set prefix \"$HOME/.local\" && npm i -g command-code@latest && bun install && bun run build",
4+
"start": "export PATH=\"$HOME/.local/bin:$HOME/.bun/bin:$HOME/.opencode/bin:$PATH\" && echo \"command-code=$(command-code --version 2>/dev/null || cmd --version)\" && echo \"opencode=$(opencode --version)\" && echo \"bun=$(bun --version)\""
5+
}

‎.github/workflows/release.yml‎

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
name: Release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version:
7+
description: 'Explicit version (e.g., 0.2.0). If empty, bump type is used.'
8+
required: false
9+
type: string
10+
bump:
11+
description: 'Version bump type (used if version is empty)'
12+
required: false
13+
default: 'minor'
14+
type: choice
15+
options:
16+
- minor
17+
- patch
18+
- major
19+
dry_run:
20+
description: 'Dry run — skip npm publish, create draft release'
21+
required: false
22+
default: false
23+
type: boolean
24+
25+
env:
26+
NODE_VERSION: '22'
27+
28+
permissions:
29+
contents: write
30+
31+
jobs:
32+
release:
33+
runs-on: ubuntu-latest
34+
steps:
35+
- uses: actions/checkout@v4
36+
with:
37+
fetch-depth: 0
38+
fetch-tags: true
39+
40+
- name: Get current version from package.json
41+
id: current_version
42+
run: echo "version=$(node -p "require('./package.json').version")" >> "$GITHUB_OUTPUT"
43+
44+
- name: Calculate new version
45+
id: version
46+
env:
47+
CURRENT_VERSION: ${{ steps.current_version.outputs.version }}
48+
INPUT_VERSION: ${{ github.event.inputs.version }}
49+
BUMP_TYPE: ${{ github.event.inputs.bump }}
50+
run: |
51+
set -euo pipefail
52+
if [[ -n "$INPUT_VERSION" ]]; then
53+
if ! echo "$INPUT_VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$'; then
54+
echo "Error: version must be in semver format X.Y.Z"
55+
exit 1
56+
fi
57+
echo "version=$INPUT_VERSION" >> "$GITHUB_OUTPUT"
58+
else
59+
IFS='.' read -r major minor patch <<< "$CURRENT_VERSION"
60+
case "$BUMP_TYPE" in
61+
major) echo "version=$((major+1)).0.0" >> "$GITHUB_OUTPUT" ;;
62+
minor) echo "version=$major.$((minor+1)).0" >> "$GITHUB_OUTPUT" ;;
63+
patch) echo "version=$major.$minor.$((patch+1))" >> "$GITHUB_OUTPUT" ;;
64+
*) echo "Error: unknown bump type $BUMP_TYPE"; exit 1 ;;
65+
esac
66+
fi
67+
68+
- name: Update package.json version
69+
run: |
70+
node -e "
71+
const pkg = require('./package.json');
72+
pkg.version = '${{ steps.version.outputs.version }}';
73+
require('fs').writeFileSync('./package.json', JSON.stringify(pkg, null, 2) + '\n');
74+
"
75+
76+
- name: Setup Bun
77+
uses: oven-sh/setup-bun@v2
78+
79+
- name: Setup Node.js
80+
uses: actions/setup-node@v4
81+
with:
82+
node-version: ${{ env.NODE_VERSION }}
83+
registry-url: 'https://registry.npmjs.org'
84+
85+
- name: Install dependencies
86+
run: bun install --frozen-lockfile
87+
88+
- name: Run tests
89+
run: bun run test
90+
91+
- name: Build package
92+
run: bun run build
93+
94+
- name: Commit and tag
95+
env:
96+
VERSION: ${{ steps.version.outputs.version }}
97+
run: |
98+
git config user.name "github-actions[bot]"
99+
git config user.email "github-actions[bot]@users.noreply.github.com"
100+
git add package.json
101+
if git ls-files --modified --others | grep -q bun.lock; then
102+
git add bun.lock
103+
fi
104+
git commit -m "chore: release v${VERSION}"
105+
git tag "v${VERSION}"
106+
git push origin "v${VERSION}"
107+
git push origin HEAD:main
108+
109+
- name: Publish to npm
110+
if: ${{ github.event.inputs.dry_run != 'true' }}
111+
run: npm publish --access public
112+
env:
113+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
114+
115+
- name: Create GitHub Release
116+
uses: softprops/action-gh-release@v2
117+
with:
118+
tag_name: v${{ steps.version.outputs.version }}
119+
generate_release_notes: true
120+
draft: ${{ github.event.inputs.dry_run == 'true' }}
121+
name: v${{ steps.version.outputs.version }}
122+
env:
123+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

‎.gitignore‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
node_modules/
2+
dist/
3+
*.tsbuildinfo
4+
.DS_Store
5+
6+
# Local agent notes / environment-specific
7+
AGENTS.md

‎.opencode/opencode.json‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"$schema": "https://opencode.ai/config.json",
3+
"plugin": ["file://."],
4+
"provider": {
5+
"command-code": { "name": "Command Code" }
6+
}
7+
}

‎CHANGELOG.md‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Changelog
2+
3+
## 0.1.0
4+
5+
- Initial release: Command Code OpenCode plugin
6+
- Local OpenAI-compatible proxy → `api.commandcode.ai/alpha/generate`
7+
- Auth via Command Code Go-plan browser OAuth (`cmd login`) — no Studio API key
8+
- Default model: Laguna S 2.1 free (`poolside/laguna-s-2.1-free`)
9+
- Tools/MCP park-resume, attachment plumbing, context compact, usage endpoints

‎LICENSE‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 Otto Assistant contributors
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

‎README.md‎

Lines changed: 120 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,120 @@
1-
# opencode-commandcode
1+
<p align="center">
2+
<img src="docs/header.svg" width="828" alt="opencode-commandcode — Command Code in OpenCode, Laguna S 2.1 gateway">
3+
</p>
4+
5+
<p align="center">
6+
<a href="https://www.npmjs.com/package/@otto-assistant/opencode-commandcode"><img src="https://img.shields.io/npm/v/%40otto-assistant%2Fopencode-commandcode?style=flat-square&color=7dcea0&labelColor=0c1412&label=npm" alt="npm version"></a>
7+
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-7dcea0?style=flat-square&labelColor=0c1412" alt="MIT license"></a>
8+
<img src="https://img.shields.io/badge/linux%20·%20macos%20·%20windows-7dcea0?style=flat-square&labelColor=0c1412" alt="linux, macos, windows">
9+
</p>
10+
11+
<p align="center">
12+
<strong>Command Code inside OpenCode</strong> — Go-plan ($1) browser login,<br>
13+
gateway proxy, free Laguna S 2.1, tools/MCP, attachments, compact, usage.
14+
</p>
15+
16+
---
17+
18+
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).
19+
20+
Plugin shape mirrors [@otto-assistant/opencode-claude](https://github.com/otto-assistant/opencode-claude) and [@otto-assistant/opencode-cursor](https://github.com/otto-assistant/opencode-cursor).
21+
22+
## Install
23+
24+
```bash
25+
# global (recommended)
26+
opencode plugin @otto-assistant/opencode-commandcode -g
27+
28+
# or project-local
29+
opencode plugin @otto-assistant/opencode-commandcode
30+
```
31+
32+
Optional provider naming:
33+
34+
```jsonc
35+
{
36+
"$schema": "https://opencode.ai/config.json",
37+
"plugin": ["@otto-assistant/opencode-commandcode"],
38+
"provider": {
39+
"command-code": { "name": "Command Code" }
40+
}
41+
}
42+
```
43+
44+
From source:
45+
46+
```bash
47+
git clone https://github.com/otto-assistant/opencode-commandcode.git
48+
cd opencode-commandcode
49+
bun install && bun run build
50+
opencode plugin file://$PWD
51+
```
52+
53+
## Authenticate
54+
55+
Uses the **Command Code Go plan ($1/mo)** — same browser login as `cmd login`. No Studio API key.
56+
57+
```bash
58+
npm i -g command-code@latest
59+
cmd login # browser → Studio CLI auth (Go plan). Laguna S 2.1 is $0 credits.
60+
61+
opencode auth login --provider command-code
62+
# pick "Login with Command Code (Go $1)" — or "Use existing cmd login session"
63+
```
64+
65+
Then:
66+
67+
```bash
68+
opencode run "Summarise this repository in five bullets." --model command-code/laguna-s-2.1-free
69+
```
70+
71+
Laguna S 2.1 free requires an active Go (or higher) account with credits on file; requests on that model still bill **$0**.
72+
73+
## Why this plugin
74+
75+
| | |
76+
|---|---|
77+
| **Gateway proxy** | Talks to `api.commandcode.ai/alpha/generate` — same transport as the `cmd` CLI. |
78+
| **Laguna S 2.1 free** | 256k context, reasoning, $0 while the deal lasts. |
79+
| **Go-plan auth** | Browser OAuth like `cmd login` ($1/mo). Syncs `~/.commandcode/auth.json`. No API key. |
80+
| **Agent-grade tools** | OpenCode tool calls park and resume; MCP-prefixed tools are tracked separately. |
81+
| **Attachments** | Images, PDFs, text/binary files from OpenCode. Text-only models get image placeholders (Command Code behavior). |
82+
| **Compact** | Context-fraction tips + tiered client compact before the 256k window overflows. |
83+
| **Usage** | Per-turn and session totals via SSE `usage` + `GET /v1/usage`. |
84+
85+
## Architecture
86+
87+
```text
88+
OpenCode
89+
└─ /v1/chat/completions
90+
└─ Bun.serve proxy (port 8797)
91+
└─ POST https://api.commandcode.ai/alpha/generate
92+
└─ poolside/laguna-s-2.1-free (default)
93+
```
94+
95+
## Requirements
96+
97+
- [OpenCode](https://opencode.ai)
98+
- [Command Code CLI](https://www.npmjs.com/package/command-code) (`npm i -g command-code@latest`) and a free account
99+
- Bun (plugin runtime) · Node.js ≥ 18 (CLI needs ≥ 22)
100+
101+
## Development
102+
103+
```bash
104+
bun install
105+
bun run build
106+
bun run test # mocked gateway — attachments, tools, compact, usage
107+
bun run test:live # live Laguna S 2.1 (needs `cmd login` / Go plan session)
108+
```
109+
110+
Debug: `OPENCODE_COMMANDCODE_DEBUG=1`.
111+
112+
Optional knobs:
113+
114+
- `OPENCODE_COMMANDCODE_PROXY_PORT` — fixed local proxy port (default `8797`)
115+
- `OPENCODE_COMMANDCODE_CWD` — working directory reported to the gateway
116+
- `COMMANDCODE_API_URL` — override API base (default `https://api.commandcode.ai`)
117+
118+
## License
119+
120+
[MIT](LICENSE)

‎bun.lock‎

Lines changed: 92 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)