refactor(cli): make yolo canonical

This commit is contained in:
opencode-agent[bot] 2026-06-21 00:59:17 +00:00
commit c8da01ba38
10 changed files with 35 additions and 21 deletions

View file

@ -228,8 +228,8 @@ export const RunCommand = effectCmd({
describe: "run in direct interactive split-footer mode", describe: "run in direct interactive split-footer mode",
default: false, default: false,
}) })
.option("dangerously-skip-permissions", { .option("yolo", {
alias: ["yolo"], alias: ["dangerously-skip-permissions"],
type: "boolean", type: "boolean",
describe: "auto-approve permissions that are not explicitly denied (dangerous!)", describe: "auto-approve permissions that are not explicitly denied (dangerous!)",
default: false, default: false,
@ -733,7 +733,7 @@ export const RunCommand = effectCmd({
const permission = event.properties const permission = event.properties
if (permission.sessionID !== sessionID) continue if (permission.sessionID !== sessionID) continue
if (args["dangerously-skip-permissions"]) { if (args.yolo) {
await client.permission.reply({ await client.permission.reply({
requestID: permission.id, requestID: permission.id,
reply: "once", reply: "once",

View file

@ -104,8 +104,8 @@ export const TuiThreadCommand = cmd({
type: "string", type: "string",
describe: "agent to use", describe: "agent to use",
}) })
.option("dangerously-skip-permissions", { .option("yolo", {
alias: ["yolo"], alias: ["dangerously-skip-permissions"],
type: "boolean", type: "boolean",
describe: "auto-approve permissions that are not explicitly denied (dangerous!)", describe: "auto-approve permissions that are not explicitly denied (dangerous!)",
default: false, default: false,

View file

@ -15,7 +15,10 @@ const enabledByExperimental = (name: string) =>
export class Service extends ConfigService.Service<Service>()("@opencode/RuntimeFlags", { export class Service extends ConfigService.Service<Service>()("@opencode/RuntimeFlags", {
autoShare: bool("OPENCODE_AUTO_SHARE"), autoShare: bool("OPENCODE_AUTO_SHARE"),
dangerouslySkipPermissions: bool("OPENCODE_DANGEROUSLY_SKIP_PERMISSIONS"), yolo: Config.all({
primary: bool("OPENCODE_YOLO"),
legacy: bool("OPENCODE_DANGEROUSLY_SKIP_PERMISSIONS"),
}).pipe(Config.map((flags) => flags.primary || flags.legacy)),
pure: bool("OPENCODE_PURE"), pure: bool("OPENCODE_PURE"),
disableDefaultPlugins: bool("OPENCODE_DISABLE_DEFAULT_PLUGINS"), disableDefaultPlugins: bool("OPENCODE_DISABLE_DEFAULT_PLUGINS"),
disableEmbeddedWebUi: bool("OPENCODE_DISABLE_EMBEDDED_WEB_UI"), disableEmbeddedWebUi: bool("OPENCODE_DISABLE_EMBEDDED_WEB_UI"),

View file

@ -66,7 +66,7 @@ const cli = yargs(args)
.middleware(async (opts) => { .middleware(async (opts) => {
if (opts.printLogs) process.env.OPENCODE_PRINT_LOGS = "1" if (opts.printLogs) process.env.OPENCODE_PRINT_LOGS = "1"
if (opts.logLevel) process.env.OPENCODE_LOG_LEVEL = opts.logLevel if (opts.logLevel) process.env.OPENCODE_LOG_LEVEL = opts.logLevel
if (opts.dangerouslySkipPermissions) process.env.OPENCODE_DANGEROUSLY_SKIP_PERMISSIONS = "1" if (opts.yolo) process.env.OPENCODE_YOLO = "1"
if (opts.pure) { if (opts.pure) {
process.env.OPENCODE_PURE = "1" process.env.OPENCODE_PURE = "1"
} }

View file

@ -91,7 +91,7 @@ export const layer = Layer.effect(
}) })
} }
if (rule.action === "allow") continue if (rule.action === "allow") continue
if (flags.dangerouslySkipPermissions) continue if (flags.yolo) continue
needsAsk = true needsAsk = true
} }

View file

@ -111,7 +111,7 @@ Options:
messages [number] messages [number]
-i, --interactive run in direct interactive split-footer mode -i, --interactive run in direct interactive split-footer mode
[boolean] [default: false] [boolean] [default: false]
--dangerously-skip-permissions, --yolo auto-approve permissions that are not explicitly --yolo, --dangerously-skip-permissions auto-approve permissions that are not explicitly
denied (dangerous!) [boolean] [default: false] denied (dangerous!) [boolean] [default: false]
--demo enable direct interactive demo slash commands; pass --demo enable direct interactive demo slash commands; pass
one as the message to run it immediately one as the message to run it immediately

View file

@ -102,8 +102,8 @@ describe("opencode CLI help-text snapshots", () => {
const topLevel = yield* opencode.spawn(["--help"], { env: SNAPSHOT_ENV }) const topLevel = yield* opencode.spawn(["--help"], { env: SNAPSHOT_ENV })
expect(topLevel.exitCode).toBe(0) expect(topLevel.exitCode).toBe(0)
expect(topLevel.stderr.endsWith(EOL)).toBe(true) expect(topLevel.stderr.endsWith(EOL)).toBe(true)
expect(topLevel.stderr).toContain("--dangerously-skip-permissions")
expect(topLevel.stderr).toContain("--yolo") expect(topLevel.stderr).toContain("--yolo")
expect(topLevel.stderr).toContain("--dangerously-skip-permissions")
const argvs: Array<readonly string[]> = [...TOP_LEVEL.map((c) => [c] as const), ...SUBCOMMANDS] const argvs: Array<readonly string[]> = [...TOP_LEVEL.map((c) => [c] as const), ...SUBCOMMANDS]

View file

@ -14,7 +14,7 @@ describe("RuntimeFlags", () => {
const flags = yield* readFlags.pipe(Effect.provide(fromConfig({}))) const flags = yield* readFlags.pipe(Effect.provide(fromConfig({})))
expect(flags.autoShare).toBe(false) expect(flags.autoShare).toBe(false)
expect(flags.dangerouslySkipPermissions).toBe(false) expect(flags.yolo).toBe(false)
}), }),
) )
@ -24,7 +24,7 @@ describe("RuntimeFlags", () => {
Effect.provide( Effect.provide(
fromConfig({ fromConfig({
OPENCODE_PURE: "true", OPENCODE_PURE: "true",
OPENCODE_DANGEROUSLY_SKIP_PERMISSIONS: "true", OPENCODE_YOLO: "true",
OPENCODE_DISABLE_DEFAULT_PLUGINS: "true", OPENCODE_DISABLE_DEFAULT_PLUGINS: "true",
OPENCODE_AUTO_SHARE: "true", OPENCODE_AUTO_SHARE: "true",
OPENCODE_DISABLE_EMBEDDED_WEB_UI: "true", OPENCODE_DISABLE_EMBEDDED_WEB_UI: "true",
@ -41,7 +41,7 @@ describe("RuntimeFlags", () => {
) )
expect(flags.pure).toBe(true) expect(flags.pure).toBe(true)
expect(flags.dangerouslySkipPermissions).toBe(true) expect(flags.yolo).toBe(true)
expect(flags.autoShare).toBe(true) expect(flags.autoShare).toBe(true)
expect(flags.disableDefaultPlugins).toBe(true) expect(flags.disableDefaultPlugins).toBe(true)
expect(flags.disableEmbeddedWebUi).toBe(true) expect(flags.disableEmbeddedWebUi).toBe(true)
@ -81,6 +81,14 @@ describe("RuntimeFlags", () => {
}), }),
) )
it.effect("supports the legacy dangerous permission environment variable", () =>
Effect.gen(function* () {
const flags = yield* readFlags.pipe(Effect.provide(fromConfig({ OPENCODE_DANGEROUSLY_SKIP_PERMISSIONS: "true" })))
expect(flags.yolo).toBe(true)
}),
)
it.effect("enables native LLM via dedicated flag only", () => it.effect("enables native LLM via dedicated flag only", () =>
Effect.gen(function* () { Effect.gen(function* () {
const explicit = yield* readFlags.pipe(Effect.provide(fromConfig({ OPENCODE_EXPERIMENTAL_NATIVE_LLM: "true" }))) const explicit = yield* readFlags.pipe(Effect.provide(fromConfig({ OPENCODE_EXPERIMENTAL_NATIVE_LLM: "true" })))

View file

@ -25,7 +25,7 @@ const makeEnv = (flags: Partial<RuntimeFlags.Info> = {}) => {
) )
} }
const it = testEffect(makeEnv()) const it = testEffect(makeEnv())
const dangerousIt = testEffect(makeEnv({ dangerouslySkipPermissions: true })) const yoloIt = testEffect(makeEnv({ yolo: true }))
const rejectAll = (message?: string) => const rejectAll = (message?: string) =>
Effect.gen(function* () { Effect.gen(function* () {
@ -618,8 +618,8 @@ it.instance(
{ git: true }, { git: true },
) )
dangerousIt.instance( yoloIt.instance(
"ask - resolves ask rules when dangerous permission skipping is enabled", "ask - resolves ask rules when yolo mode is enabled",
() => () =>
ask({ ask({
sessionID: SessionID.make("session_test"), sessionID: SessionID.make("session_test"),
@ -632,8 +632,8 @@ dangerousIt.instance(
{ git: true }, { git: true },
) )
dangerousIt.instance( yoloIt.instance(
"ask - preserves deny rules when dangerous permission skipping is enabled", "ask - preserves deny rules when yolo mode is enabled",
() => () =>
Effect.gen(function* () { Effect.gen(function* () {
const err = yield* fail( const err = yield* fail(

View file

@ -42,7 +42,8 @@ opencode [project]
| <nobr><code>{"--mdns"}</code></nobr> | | Enable mDNS discovery | | <nobr><code>{"--mdns"}</code></nobr> | | Enable mDNS discovery |
| <nobr><code>{"--mdns-domain"}</code></nobr> | | Custom mDNS domain name | | <nobr><code>{"--mdns-domain"}</code></nobr> | | Custom mDNS domain name |
| <nobr><code>{"--cors"}</code></nobr> | | Additional browser origin(s) to allow CORS | | <nobr><code>{"--cors"}</code></nobr> | | Additional browser origin(s) to allow CORS |
| <nobr><code>{"--dangerously-skip-permissions"}</code></nobr> | | Auto-approve permissions not explicitly denied. Alias: `--yolo` | | <nobr><code>{"--yolo"}</code></nobr> | | Auto-approve permissions not explicitly denied |
| <nobr><code>{"--dangerously-skip-permissions"}</code></nobr> | | Legacy alias for `--yolo` |
--- ---
@ -381,7 +382,8 @@ opencode run --attach http://localhost:4096 "Explain async/await in JavaScript"
| <nobr><code>{"--port"}</code></nobr> | | Port for the local server (defaults to random port) | | <nobr><code>{"--port"}</code></nobr> | | Port for the local server (defaults to random port) |
| <nobr><code>{"--variant"}</code></nobr> | | Model variant (provider-specific reasoning effort) | | <nobr><code>{"--variant"}</code></nobr> | | Model variant (provider-specific reasoning effort) |
| <nobr><code>{"--thinking"}</code></nobr> | | Show thinking blocks | | <nobr><code>{"--thinking"}</code></nobr> | | Show thinking blocks |
| <nobr><code>{"--dangerously-skip-permissions"}</code></nobr> | | Auto-approve permissions that are not explicitly denied. Alias: `--yolo` | | <nobr><code>{"--yolo"}</code></nobr> | | Auto-approve permissions that are not explicitly denied |
| <nobr><code>{"--dangerously-skip-permissions"}</code></nobr> | | Legacy alias for `--yolo` |
--- ---
@ -689,7 +691,8 @@ OpenCode can be configured using environment variables.
| `OPENCODE_DISABLE_PRUNE` | boolean | Disable pruning of old data | | `OPENCODE_DISABLE_PRUNE` | boolean | Disable pruning of old data |
| `OPENCODE_DISABLE_TERMINAL_TITLE` | boolean | Disable automatic terminal title updates | | `OPENCODE_DISABLE_TERMINAL_TITLE` | boolean | Disable automatic terminal title updates |
| `OPENCODE_PERMISSION` | string | Inlined json permissions config | | `OPENCODE_PERMISSION` | string | Inlined json permissions config |
| `OPENCODE_DANGEROUSLY_SKIP_PERMISSIONS` | boolean | Auto-approve permissions not explicitly denied | | `OPENCODE_YOLO` | boolean | Auto-approve permissions not explicitly denied |
| `OPENCODE_DANGEROUSLY_SKIP_PERMISSIONS` | boolean | Legacy alias for `OPENCODE_YOLO` |
| `OPENCODE_DISABLE_DEFAULT_PLUGINS` | boolean | Disable default plugins | | `OPENCODE_DISABLE_DEFAULT_PLUGINS` | boolean | Disable default plugins |
| `OPENCODE_DISABLE_LSP_DOWNLOAD` | boolean | Disable automatic LSP server downloads | | `OPENCODE_DISABLE_LSP_DOWNLOAD` | boolean | Disable automatic LSP server downloads |
| `OPENCODE_ENABLE_EXPERIMENTAL_MODELS` | boolean | Enable experimental models | | `OPENCODE_ENABLE_EXPERIMENTAL_MODELS` | boolean | Enable experimental models |