Compare commits

...

19 Commits

Author SHA1 Message Date
Dax Raad 23c30521d8 only enable ruff if it seems to be used 2025-07-17 18:07:06 -04:00
Wendell Misiedjan e681d610de feat: support AWS_BEARER_TOKEN_BEDROCK for amazon bedrock provider autoloading (#1094) 2025-07-17 09:12:30 -05:00
Aiden Cline a1fdeded3e tweak: allow mcp servers to include headers (#1096) 2025-07-17 09:11:48 -05:00
GitHub Action 2051312d12 ignore: update download stats 2025-07-17 2025-07-17 14:07:13 +00:00
Alexander Drottsgård 20cb7a76af feat(tui): highlight current session in sessions modal (#1093) 2025-07-17 07:40:15 -05:00
Timo Clasen a493aec174 feat(tui): remove share commands from help if sharing is disabled (#1087) 2025-07-17 04:28:12 -05:00
Aiden Cline 3ce3ac8e61 fix: message error centering (#1085) 2025-07-17 04:27:40 -05:00
Timo Clasen 91ad64feda fix(tui): user defined ctrl+z should take precedence over suspending (#1088) 2025-07-17 04:27:02 -05:00
Timo Clasen 60b55f9d92 feat(tui): remove sharing info from session header when sharing is disabled (#1076) 2025-07-16 17:36:48 -05:00
Timo Clasen 3c6c2bf13b docs(share): add explicit manual share mode (#1074) 2025-07-16 16:08:25 -05:00
Aiden Cline d4f9375548 fix: type 'reasoning' was provided without its required following item (#1072) 2025-07-16 15:59:40 -05:00
Jay V 28b39f547e docs: edit 2025-07-16 16:59:12 -04:00
Jay V 7520f5efa8 docs: update enterprise doc 2025-07-16 16:44:28 -04:00
Jay V eb4cdf4b20 docs: config doc 2025-07-16 16:27:44 -04:00
Jay V 9f6fc1c3c5 docs: edits 2025-07-16 16:20:09 -04:00
Mike Wallio dfede9ae6e Remove binary file opencode (#1069) 2025-07-16 15:10:40 -05:00
Daniel Saldarriaga López fc45c0c944 docs: fix keybinds documentation to match actual config schema (#867) 2025-07-16 15:34:52 -04:00
adamdotdevin 9d869f784c fix(tui): expand edit calls 2025-07-16 14:33:57 -05:00
adamdotdevin bd244f73af fix(tui): slightly faster scroll speed 2025-07-16 14:26:46 -05:00
21 changed files with 294 additions and 107 deletions
+19 -18
View File
@@ -1,20 +1,21 @@
# 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-10 | 43,796 (+5,744) | 71,402 (+6,934) | 115,198 (+12,678) |
| 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) |
| 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-10 | 43,796 (+5,744) | 71,402 (+6,934) | 115,198 (+12,678) |
| 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) |
+4 -4
View File
@@ -100,7 +100,7 @@
],
"catalog": {
"@types/node": "22.13.9",
"ai": "5.0.0-beta.18",
"ai": "5.0.0-beta.21",
"typescript": "5.8.2",
"zod": "3.25.49",
},
@@ -109,11 +109,11 @@
"@ai-sdk/anthropic": ["@ai-sdk/anthropic@1.2.12", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "@ai-sdk/provider-utils": "2.2.8" }, "peerDependencies": { "zod": "^3.0.0" } }, "sha512-YSzjlko7JvuiyQFmI9RN1tNZdEiZxc+6xld/0tq/VkJaHpEzGAb1yiNxxvmYVcjvfu/PcvCxAAYXmTYQQ63IHQ=="],
"@ai-sdk/gateway": ["@ai-sdk/gateway@1.0.0-beta.7", "", { "dependencies": { "@ai-sdk/provider": "2.0.0-beta.1", "@ai-sdk/provider-utils": "3.0.0-beta.2" }, "peerDependencies": { "zod": "^3.25.49" } }, "sha512-0TOWFetxYximugqdmA/uxk+NRkz51Lyo+anntc3hPzm2OnsbE/Q2wWkKJ14YzoCAfWZ9ZhvxsJRp8xzvvQREsA=="],
"@ai-sdk/gateway": ["@ai-sdk/gateway@1.0.0-beta.8", "", { "dependencies": { "@ai-sdk/provider": "2.0.0-beta.1", "@ai-sdk/provider-utils": "3.0.0-beta.3" }, "peerDependencies": { "zod": "^3.25.49 || ^4" } }, "sha512-D2SqYRT/42JTiRxUuiWtn5cYQFscpb9Z14UNvJx7lnurBUXx57zy7TbLH0h7O+WbCluTQN5G6146JpUZ/SRyzw=="],
"@ai-sdk/provider": ["@ai-sdk/provider@2.0.0-beta.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-Z8SPncMtS3RsoXITmT7NVwrAq6M44dmw0DoUOYJqNNtCu8iMWuxB8Nxsoqpa0uEEy9R1V1ZThJAXTYgjTUxl3w=="],
"@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.0-beta.2", "", { "dependencies": { "@ai-sdk/provider": "2.0.0-beta.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.3", "zod-to-json-schema": "^3.24.1" }, "peerDependencies": { "zod": "^3.25.49" } }, "sha512-H4K+4weOVgWqrDDeAbQWoA4U5mN4WrQPHQFdH7ynQYcnhj/pzctU9Q6mGlR5ESMWxaXxazxlOblSITlXo9bahA=="],
"@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.0-beta.3", "", { "dependencies": { "@ai-sdk/provider": "2.0.0-beta.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.3", "zod-to-json-schema": "^3.24.1" }, "peerDependencies": { "zod": "^3.25.49 || ^4" } }, "sha512-4gZ392GxjzMF7TnReF2eTKhOSyiSS3ydRVq4I7jxkeV5sdEuMoH3gzfItmlctsqGxlMU1/+zKPwl5yYz9O2dzg=="],
"@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="],
@@ -543,7 +543,7 @@
"acorn-walk": ["acorn-walk@8.3.2", "", {}, "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A=="],
"ai": ["ai@5.0.0-beta.18", "", { "dependencies": { "@ai-sdk/gateway": "1.0.0-beta.7", "@ai-sdk/provider": "2.0.0-beta.1", "@ai-sdk/provider-utils": "3.0.0-beta.2", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.49" } }, "sha512-gUkO9WF315aT6Al7FxBpY41z3aOVE11BdQUIdIekP1sebys4dElMmKjs9AoaNeYPcf+PklwQ6ZofztiT0egd4A=="],
"ai": ["ai@5.0.0-beta.21", "", { "dependencies": { "@ai-sdk/gateway": "1.0.0-beta.8", "@ai-sdk/provider": "2.0.0-beta.1", "@ai-sdk/provider-utils": "3.0.0-beta.3", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.49 || ^4" }, "bin": { "ai": "dist/bin/ai.min.js" } }, "sha512-ZmgUoEIXb2G2HLtK1U3UB+hSDa3qrVIeAfgXf3SIE9r5Vqj6xHG1pN/7fHIZDSgb1TCaypG0ANVB0O9WmnMfiw=="],
"ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="],
+1 -1
View File
@@ -18,7 +18,7 @@
"typescript": "5.8.2",
"@types/node": "22.13.9",
"zod": "3.25.49",
"ai": "5.0.0-beta.18"
"ai": "5.0.0-beta.21"
}
},
"devDependencies": {
+1 -1
View File
@@ -120,7 +120,7 @@ export const AuthLoginCommand = cmd({
if (provider === "amazon-bedrock") {
prompts.log.info(
"Amazon bedrock can be configured with standard AWS environment variables like AWS_PROFILE or AWS_ACCESS_KEY_ID",
"Amazon bedrock can be configured with standard AWS environment variables like AWS_BEARER_TOKEN_BEDROCK, AWS_PROFILE or AWS_ACCESS_KEY_ID",
)
prompts.outro("Done")
return
+8 -2
View File
@@ -31,6 +31,9 @@ export namespace Config {
const os = await import("os")
result.username = os.userInfo().username
}
if (!result.layout) {
result.layout = "auto"
}
log.info("loaded", result)
@@ -57,6 +60,7 @@ export namespace Config {
type: z.literal("remote").describe("Type of MCP server connection"),
url: z.string().describe("URL of the remote MCP server"),
enabled: z.boolean().optional().describe("Enable or disable the MCP server on startup"),
headers: z.record(z.string(), z.string()).optional().describe("Headers to send with the request"),
})
.strict()
.openapi({
@@ -136,9 +140,11 @@ export namespace Config {
theme: z.string().optional().describe("Theme name to use for the interface"),
keybinds: Keybinds.optional().describe("Custom keybind configurations"),
share: z
.enum(["auto", "disabled"])
.enum(["manual", "auto", "disabled"])
.optional()
.describe("Control sharing behavior: 'auto' enables automatic sharing, 'disabled' disables all sharing"),
.describe(
"Control sharing behavior:'manual' allows manual sharing via commands, 'auto' enables automatic sharing, 'disabled' disables all sharing",
),
autoshare: z
.boolean()
.optional()
+23 -1
View File
@@ -105,7 +105,29 @@ export const ruff: Info = {
command: ["ruff", "format", "$FILE"],
extensions: [".py", ".pyi"],
async enabled() {
return Bun.which("ruff") !== null
if (!Bun.which("ruff")) return false
const app = App.info()
const configs = ["pyproject.toml", "ruff.toml", ".ruff.toml"]
for (const config of configs) {
const found = await Filesystem.findUp(config, app.path.cwd, app.path.root)
if (found.length > 0) {
if (config === "pyproject.toml") {
const content = await Bun.file(found[0]).text()
if (content.includes("[tool.ruff]")) return true
} else {
return true
}
}
}
const deps = ["requirements.txt", "pyproject.toml", "Pipfile"]
for (const dep of deps) {
const found = await Filesystem.findUp(dep, app.path.cwd, app.path.root)
if (found.length > 0) {
const content = await Bun.file(found[0]).text()
if (content.includes("ruff")) return true
}
}
return false
},
}
+1
View File
@@ -37,6 +37,7 @@ export namespace MCP {
transport: {
type: "sse",
url: mcp.url,
headers: mcp.headers,
},
}).catch(() => {})
if (!client) {
+2 -1
View File
@@ -139,7 +139,8 @@ export namespace Provider {
}
},
"amazon-bedrock": async () => {
if (!process.env["AWS_PROFILE"] && !process.env["AWS_ACCESS_KEY_ID"]) return { autoload: false }
if (!process.env["AWS_PROFILE"] && !process.env["AWS_ACCESS_KEY_ID"] && !process.env["AWS_BEARER_TOKEN_BEDROCK"])
return { autoload: false }
const region = process.env["AWS_REGION"] ?? "us-east-1"
+1
View File
@@ -1 +1,2 @@
opencode-test
cmd/opencode/opencode
Binary file not shown.
@@ -344,6 +344,10 @@ func LoadFromConfig(config *opencode.Config) CommandRegistry {
marshalled, _ := json.Marshal(config.Keybinds)
json.Unmarshal(marshalled, &keybinds)
for _, command := range defaults {
// Remove share/unshare commands if sharing is disabled
if config.Share == opencode.ConfigShareDisabled && (command.Name == SessionShareCommand || command.Name == SessionUnshareCommand) {
continue
}
if keybind, ok := keybinds[string(command.Name)]; ok && keybind != "" {
command.Keybindings = parseBindings(keybind)
}
@@ -380,6 +380,12 @@ func (m *messagesComponent) renderView() {
width,
WithBorderColor(t.Error()),
)
error = lipgloss.PlaceHorizontal(
m.width,
lipgloss.Center,
error,
styles.WhitespaceStyle(t.Background()),
)
blocks = append(blocks, error)
m.lineCount += lipgloss.Height(error) + 1
}
@@ -448,23 +454,30 @@ func (m *messagesComponent) renderHeader() string {
Render(formatTokensAndCost(tokens, contextWindow, cost, isSubscriptionModel))
background := t.Background()
share = layout.Render(
var items []layout.FlexItem
justify := layout.JustifyEnd
if m.app.Config.Share != opencode.ConfigShareDisabled {
items = append(items, layout.FlexItem{View: share})
justify = layout.JustifySpaceBetween
}
items = append(items, layout.FlexItem{View: sessionInfo})
headerRow := layout.Render(
layout.FlexOptions{
Background: &background,
Direction: layout.Row,
Justify: layout.JustifySpaceBetween,
Justify: justify,
Align: layout.AlignStretch,
Width: headerWidth - 6,
},
layout.FlexItem{
View: share,
},
layout.FlexItem{
View: sessionInfo,
},
items...,
)
headerLines = append(headerLines, share)
headerLines = append(headerLines, headerRow)
header := strings.Join(headerLines, "\n")
header = styles.NewStyle().
Background(t.Background()).
@@ -616,6 +629,7 @@ func (m *messagesComponent) CopyLastMessage() (tea.Model, tea.Cmd) {
func NewMessagesComponent(app *app.App) MessagesComponent {
vp := viewport.New()
vp.KeyMap = viewport.KeyMap{}
vp.MouseWheelDelta = 4
return &messagesComponent{
app: app,
@@ -28,6 +28,7 @@ type SessionDialog interface {
type sessionItem struct {
title string
isDeleteConfirming bool
isCurrentSession bool
}
func (s sessionItem) Render(
@@ -42,7 +43,11 @@ func (s sessionItem) Render(
if s.isDeleteConfirming {
text = "Press again to confirm delete"
} else {
text = s.title
if s.isCurrentSession {
text = "● " + s.title
} else {
text = s.title
}
}
truncatedStr := truncate.StringWithTail(text, uint(width-1), "...")
@@ -56,6 +61,14 @@ func (s sessionItem) Render(
Foreground(t.BackgroundElement()).
Width(width).
PaddingLeft(1)
} else if s.isCurrentSession {
// Different style for current session when selected
itemStyle = baseStyle.
Background(t.Primary()).
Foreground(t.BackgroundElement()).
Width(width).
PaddingLeft(1).
Bold(true)
} else {
// Normal selection
itemStyle = baseStyle.
@@ -70,6 +83,12 @@ func (s sessionItem) Render(
itemStyle = baseStyle.
Foreground(t.Error()).
PaddingLeft(1)
} else if s.isCurrentSession {
// Highlight current session when not selected
itemStyle = baseStyle.
Foreground(t.Primary()).
PaddingLeft(1).
Bold(true)
} else {
itemStyle = baseStyle.
PaddingLeft(1)
@@ -194,6 +213,7 @@ func (s *sessionDialog) updateListItems() {
item := sessionItem{
title: sess.Title,
isDeleteConfirming: s.deleteConfirmation == i,
isCurrentSession: s.app.Session != nil && s.app.Session.ID == sess.ID,
}
items = append(items, item)
}
@@ -229,6 +249,7 @@ func NewSessionDialog(app *app.App) SessionDialog {
items = append(items, sessionItem{
title: sess.Title,
isDeleteConfirming: false,
isCurrentSession: app.Session != nil && app.Session.ID == sess.ID,
})
}
+5 -5
View File
@@ -110,11 +110,6 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case tea.KeyPressMsg:
keyString := msg.String()
// Handle Ctrl+Z for suspend
if keyString == "ctrl+z" {
return a, tea.Suspend
}
// 1. Handle active modal
if a.modal != nil {
switch keyString {
@@ -277,6 +272,11 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return a, util.CmdHandler(commands.ExecuteCommandsMsg(matches))
}
// Fallback: suspend if ctrl+z is pressed and no user keybind matched
if keyString == "ctrl+z" {
return a, tea.Suspend
}
// 10. Fallback to editor. This is for other characters like backspace, tab, etc.
updatedEditor, cmd := a.editor.Update(msg)
a.editor = updatedEditor.(chat.EditorComponent)
+70 -4
View File
@@ -10,7 +10,6 @@ You can configure opencode using a JSON config file.
"$schema": "https://opencode.ai/config.json",
"theme": "opencode",
"model": "anthropic/claude-sonnet-4-20250514",
"autoshare": false,
"autoupdate": true
}
```
@@ -93,6 +92,24 @@ You can configure the theme you want to use in your opencode config through the
---
### Layout
You can configure the layout of the TUI with the `layout` option.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"layout": "stretch"
}
```
This takes:
- `"auto"`: Centers content with padding. This is the default.
- `"stretch"`: Uses full terminal width.
---
### Logging
Logs are written to:
@@ -118,8 +135,28 @@ With the following options:
| `WARN` | Warnings and errors only |
| `ERROR` | Errors only |
The **default** log level is `INFO`. If you are running opencode locally in
development mode it's set to `DEBUG`.
The **default** log level is `INFO`. If you are running opencode locally in development mode it's set to `DEBUG`.
---
### Sharing
You can configure the [share](/docs/share) feature through the `share` option.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"share": "manual"
}
```
This takes:
- `"manual"` - Allow manual sharing via commands (default)
- `"auto"` - Automatically share new conversations
- `"disabled"` - Disable sharing entirely
By default, sharing is set to manual mode where you need to explicitly share conversations using the `/share` command.
---
@@ -138,6 +175,19 @@ You can customize your keybinds through the `keybinds` option.
---
### Autoupdate
opencode will automatically download any new updates when it starts up. You can disable this with the `autoupdate` option.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"autoupdate": false
}
```
---
### MCP servers
You can configure MCP servers you want to use through the `mcp` option.
@@ -153,6 +203,22 @@ You can configure MCP servers you want to use through the `mcp` option.
---
### Instructions
You can configure the instructions for the model you're using through the `instructions` option.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"]
}
```
This takes an array of paths and glob patterns to instruction files. [Learn more
about rules here](/docs/rules).
---
### Disabled providers
You can disable providers that are loaded automatically through the `disabled_providers` option. This is useful when you want to prevent certain providers from being loaded even if their credentials are available.
@@ -190,7 +256,7 @@ Use `{env:VARIABLE_NAME}` to substitute environment variables:
"anthropic": {
"options": {
"apiKey": "{env:ANTHROPIC_API_KEY}"
}
}
}
}
}
@@ -23,7 +23,7 @@ Since opencode is open source and does not store any of your code or context dat
**opencode does not store your code or context data.** All processing happens locally or through direct API calls to your AI provider.
The only caveat here is the optional `/share` feature that must be manually enabled.
The only caveat here is the optional `/share` feature.
---
@@ -33,6 +33,17 @@ If a user enables the `/share` feature, the conversation and the data associated
The data is currently served through our CDN's edge network, and is cached on the edge near your users.
We recommend you disable this for your trial.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"share": "disabled"
}
```
[Learn more about sharing](/docs/share).
---
### Code ownership
@@ -51,9 +62,37 @@ pricing and implementation options.
### SSO
SSO integration can be implemented for enterprise deployments after your trial. Currently users manage and configure individual API keys locally.
SSO integration can be implemented for enterprise deployments after your trial.
This will allow your team's session data and shared conversations to be protected
by your enterprise's authentication system.
This can be switched to a centralized authentication system that your organization uses.
---
### Private NPM
opencode supports private npm registries through Bun's native `.npmrc` file support. If your organization uses a private registry, such as JFrog Artifactory, Nexus, or similar, ensure developers are authenticated before running opencode.
To set up authentication with your private registry:
```bash
npm login --registry=https://your-company.jfrog.io/api/npm/npm-virtual/
```
This creates `~/.npmrc` with authentication details. opencode will automatically
pick this up.
:::caution
You must be logged into the private registry before running opencode.
:::
Alternatively, you can manually configure a `.npmrc` file:
```bash title="~/.npmrc"
registry=https://your-company.jfrog.io/api/npm/npm-virtual/
//your-company.jfrog.io/api/npm/npm-virtual/:_authToken=${NPM_AUTH_TOKEN}
```
Developers must be logged into the private registry before running opencode to ensure packages can be installed from your enterprise registry.
---
@@ -61,30 +100,3 @@ This can be switched to a centralized authentication system that your organizati
The share feature can be self-hosted and the share pages can be made accessible
only after the user has been authenticated.
---
### Private NPM registries
opencode supports private npm registries through Bun's native `.npmrc` file support. If your organization uses a private registry (such as JFrog Artifactory, Nexus, or similar), ensure developers are authenticated before running opencode.
To set up authentication with your private registry:
```bash
# Authenticate with your enterprise registry
npm login --registry=https://your-company.jfrog.io/api/npm/npm-virtual/
# This creates ~/.npmrc with authentication
# opencode will automatically use it through Bun's native support
```
Alternatively, you can manually configure a `.npmrc` file:
```bash
# ~/.npmrc
registry=https://your-company.jfrog.io/api/npm/npm-virtual/
//your-company.jfrog.io/api/npm/npm-virtual/:_authToken=${NPM_AUTH_TOKEN}
```
**Important**: Developers must be logged into the private registry before running opencode
to ensure packages can be installed from your enterprise registry.
@@ -9,32 +9,45 @@ opencode has a list of keybinds that you can customize through the opencode conf
{
"$schema": "https://opencode.ai/config.json",
"keybinds": {
"leader": "ctrl+x",
"help": "<leader>h",
"app_help": "<leader>h",
"switch_mode": "tab",
"editor_open": "<leader>e",
"session_new": "<leader>n",
"session_list": "<leader>l",
"session_share": "<leader>s",
"session_unshare": "<leader>u",
"session_interrupt": "esc",
"session_compact": "<leader>c",
"tool_details": "<leader>d",
"model_list": "<leader>m",
"theme_list": "<leader>t",
"project_init": "<leader>i",
"file_list": "<leader>f",
"file_close": "esc",
"file_diff_toggle": "<leader>v",
"input_clear": "ctrl+c",
"input_paste": "ctrl+v",
"input_submit": "enter",
"input_newline": "shift+enter,ctrl+j",
"history_previous": "up",
"history_next": "down",
"messages_page_up": "pgup",
"messages_page_down": "pgdown",
"messages_half_page_up": "ctrl+alt+u",
"messages_half_page_down": "ctrl+alt+d",
"messages_previous": "ctrl+alt+k",
"messages_next": "ctrl+alt+j",
"messages_previous": "ctrl+up",
"messages_next": "ctrl+down",
"messages_first": "ctrl+g",
"messages_last": "ctrl+alt+g",
"messages_layout_toggle": "<leader>p",
"messages_copy": "<leader>y",
"messages_revert": "<leader>r",
"app_exit": "ctrl+c,<leader>q"
}
}
@@ -49,7 +49,10 @@ Add a remote MCP servers under `mcp.remotemcp`.
"remotemcp": {
"type": "remote",
"url": "https://my-mcp-server.com",
"enabled": true
"enabled": true,
"headers": {
"Authorization": "Bearer MY_API_KEY"
}
}
}
}
@@ -46,14 +46,14 @@ You can add custom providers by specifying the npm package for the provider and
You can customize the base URL for any provider by setting the `baseURL` option. This is useful when using proxy services or custom endpoints.
```json title="opencode.json" {6-7}
```json title="opencode.json" {6}
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"anthropic": {
"options": {
"baseURL": "https://api.anthropic.com/v1"
},
}
}
}
}
+42 -17
View File
@@ -23,13 +23,13 @@ When you share a conversation, opencode:
## Sharing
You can manually share a conversation or enable automatic sharing for all new conversations.
opencode supports three sharing modes that control how conversations are shared:
---
### Manual
### Manual (default)
Use the `/share` command in any conversation to create a shareable link:
By default, opencode uses manual sharing mode. Sessions are not shared automatically, but you can manually share them using the `/share` command:
```
/share
@@ -37,24 +37,48 @@ Use the `/share` command in any conversation to create a shareable link:
This will generate a unique URL that'll be copied to your clipboard.
---
### Autoshare
You can enable automatic sharing for all new conversations through the `autoshare` option in your [config file](/docs/config).
To explicitly set manual mode in your [config file](/docs/config):
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"autoshare": true
"share": "manual"
}
```
By default, `autoshare` is disabled.
---
### Auto-share
You can enable automatic sharing for all new conversations by setting the `share` option to `"auto"` in your [config file](/docs/config):
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"share": "auto"
}
```
With auto-share enabled, every new conversation will automatically be shared and a link will be generated.
---
## Unsharing
### Disabled
You can disable sharing entirely by setting the `share` option to `"disabled"` in your [config file](/docs/config):
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"share": "disabled"
}
```
To enforce this across your team for a given project, add it to the `opencode.json` in your project and check into Git.
---
## Un-sharing
To stop sharing a conversation and remove it from public access:
@@ -85,10 +109,11 @@ includes:
### Recommendations
- Only share conversations that don't contain sensitive information
- Review conversation content before sharing
- Unshare conversations when collaboration is complete
- Avoid sharing conversations with proprietary code or confidential data
- Only share conversations that don't contain sensitive information.
- Review conversation content before sharing.
- Unshare conversations when collaboration is complete.
- Avoid sharing conversations with proprietary code or confidential data.
- For sensitive projects, disable sharing entirely.
---
@@ -96,8 +121,8 @@ includes:
For enterprise deployments, the share feature can be:
- **Self-hosted** on your own infrastructure
- **Restricted** to authenticated users only
- **Disabled** entirely for security compliance
- **Restricted** to users authenticated through SSO only
- **Self-hosted** on your own infrastructure
[Learn more](/docs/enterprise) about using opencode in your organization.
@@ -134,13 +134,10 @@ We're working on adding click & drag text selection in a future update.
By default, opencode's TUI uses an "auto" layout that centers content with padding. If you want the TUI to use the full width of your terminal, you can configure the layout setting:
```json
```json title="opencode.json"
{
"layout": "stretch"
}
```
Add this to your `opencode.json` configuration file. The available layout options are:
- `"auto"` (default) - Centers content with padding
- `"stretch"` - Uses full terminal width
Read more about this in the [config docs](/docs/config#layout).