Skip to content
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,22 @@ OPENCODE_INSTALL_DIR=/usr/local/bin curl -fsSL https://opencode.ai/install | bas
XDG_BIN_DIR=$HOME/.local/bin curl -fsSL https://opencode.ai/install | bash
```

#### Shell Completion

OpenCode can generate shell completion scripts with `opencode completion`.

```bash
# Bash
SHELL="$(command -v bash)" opencode completion >> ~/.bashrc
source ~/.bashrc

# Zsh
SHELL="$(command -v zsh)" opencode completion >> ~/.zshrc
source ~/.zshrc
```

On macOS, you may want to use `~/.bash_profile` or `~/.zprofile` instead.

### Agents

OpenCode includes two built-in agents you can switch between with the `Tab` key.
Expand Down
16 changes: 16 additions & 0 deletions README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,22 @@ OPENCODE_INSTALL_DIR=/usr/local/bin curl -fsSL https://opencode.ai/install | bas
XDG_BIN_DIR=$HOME/.local/bin curl -fsSL https://opencode.ai/install | bash
```

#### Shell 补全

OpenCode 支持通过 `opencode completion` 生成 shell 补全脚本。

```bash
# Bash
SHELL="$(command -v bash)" opencode completion >> ~/.bashrc
source ~/.bashrc

# Zsh
SHELL="$(command -v zsh)" opencode completion >> ~/.zshrc
source ~/.zshrc
```

在 macOS 上,你可能更想写入 `~/.bash_profile` 或 `~/.zprofile`。

### Agents

OpenCode 内置两种 Agent,可用 `Tab` 键快速切换:
Expand Down
4 changes: 4 additions & 0 deletions packages/opencode/src/cli/completion.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export function isShellCompletionInvocation(argv: readonly string[]) {
if (argv.includes("--get-yargs-completions")) return true
return argv.find((arg) => !arg.startsWith("-")) === "completion"
}
4 changes: 4 additions & 0 deletions packages/opencode/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import { PluginCommand } from "./cli/cmd/plug"
import { Heap } from "./cli/heap"
import { drizzle } from "drizzle-orm/bun-sqlite"
import { ensureProcessMetadata } from "@opencode-ai/core/util/opencode-process"
import { isShellCompletionInvocation } from "./cli/completion"

const processMetadata = ensureProcessMetadata("main")

Expand All @@ -55,6 +56,7 @@ process.on("uncaughtException", (e) => {
})

const args = hideBin(process.argv)
const shellCompletionInvocation = isShellCompletionInvocation(args)

function show(out: string) {
const text = out.trimStart()
Expand Down Expand Up @@ -88,6 +90,8 @@ const cli = yargs(args)
type: "boolean",
})
.middleware(async (opts) => {
if (shellCompletionInvocation) return

if (opts.pure) {
process.env.OPENCODE_PURE = "1"
}
Expand Down
3 changes: 2 additions & 1 deletion packages/opencode/src/provider/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Flock } from "@opencode-ai/core/util/flock"
import { Hash } from "@opencode-ai/core/util/hash"
import { AppFileSystem } from "@opencode-ai/core/filesystem"
import { withTransientReadRetry } from "@/util/effect-http-client"
import { isShellCompletionInvocation } from "@/cli/completion"

const Cost = Schema.Struct({
input: Schema.Finite,
Expand Down Expand Up @@ -181,7 +182,7 @@ export const layer: Layer.Layer<Service, never, AppFileSystem.Service | HttpClie
)
})

if (!Flag.OPENCODE_DISABLE_MODELS_FETCH && !process.argv.includes("--get-yargs-completions")) {
if (!Flag.OPENCODE_DISABLE_MODELS_FETCH && !isShellCompletionInvocation(process.argv.slice(2))) {
// Schedule.spaced runs the effect once, then waits between completions.
yield* Effect.forkScoped(refresh().pipe(Effect.repeat(Schedule.spaced("60 minutes")), Effect.ignore))
}
Expand Down
19 changes: 19 additions & 0 deletions packages/opencode/test/cli/completion.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { describe, expect, test } from "bun:test"
import { isShellCompletionInvocation } from "../../src/cli/completion"

describe("isShellCompletionInvocation", () => {
test("matches the yargs completion command", () => {
expect(isShellCompletionInvocation(["completion"])).toBe(true)
expect(isShellCompletionInvocation(["--pure", "completion"])).toBe(true)
})

test("matches yargs completion probe calls", () => {
expect(isShellCompletionInvocation(["--get-yargs-completions", "opencode"])).toBe(true)
})

test("ignores normal cli invocations", () => {
expect(isShellCompletionInvocation([])).toBe(false)
expect(isShellCompletionInvocation(["run", "fix this"])).toBe(false)
expect(isShellCompletionInvocation(["./completion"])).toBe(false)
})
})
16 changes: 16 additions & 0 deletions packages/web/src/content/docs/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,22 @@ You can also install it with the following commands:
paru -S opencode-bin # Arch Linux (Latest from AUR)
```

### Shell completion

OpenCode can generate shell completion scripts with `opencode completion`.

```bash
# Bash
SHELL="$(command -v bash)" opencode completion >> ~/.bashrc
source ~/.bashrc

# Zsh
SHELL="$(command -v zsh)" opencode completion >> ~/.zshrc
source ~/.zshrc
```

On macOS, you may want to use `~/.bash_profile` or `~/.zprofile` instead.

#### Windows

:::tip[Recommended: Use WSL]
Expand Down
16 changes: 16 additions & 0 deletions packages/web/src/content/docs/zh-cn/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,22 @@ curl -fsSL https://opencode.ai/install | bash
paru -S opencode-bin # Arch Linux (Latest from AUR)
```

### Shell 补全

OpenCode 支持通过 `opencode completion` 生成 shell 补全脚本。

```bash
# Bash
SHELL="$(command -v bash)" opencode completion >> ~/.bashrc
source ~/.bashrc

# Zsh
SHELL="$(command -v zsh)" opencode completion >> ~/.zshrc
source ~/.zshrc
```

在 macOS 上,你可能更想写入 `~/.bash_profile` 或 `~/.zprofile`。

#### Windows

:::tip[推荐:使用 WSL]
Expand Down
Loading