Compare commits

..

16 Commits

Author SHA1 Message Date
opencode a071a2b7f4 release: v0.4.27 2025-08-12 12:58:53 +00:00
adamdotdevin b2f2c9ac37 fix: use real cursor instead of virtual cursor 2025-08-12 07:52:19 -05:00
GitHub Action 631722213b ignore: update download stats 2025-08-12 2025-08-12 12:04:42 +00:00
Camden Clark 80b25c79bb fix: preserve process.env when spawning formatter commands (#1850) 2025-08-12 02:05:26 -04:00
Dax 3d9c5b4adf Update guidelines-check.yml 2025-08-12 00:34:34 -04:00
Dax a3064e2c32 Update duplicate-issues.yml 2025-08-12 00:34:16 -04:00
Dax Raad 275bc4d2c8 ci: add guidelines check workflow for PRs 2025-08-12 00:01:59 -04:00
Dax Raad 39106718ed ci: tweak 2025-08-11 23:52:16 -04:00
Dax Raad 02cfdfbf5b ci: add duplicate issue detection workflow 2025-08-11 23:51:08 -04:00
Dax Raad 1ec71e419b support wildcard matching tool names in config 2025-08-11 23:37:09 -04:00
opencode 5fbbdcaf64 release: v0.4.26 2025-08-12 03:25:36 +00:00
Dax Raad 2b6afe90d0 fix azure reasoningEffort 2025-08-11 23:20:19 -04:00
Dax Raad 5f34dcc792 azure reasoning effort 2025-08-11 23:04:32 -04:00
opencode 681abcbf2d release: v0.4.25 2025-08-12 02:51:32 +00:00
Dax Raad 603e81ef5a Simplify git-committer agent definition for better maintainability 2025-08-11 22:45:40 -04:00
Dax Raad fb0a200ecf refactor: replace OPENCODE_AGENTS env var with HTTP API call
Replace environment variable passing of agent data from Node.js to TUI
with proper HTTP API call to /agent endpoint. This improves architecture
by eliminating env var dependencies and allows dynamic agent data fetching.
2025-08-11 22:42:25 -04:00
24 changed files with 160 additions and 85 deletions
+10
View File
@@ -0,0 +1,10 @@
---
description: Use this agent when you are saked to commit and push code changes to a git repository.
mode: subagent
---
You commit and push to git
Commit messages should be brief since they are used to generate release notes.
Messages should say WHY the change was made and not WHAT was changed.
+46 -45
View File
@@ -1,47 +1,48 @@
# Download Stats
| Date | GitHub Downloads | npm Downloads | Total |
| ---------- | ---------------- | ---------------- | ---------------- |
| 2025-06-29 | 18,789 (+0) | 39,420 (+0) | 58,209 (+0) |
| 2025-06-30 | 20,127 (+1,338) | 41,059 (+1,639) | 61,186 (+2,977) |
| 2025-07-01 | 22,108 (+1,981) | 43,745 (+2,686) | 65,853 (+4,667) |
| 2025-07-02 | 24,814 (+2,706) | 46,168 (+2,423) | 70,982 (+5,129) |
| 2025-07-03 | 27,834 (+3,020) | 49,955 (+3,787) | 77,789 (+6,807) |
| 2025-07-04 | 30,608 (+2,774) | 54,758 (+4,803) | 85,366 (+7,577) |
| 2025-07-05 | 32,524 (+1,916) | 58,371 (+3,613) | 90,895 (+5,529) |
| 2025-07-06 | 33,766 (+1,242) | 59,694 (+1,323) | 93,460 (+2,565) |
| 2025-07-08 | 38,052 (+4,286) | 64,468 (+4,774) | 102,520 (+9,060) |
| 2025-07-09 | 40,924 (+2,872) | 67,935 (+3,467) | 108,859 (+6,339) |
| 2025-07-10 | 43,796 (+2,872) | 71,402 (+3,467) | 115,198 (+6,339) |
| 2025-07-11 | 46,982 (+3,186) | 77,462 (+6,060) | 124,444 (+9,246) |
| 2025-07-12 | 49,302 (+2,320) | 82,177 (+4,715) | 131,479 (+7,035) |
| 2025-07-13 | 50,803 (+1,501) | 86,394 (+4,217) | 137,197 (+5,718) |
| 2025-07-14 | 53,283 (+2,480) | 87,860 (+1,466) | 141,143 (+3,946) |
| 2025-07-15 | 57,590 (+4,307) | 91,036 (+3,176) | 148,626 (+7,483) |
| 2025-07-16 | 62,313 (+4,723) | 95,258 (+4,222) | 157,571 (+8,945) |
| 2025-07-17 | 66,684 (+4,371) | 100,048 (+4,790) | 166,732 (+9,161) |
| 2025-07-18 | 70,379 (+3,695) | 102,587 (+2,539) | 172,966 (+6,234) |
| 2025-07-19 | 73,497 (+3,117) | 105,904 (+3,317) | 179,401 (+6,434) |
| 2025-07-20 | 76,453 (+2,956) | 109,044 (+3,140) | 185,497 (+6,096) |
| 2025-07-21 | 80,197 (+3,744) | 113,537 (+4,493) | 193,734 (+8,237) |
| 2025-07-22 | 84,251 (+4,054) | 118,073 (+4,536) | 202,324 (+8,590) |
| 2025-07-23 | 88,589 (+4,338) | 121,436 (+3,363) | 210,025 (+7,701) |
| 2025-07-24 | 92,469 (+3,880) | 124,091 (+2,655) | 216,560 (+6,535) |
| 2025-07-25 | 96,417 (+3,948) | 126,985 (+2,894) | 223,402 (+6,842) |
| 2025-07-26 | 100,646 (+4,229) | 131,411 (+4,426) | 232,057 (+8,655) |
| 2025-07-27 | 102,644 (+1,998) | 134,736 (+3,325) | 237,380 (+5,323) |
| 2025-07-28 | 105,446 (+2,802) | 136,016 (+1,280) | 241,462 (+4,082) |
| 2025-07-29 | 108,998 (+3,552) | 137,542 (+1,526) | 246,540 (+5,078) |
| 2025-07-30 | 113,544 (+4,546) | 140,317 (+2,775) | 253,861 (+7,321) |
| 2025-07-31 | 118,339 (+4,795) | 143,344 (+3,027) | 261,683 (+7,822) |
| 2025-08-01 | 123,539 (+5,200) | 146,680 (+3,336) | 270,219 (+8,536) |
| 2025-08-02 | 127,864 (+4,325) | 149,236 (+2,556) | 277,100 (+6,881) |
| 2025-08-03 | 131,397 (+3,533) | 150,451 (+1,215) | 281,848 (+4,748) |
| 2025-08-04 | 136,266 (+4,869) | 153,260 (+2,809) | 289,526 (+7,678) |
| 2025-08-05 | 141,596 (+5,330) | 155,752 (+2,492) | 297,348 (+7,822) |
| 2025-08-06 | 147,067 (+5,471) | 158,309 (+2,557) | 305,376 (+8,028) |
| 2025-08-07 | 152,591 (+5,524) | 160,889 (+2,580) | 313,480 (+8,104) |
| 2025-08-08 | 158,187 (+5,596) | 163,448 (+2,559) | 321,635 (+8,155) |
| 2025-08-09 | 162,770 (+4,583) | 165,721 (+2,273) | 328,491 (+6,856) |
| 2025-08-10 | 165,695 (+2,925) | 167,109 (+1,388) | 332,804 (+4,313) |
| 2025-08-11 | 169,297 (+3,602) | 167,953 (+844) | 337,250 (+4,446) |
| Date | GitHub Downloads | npm Downloads | Total |
| ---------- | ---------------- | ---------------- | ----------------- |
| 2025-06-29 | 18,789 (+0) | 39,420 (+0) | 58,209 (+0) |
| 2025-06-30 | 20,127 (+1,338) | 41,059 (+1,639) | 61,186 (+2,977) |
| 2025-07-01 | 22,108 (+1,981) | 43,745 (+2,686) | 65,853 (+4,667) |
| 2025-07-02 | 24,814 (+2,706) | 46,168 (+2,423) | 70,982 (+5,129) |
| 2025-07-03 | 27,834 (+3,020) | 49,955 (+3,787) | 77,789 (+6,807) |
| 2025-07-04 | 30,608 (+2,774) | 54,758 (+4,803) | 85,366 (+7,577) |
| 2025-07-05 | 32,524 (+1,916) | 58,371 (+3,613) | 90,895 (+5,529) |
| 2025-07-06 | 33,766 (+1,242) | 59,694 (+1,323) | 93,460 (+2,565) |
| 2025-07-08 | 38,052 (+4,286) | 64,468 (+4,774) | 102,520 (+9,060) |
| 2025-07-09 | 40,924 (+2,872) | 67,935 (+3,467) | 108,859 (+6,339) |
| 2025-07-10 | 43,796 (+2,872) | 71,402 (+3,467) | 115,198 (+6,339) |
| 2025-07-11 | 46,982 (+3,186) | 77,462 (+6,060) | 124,444 (+9,246) |
| 2025-07-12 | 49,302 (+2,320) | 82,177 (+4,715) | 131,479 (+7,035) |
| 2025-07-13 | 50,803 (+1,501) | 86,394 (+4,217) | 137,197 (+5,718) |
| 2025-07-14 | 53,283 (+2,480) | 87,860 (+1,466) | 141,143 (+3,946) |
| 2025-07-15 | 57,590 (+4,307) | 91,036 (+3,176) | 148,626 (+7,483) |
| 2025-07-16 | 62,313 (+4,723) | 95,258 (+4,222) | 157,571 (+8,945) |
| 2025-07-17 | 66,684 (+4,371) | 100,048 (+4,790) | 166,732 (+9,161) |
| 2025-07-18 | 70,379 (+3,695) | 102,587 (+2,539) | 172,966 (+6,234) |
| 2025-07-19 | 73,497 (+3,117) | 105,904 (+3,317) | 179,401 (+6,434) |
| 2025-07-20 | 76,453 (+2,956) | 109,044 (+3,140) | 185,497 (+6,096) |
| 2025-07-21 | 80,197 (+3,744) | 113,537 (+4,493) | 193,734 (+8,237) |
| 2025-07-22 | 84,251 (+4,054) | 118,073 (+4,536) | 202,324 (+8,590) |
| 2025-07-23 | 88,589 (+4,338) | 121,436 (+3,363) | 210,025 (+7,701) |
| 2025-07-24 | 92,469 (+3,880) | 124,091 (+2,655) | 216,560 (+6,535) |
| 2025-07-25 | 96,417 (+3,948) | 126,985 (+2,894) | 223,402 (+6,842) |
| 2025-07-26 | 100,646 (+4,229) | 131,411 (+4,426) | 232,057 (+8,655) |
| 2025-07-27 | 102,644 (+1,998) | 134,736 (+3,325) | 237,380 (+5,323) |
| 2025-07-28 | 105,446 (+2,802) | 136,016 (+1,280) | 241,462 (+4,082) |
| 2025-07-29 | 108,998 (+3,552) | 137,542 (+1,526) | 246,540 (+5,078) |
| 2025-07-30 | 113,544 (+4,546) | 140,317 (+2,775) | 253,861 (+7,321) |
| 2025-07-31 | 118,339 (+4,795) | 143,344 (+3,027) | 261,683 (+7,822) |
| 2025-08-01 | 123,539 (+5,200) | 146,680 (+3,336) | 270,219 (+8,536) |
| 2025-08-02 | 127,864 (+4,325) | 149,236 (+2,556) | 277,100 (+6,881) |
| 2025-08-03 | 131,397 (+3,533) | 150,451 (+1,215) | 281,848 (+4,748) |
| 2025-08-04 | 136,266 (+4,869) | 153,260 (+2,809) | 289,526 (+7,678) |
| 2025-08-05 | 141,596 (+5,330) | 155,752 (+2,492) | 297,348 (+7,822) |
| 2025-08-06 | 147,067 (+5,471) | 158,309 (+2,557) | 305,376 (+8,028) |
| 2025-08-07 | 152,591 (+5,524) | 160,889 (+2,580) | 313,480 (+8,104) |
| 2025-08-08 | 158,187 (+5,596) | 163,448 (+2,559) | 321,635 (+8,155) |
| 2025-08-09 | 162,770 (+4,583) | 165,721 (+2,273) | 328,491 (+6,856) |
| 2025-08-10 | 165,695 (+2,925) | 167,109 (+1,388) | 332,804 (+4,313) |
| 2025-08-11 | 169,297 (+3,602) | 167,953 (+844) | 337,250 (+4,446) |
| 2025-08-12 | 176,307 (+7,010) | 171,876 (+3,923) | 348,183 (+10,933) |
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@opencode/cloud-core",
"version": "0.4.24",
"version": "0.4.27",
"private": true,
"type": "module",
"dependencies": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@opencode/cloud-function",
"version": "0.4.24",
"version": "0.4.27",
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"type": "module",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@opencode/cloud-web",
"version": "0.4.24",
"version": "0.4.27",
"private": true,
"description": "",
"type": "module",
+3
View File
@@ -1,5 +1,8 @@
{
"$schema": "https://opencode.ai/config.json",
"agent": {
"build": {}
},
"mcp": {
"context7": {
"type": "remote",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@opencode/function",
"version": "0.4.24",
"version": "0.4.27",
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"type": "module",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/package.json",
"version": "0.4.24",
"version": "0.4.27",
"name": "opencode",
"type": "module",
"private": true,
+1 -2
View File
@@ -12,7 +12,7 @@ import { Bus } from "../../bus"
import { Log } from "../../util/log"
import { FileWatcher } from "../../file/watch"
import { Ide } from "../../ide"
import { Agent } from "../../agent/agent"
import { Flag } from "../../flag/flag"
import { Session } from "../../session"
@@ -141,7 +141,6 @@ export const TuiCommand = cmd({
CGO_ENABLED: "0",
OPENCODE_SERVER: server.url.toString(),
OPENCODE_APP_INFO: JSON.stringify(app),
OPENCODE_AGENTS: JSON.stringify(await Agent.list()),
},
onExit: () => {
server.stop()
+1 -1
View File
@@ -71,7 +71,7 @@ export namespace Format {
const proc = Bun.spawn({
cmd: item.command.map((x) => x.replace("$FILE", file)),
cwd: App.info().path.cwd,
env: item.environment,
env: { ...process.env, ...item.environment },
stdout: "ignore",
stderr: "ignore",
})
+1 -1
View File
@@ -27,7 +27,7 @@ await Promise.all([
fs.mkdir(Global.Path.log, { recursive: true }),
])
const CACHE_VERSION = "6"
const CACHE_VERSION = "7"
const version = await Bun.file(path.join(Global.Path.cache, "version"))
.text()
+1 -2
View File
@@ -87,8 +87,7 @@ export namespace ProviderTransform {
if (modelID.includes("gpt-5")) {
if (providerID === "azure") {
return {
reasoning_effort: "minimal",
text_verbosity: "verbose",
reasoningEffort: "minimal",
}
}
return {
+3 -2
View File
@@ -42,6 +42,7 @@ import { ToolRegistry } from "../tool/registry"
import { Plugin } from "../plugin"
import { Agent } from "../agent/agent"
import { Permission } from "../permission"
import { Wildcard } from "../util/wildcard"
export namespace Session {
const log = Log.create({ service: "session" })
@@ -768,7 +769,7 @@ export namespace Session {
mergeDeep(input.tools ?? {}),
)
for (const item of await ToolRegistry.tools(input.providerID, input.modelID)) {
if (enabledTools[item.id] === false) continue
if (Wildcard.all(item.id, enabledTools) === false) continue
tools[item.id] = tool({
id: item.id as any,
description: item.description,
@@ -829,7 +830,7 @@ export namespace Session {
}
for (const [key, item] of Object.entries(await MCP.tools())) {
if (enabledTools[key] === false) continue
if (Wildcard.all(key, enabledTools) === false) continue
const execute = item.execute
if (!execute) continue
item.execute = async (args, opts) => {
+14
View File
@@ -1,3 +1,5 @@
import { sortBy, pipe } from "remeda"
export namespace Wildcard {
export function match(str: string, pattern: string) {
const regex = new RegExp(
@@ -11,4 +13,16 @@ export namespace Wildcard {
)
return regex.test(str)
}
export function all(input: string, patterns: Record<string, any>) {
const sorted = pipe(patterns, Object.entries, sortBy([([key]) => key.length, "asc"], [([key]) => key, "asc"]))
let result = undefined
for (const [pattern, value] of sorted) {
if (match(input, pattern)) {
result = value
continue
}
}
return result
}
}
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@opencode-ai/plugin",
"version": "0.4.24",
"version": "0.4.27",
"type": "module",
"scripts": {
"typecheck": "tsc --noEmit"
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@opencode-ai/sdk",
"version": "0.4.24",
"version": "0.4.27",
"type": "module",
"scripts": {
"typecheck": "tsc --noEmit"
+13 -9
View File
@@ -45,14 +45,6 @@ func main() {
os.Exit(1)
}
agentsStr := os.Getenv("OPENCODE_AGENTS")
var agents []opencode.Agent
err = json.Unmarshal([]byte(agentsStr), &agents)
if err != nil {
slog.Error("Failed to unmarshal modes", "error", err)
os.Exit(1)
}
stat, err := os.Stdin.Stat()
if err != nil {
slog.Error("Failed to stat stdin", "error", err)
@@ -81,13 +73,25 @@ func main() {
option.WithBaseURL(url),
)
// Fetch agents from the /agent endpoint
agentsPtr, err := httpClient.App.Agents(context.Background())
if err != nil {
slog.Error("Failed to fetch agents", "error", err)
os.Exit(1)
}
if agentsPtr == nil {
slog.Error("No agents returned from server")
os.Exit(1)
}
agents := *agentsPtr
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
apiHandler := util.NewAPILogHandler(ctx, httpClient, "tui", slog.LevelDebug)
logger := slog.New(apiHandler)
slog.SetDefault(logger)
slog.Debug("TUI launched", "app", appInfoStr, "modes", agentsStr, "url", url)
slog.Debug("TUI launched", "app", appInfoStr, "agents_count", len(agents), "url", url)
go func() {
err = clipboard.Init()
@@ -31,6 +31,7 @@ type EditorComponent interface {
tea.Model
tea.ViewModel
Content() string
Cursor() *tea.Cursor
Lines() int
Value() string
Length() int
@@ -407,6 +408,10 @@ func (m *editorComponent) Content() string {
return content
}
func (m *editorComponent) Cursor() *tea.Cursor {
return m.textarea.Cursor()
}
func (m *editorComponent) View() string {
width := m.width
if m.app.Session.ID == "" {
@@ -694,6 +699,7 @@ func NewEditorComponent(app *app.App) EditorComponent {
ta.Prompt = " "
ta.ShowLineNumbers = false
ta.CharLimit = -1
ta.VirtualCursor = false
ta = updateTextareaStyles(ta)
m := &editorComponent{
+35 -13
View File
@@ -59,6 +59,8 @@ const interruptDebounceTimeout = 1 * time.Second
const exitDebounceTimeout = 1 * time.Second
type Model struct {
tea.Model
tea.CursorModel
width, height int
app *app.App
modal layout.Modal
@@ -748,15 +750,17 @@ func (a Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return a, tea.Batch(cmds...)
}
func (a Model) View() string {
func (a Model) View() (string, *tea.Cursor) {
t := theme.CurrentTheme()
var mainLayout string
var editorX int
var editorY int
if a.app.Session.ID == "" {
mainLayout = a.home()
mainLayout, editorX, editorY = a.home()
} else {
mainLayout = a.chat()
mainLayout, editorX, editorY = a.chat()
}
mainLayout = styles.NewStyle().
Background(t.Background()).
@@ -780,7 +784,12 @@ func (a Model) View() string {
if theme.CurrentThemeUsesAnsiColors() {
mainLayout = util.ConvertRGBToAnsi16Colors(mainLayout)
}
return mainLayout + "\n" + a.status.View()
cursor := a.editor.Cursor()
cursor.Position.X += editorX
cursor.Position.Y += editorY
return mainLayout + "\n" + a.status.View(), cursor
}
func (a Model) Cleanup() {
@@ -807,7 +816,7 @@ func (a Model) openFile(filepath string) (tea.Model, tea.Cmd) {
return a, cmd
}
func (a Model) home() string {
func (a Model) home() (string, int, int) {
t := theme.CurrentTheme()
effectiveWidth := a.width - 4
baseStyle := styles.NewStyle().Background(t.Background())
@@ -899,14 +908,21 @@ func (a Model) home() string {
styles.WhitespaceStyle(t.Background()),
)
editorX := (effectiveWidth - editorWidth) / 2
editorX := max(0, (effectiveWidth-editorWidth)/2)
editorY := (a.height / 2) + (mainHeight / 2) - 2
if editorLines > 1 {
content := a.editor.Content()
editorHeight := lipgloss.Height(content)
if editorY+editorHeight > a.height {
difference := (editorY + editorHeight) - a.height
editorY -= difference
}
mainLayout = layout.PlaceOverlay(
editorX,
editorY,
a.editor.Content(),
content,
mainLayout,
)
}
@@ -924,10 +940,10 @@ func (a Model) home() string {
)
}
return mainLayout
return mainLayout, editorX + 5, editorY + 2
}
func (a Model) chat() string {
func (a Model) chat() (string, int, int) {
effectiveWidth := a.width - 4
t := theme.CurrentTheme()
editorView := a.editor.View()
@@ -944,14 +960,20 @@ func (a Model) chat() string {
)
mainLayout := messagesView + "\n" + editorView
editorX := (effectiveWidth - editorWidth) / 2
editorX := max(0, (effectiveWidth-editorWidth)/2)
editorY := a.height - editorHeight
if lines > 1 {
editorY := a.height - editorHeight
content := a.editor.Content()
editorHeight := lipgloss.Height(content)
if editorY+editorHeight > a.height {
difference := (editorY + editorHeight) - a.height
editorY -= difference
}
mainLayout = layout.PlaceOverlay(
editorX,
editorY,
a.editor.Content(),
content,
mainLayout,
)
}
@@ -970,7 +992,7 @@ func (a Model) chat() string {
)
}
return mainLayout
return mainLayout, editorX + 5, editorY + 2
}
func (a Model) executeCommand(command commands.Command) (tea.Model, tea.Cmd) {
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@opencode/web",
"type": "module",
"version": "0.4.24",
"version": "0.4.27",
"scripts": {
"dev": "astro dev",
"dev:remote": "sst shell --stage=dev --target=Web astro dev",
+17 -1
View File
@@ -318,6 +318,22 @@ Control which tools are available in this agent with the `tools` config. You can
}
```
You can also use wildcards to control multiple tools at once. For example, to disable all tools from an MCP server:
```json title="opencode.json"
{
"agent": {
"readonly": {
"tools": {
"mymcp_*": false,
"write": false,
"edit": false
}
}
}
}
```
If no tools are specified, all tools are enabled by default.
---
@@ -371,7 +387,7 @@ For example, with OpenAI's reasoning models, you can control the reasoning effor
"agent": {
"deep-thinker": {
"description": "Agent that uses high reasoning effort for complex problems",
"model": "openai/gpt-5-turbo",
"model": "openai/gpt-5-turbo",
"reasoningEffort": "high",
"textVerbosity": "low"
}
+1 -1
View File
@@ -2,7 +2,7 @@
"name": "opencode",
"displayName": "opencode",
"description": "opencode for VS Code",
"version": "0.4.24",
"version": "0.4.27",
"publisher": "sst-dev",
"repository": {
"type": "git",