Skip to content

Commit aa93c58

Browse files
dashboard: use 'opencode --pure models' for model discovery
The config-page model dropdowns populate by running 'opencode models' (and a login-shell fallback) in short-lived subprocesses. A plain 'opencode models' boots the full OpenCode runtime and loads every configured external plugin. The AFT plugin in particular spawns a native indexer daemon on load; when this discovery process exits (or is killed by the 8s timeout), that daemon detaches, reparents to launchd, and pegs 50-65% CPU. Every dashboard open spawned another. '--pure' is a global OpenCode option (placed before the subcommand) that zeroes external plugin origins, so no external plugin loads and nothing like AFT's daemon is spawned, while built-in provider-auth plugins still load so the printed provider/model list is unchanged. Applied to all three opencode discovery sites (candidate binaries, Windows where.exe fallback, login-shell fallback). The Pi path (pi --list-models) is unaffected. Co-authored-by: Alfonso [Magic Context] <288211368+alfonso-magic-context@users.noreply.github.com>
1 parent 8e086aa commit aa93c58

1 file changed

Lines changed: 10 additions & 3 deletions

File tree

packages/dashboard/src-tauri/src/commands.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -703,8 +703,15 @@ pub async fn get_available_models() -> Vec<String> {
703703
.collect()
704704
};
705705

706+
// `--pure` (global option, before the subcommand) lists models WITHOUT
707+
// loading external plugins. A plain `opencode models` boots the full
708+
// runtime and loads every configured plugin; the AFT plugin in particular
709+
// spawns a native indexer daemon that then orphans and pegs CPU after this
710+
// short-lived discovery process exits. `--pure` keeps built-in provider
711+
// auth (so the model list is still correct) while skipping external plugin
712+
// side effects entirely.
706713
for bin in &candidates {
707-
if let Some(text) = run_bounded_binary(bin, &["models"]).await {
714+
if let Some(text) = run_bounded_binary(bin, &["--pure", "models"]).await {
708715
let models = parse(&text);
709716
if !models.is_empty() {
710717
return models;
@@ -714,7 +721,7 @@ pub async fn get_available_models() -> Vec<String> {
714721

715722
if cfg!(target_os = "windows") {
716723
if let Some(bin) = resolve_via_where("opencode").await {
717-
if let Some(text) = run_bounded_binary(&bin, &["models"]).await {
724+
if let Some(text) = run_bounded_binary(&bin, &["--pure", "models"]).await {
718725
let models = parse(&text);
719726
if !models.is_empty() {
720727
return models;
@@ -725,7 +732,7 @@ pub async fn get_available_models() -> Vec<String> {
725732

726733
// Login-shell fallback for version-manager (mise/nvm/fnm) installs the
727734
// hardcoded candidates can't enumerate — see run_via_login_shell.
728-
if let Some(text) = run_via_login_shell("opencode models".to_string()).await {
735+
if let Some(text) = run_via_login_shell("opencode --pure models".to_string()).await {
729736
return parse(&text);
730737
}
731738

0 commit comments

Comments
 (0)