From dfbd329c855ff5207a8ab3030fb8419a57a5e21b Mon Sep 17 00:00:00 2001 From: toavina Date: Wed, 11 Mar 2026 12:35:05 +0300 Subject: [PATCH] feat: add --profile global CLI flag for startup profile selection Adds `--profile ` as a global yargs option that sets the active profile before the app bootstraps. The middleware validates the profile name format and existence, then each command handler (TUI, run) re-applies the profile to its resolved project directory. Enables usage like: `vuhitracode --profile default --agent alice`. --- packages/opencode/src/cli/cmd/run.ts | 5 +++++ packages/opencode/src/cli/cmd/tui/thread.ts | 5 +++++ packages/opencode/src/index.ts | 20 ++++++++++++++++++++ packages/web/src/content/docs/cli.mdx | 11 ++++++++++- packages/web/src/content/docs/profiles.mdx | 12 ++++++++++++ 5 files changed, 52 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/cli/cmd/run.ts b/packages/opencode/src/cli/cmd/run.ts index 53be9ee9e..60c3f57d7 100644 --- a/packages/opencode/src/cli/cmd/run.ts +++ b/packages/opencode/src/cli/cmd/run.ts @@ -27,6 +27,7 @@ import { SkillTool } from "../../tool/skill" import { BashTool } from "../../tool/bash" import { TodoWriteTool } from "../../tool/todo" import { Locale } from "../../util/locale" +import { VuHitraSettings } from "@/project/vuhitra-settings" type ToolProps = { input: Tool.InferParameters @@ -315,6 +316,10 @@ export const RunCommand = cmd({ } })() + if (args.profile && directory && !args.attach) { + await VuHitraSettings.setActiveProfile(args.profile as string, directory) + } + const files: { type: "file"; url: string; filename: string; mime: string }[] = [] if (args.file) { const list = Array.isArray(args.file) ? args.file : [args.file] diff --git a/packages/opencode/src/cli/cmd/tui/thread.ts b/packages/opencode/src/cli/cmd/tui/thread.ts index fbedda46c..2ed8089bb 100644 --- a/packages/opencode/src/cli/cmd/tui/thread.ts +++ b/packages/opencode/src/cli/cmd/tui/thread.ts @@ -12,6 +12,7 @@ import { Filesystem } from "@/util/filesystem" import type { Event } from "@opencode-ai/sdk/v2" import type { EventSource } from "./context/sdk" import { win32DisableProcessedInput, win32InstallCtrlCGuard } from "./win32" +import { VuHitraSettings } from "@/project/vuhitra-settings" declare global { const OPENCODE_WORKER_PATH: string @@ -111,6 +112,10 @@ export const TuiThreadCommand = cmd({ return } + if (args.profile) { + await VuHitraSettings.setActiveProfile(args.profile as string, cwd) + } + const worker = new Worker(workerPath, { env: Object.fromEntries( Object.entries(process.env).filter((entry): entry is [string, string] => entry[1] !== undefined), diff --git a/packages/opencode/src/index.ts b/packages/opencode/src/index.ts index 5eeca8432..1eeaac927 100644 --- a/packages/opencode/src/index.ts +++ b/packages/opencode/src/index.ts @@ -31,6 +31,8 @@ import { DbCommand } from "./cli/cmd/db" import { SetCommand } from "./cli/cmd/set" import { InitCommand } from "./cli/cmd/init" import { IndexCommand } from "./cli/cmd/indexer" +import { Profiles } from "./project/profiles" +import { VuHitraSettings } from "./project/vuhitra-settings" import path from "path" import { Global } from "./global" import { JsonMigration } from "./storage/json-migration" @@ -65,6 +67,10 @@ const cli = yargs(hideBin(process.argv)) type: "string", choices: ["DEBUG", "INFO", "WARN", "ERROR"], }) + .option("profile", { + describe: "profile to use", + type: "string", + }) .middleware(async (opts) => { await Log.init({ print: process.argv.includes("--print-logs"), @@ -76,6 +82,20 @@ const cli = yargs(hideBin(process.argv)) })(), }) + if (opts.profile) { + const dir = process.cwd() + if (!/^[A-Za-z0-9_\-.]+$/.test(opts.profile)) { + UI.error(`Invalid profile name: ${opts.profile}`) + process.exit(1) + } + const available = await Profiles.list(dir) + if (!available.includes(opts.profile)) { + UI.error(`Profile "${opts.profile}" not found. Available profiles: ${available.join(", ") || "(none)"}`) + process.exit(1) + } + await VuHitraSettings.setActiveProfile(opts.profile, dir) + } + process.env.AGENT = "1" process.env.OPENCODE = "1" diff --git a/packages/web/src/content/docs/cli.mdx b/packages/web/src/content/docs/cli.mdx index 5def10589..e8676e3d5 100644 --- a/packages/web/src/content/docs/cli.mdx +++ b/packages/web/src/content/docs/cli.mdx @@ -37,10 +37,19 @@ opencode [project] | `--prompt` | | Prompt to use | | `--model` | `-m` | Model to use in the form of provider/model | | `--agent` | | Agent to use | +| `--profile` | | Profile to use (overrides active profile in settings for this run) | | `--port` | | Port to listen on | | `--hostname` | | Hostname to listen on | ---- +#### Examples + +```bash +# Start with a specific profile +opencode --profile fast + +# Combine profile with agent +opencode --profile quality --agent alice +``` ## Commands diff --git a/packages/web/src/content/docs/profiles.mdx b/packages/web/src/content/docs/profiles.mdx index b849dc6c9..15447295e 100644 --- a/packages/web/src/content/docs/profiles.mdx +++ b/packages/web/src/content/docs/profiles.mdx @@ -52,6 +52,18 @@ The active profile name is displayed below the input field in the TUI. --- +## Command Line + +You can also select a profile when starting OpenCode from the command line: + +```bash frame="none" +opencode --profile fast +``` + +This overrides the active profile stored in `.vuhitra/settings.json` for the duration of the run. + +--- + ## Use Cases ### Different Models for Different Tasks