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
5 changes: 5 additions & 0 deletions .cursor/environment.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "opencode-commandcode",
"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",
"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)\""
}
123 changes: 123 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
name: Release

on:
workflow_dispatch:
inputs:
version:
description: 'Explicit version (e.g., 0.2.0). If empty, bump type is used.'
required: false
type: string
bump:
description: 'Version bump type (used if version is empty)'
required: false
default: 'minor'
type: choice
options:
- minor
- patch
- major
dry_run:
description: 'Dry run — skip npm publish, create draft release'
required: false
default: false
type: boolean

env:
NODE_VERSION: '22'

permissions:
contents: write

jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true

- name: Get current version from package.json
id: current_version
run: echo "version=$(node -p "require('./package.json').version")" >> "$GITHUB_OUTPUT"

- name: Calculate new version
id: version
env:
CURRENT_VERSION: ${{ steps.current_version.outputs.version }}
INPUT_VERSION: ${{ github.event.inputs.version }}
BUMP_TYPE: ${{ github.event.inputs.bump }}
run: |
set -euo pipefail
if [[ -n "$INPUT_VERSION" ]]; then
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
fi
echo "version=$INPUT_VERSION" >> "$GITHUB_OUTPUT"
else
IFS='.' read -r major minor patch <<< "$CURRENT_VERSION"
case "$BUMP_TYPE" in
major) echo "version=$((major+1)).0.0" >> "$GITHUB_OUTPUT" ;;
minor) echo "version=$major.$((minor+1)).0" >> "$GITHUB_OUTPUT" ;;
patch) echo "version=$major.$minor.$((patch+1))" >> "$GITHUB_OUTPUT" ;;
*) echo "Error: unknown bump type $BUMP_TYPE"; exit 1 ;;
esac
fi

- name: Update package.json version
run: |
node -e "
const pkg = require('./package.json');
pkg.version = '${{ steps.version.outputs.version }}';
require('fs').writeFileSync('./package.json', JSON.stringify(pkg, null, 2) + '\n');
"

- name: Setup Bun
uses: oven-sh/setup-bun@v2

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
registry-url: 'https://registry.npmjs.org'

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Run tests
run: bun run test

- name: Build package
run: bun run build

- name: Commit and tag
env:
VERSION: ${{ steps.version.outputs.version }}
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add package.json
if git ls-files --modified --others | grep -q bun.lock; then
git add bun.lock
fi
git commit -m "chore: release v${VERSION}"
git tag "v${VERSION}"
git push origin "v${VERSION}"
git push origin HEAD:main

- name: Publish to npm
if: ${{ github.event.inputs.dry_run != 'true' }}
run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ steps.version.outputs.version }}
generate_release_notes: true
draft: ${{ github.event.inputs.dry_run == 'true' }}
name: v${{ steps.version.outputs.version }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
node_modules/
dist/
*.tsbuildinfo
.DS_Store

# Local agent notes / environment-specific
AGENTS.md
7 changes: 7 additions & 0 deletions .opencode/opencode.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["file://."],
"provider": {
"command-code": { "name": "Command Code" }
}
}
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Changelog

## 0.1.0

- Initial release: Command Code OpenCode plugin
- Local OpenAI-compatible proxy → `api.commandcode.ai/alpha/generate`
- Auth via Command Code Go-plan browser OAuth (`cmd login`) — no Studio API key
- Default model: Laguna S 2.1 free (`poolside/laguna-s-2.1-free`)
- Tools/MCP park-resume, attachment plumbing, context compact, usage endpoints
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 Otto Assistant contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
121 changes: 120 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,120 @@
# opencode-commandcode
<p align="center">
<img src="docs/header.svg" width="828" alt="opencode-commandcode — Command Code in OpenCode, Laguna S 2.1 gateway">
</p>

<p align="center">
<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>
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-7dcea0?style=flat-square&labelColor=0c1412" alt="MIT license"></a>
<img src="https://img.shields.io/badge/linux%20·%20macos%20·%20windows-7dcea0?style=flat-square&labelColor=0c1412" alt="linux, macos, windows">
</p>

<p align="center">
<strong>Command Code inside OpenCode</strong> — Go-plan ($1) browser login,<br>
gateway proxy, free Laguna S 2.1, tools/MCP, attachments, compact, usage.
</p>

---

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).

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).

## Install

```bash
# global (recommended)
opencode plugin @otto-assistant/opencode-commandcode -g

# or project-local
opencode plugin @otto-assistant/opencode-commandcode
```

Optional provider naming:

```jsonc
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["@otto-assistant/opencode-commandcode"],
"provider": {
"command-code": { "name": "Command Code" }
}
}
```

From source:

```bash
git clone https://github.com/otto-assistant/opencode-commandcode.git
cd opencode-commandcode
bun install && bun run build
opencode plugin file://$PWD
```

## Authenticate

Uses the **Command Code Go plan ($1/mo)** — same browser login as `cmd login`. No Studio API key.

```bash
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 "Login with Command Code (Go $1)" — or "Use existing cmd login session"
```

Then:

```bash
opencode run "Summarise this repository in five bullets." --model command-code/laguna-s-2.1-free
```

Laguna S 2.1 free requires an active Go (or higher) account with credits on file; requests on that model still bill **$0**.

## Why this plugin

| | |
|---|---|
| **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. |
| **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. |
| **Usage** | Per-turn and session totals via SSE `usage` + `GET /v1/usage`. |

## Architecture

```text
OpenCode
└─ /v1/chat/completions
└─ Bun.serve proxy (port 8797)
└─ POST https://api.commandcode.ai/alpha/generate
└─ poolside/laguna-s-2.1-free (default)
```

## 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
- Bun (plugin runtime) · Node.js ≥ 18 (CLI needs ≥ 22)

## Development

```bash
bun install
bun run build
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`.

Optional knobs:

- `OPENCODE_COMMANDCODE_PROXY_PORT` — fixed local proxy port (default `8797`)
- `OPENCODE_COMMANDCODE_CWD` — working directory reported to the gateway
- `COMMANDCODE_API_URL` — override API base (default `https://api.commandcode.ai`)

## License

[MIT](LICENSE)
92 changes: 92 additions & 0 deletions bun.lock

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

Loading