Skip to content

feat: ask which tool to use on first run - #91

Merged
xai merged 2 commits into
mainfrom
feat/tool-prompt
Sep 18, 2026
Merged

xai merged 2 commits into
mainfrom
feat/tool-prompt

Conversation

@xai

@xai xai commented Sep 17, 2026 •

Copy link
Copy Markdown
Collaborator

What it does

Closes #89.

The tool default is no longer claude. It is unset (auto), and the first
command that starts a session or builds its image asks once which agent to run,
then saves the answer as "tool" in the global config — the same shape #74 gave
backend.

  • Asked only for run, shell, continue, resume, exec, and a bare
    update. An update with explicit tool arguments rebuilds exactly those
    images and never reads the default tool, so it does not ask.
  • Never asked under --json, --yes, or when stdin/stdout/stderr are not all
    terminals, and never by the other verbs (ps, status, stop, cleanup,
    tools, features, config, review-target, …). Those keep using claude,
    so scripts and CI are unaffected. An unanswered question does the same for
    that run and saves nothing.
  • The menu lists every installed agent. The IDE profiles (theia,
    theia-next) are never offered; they attach a host IDE rather than running an
    agent in the terminal. --tool theia still selects them.
  • A host with exactly one installed agent has nothing to choose between, so it
    is never asked — and the non-interactive path uses that agent too, rather than
    a claude that may not be installed there. An empty inventory falls back to
    claude.
  • --tool and a configured tool skip the question entirely. "tool": "auto"
    asks again.

How to test

A scratch HOME keeps your real config and stores untouched. From the repo
root, after make build:

scratch=$(mktemp -d); app="$PWD"; bin="$PWD/bin/enclave"
run() { env -u XDG_CONFIG_HOME -u XDG_STATE_HOME -u XDG_CACHE_HOME \
  HOME="$scratch" ENCLAVE_HOME="$app" "$bin" "$@"; }
cd /some/project
  1. It asks once and remembers. run in a terminal. The question lists
    claude/codex/mistral-vibe/opencode/pi — no theia entries — and names the
    config file the answer goes to. Answer codex. The run then proceeds
    normally (from an empty scratch state that means an image build; Ctrl-C is
    fine, the answer is already saved).
    cat $scratch/.config/enclave/config.json shows {"tool": "codex"}. Run
    run again: no question.
  2. auto asks again. Write {"tool": "auto"} to
    $scratch/.config/enclave/config.json and run in a terminal: the question
    is back. The same config resolves to claude without asking when it cannot
    ask — run config --json reports tool effective as claude.
  3. Scripts are unaffected. rm $scratch/.config/enclave/config.json, then
    run < /dev/null, run ps --json, run tools, run config. None asks,
    none writes config.json, and run config shows tool effective as
    claude.
  4. Explicit update targets do not ask. Still without a config:
    run update codex goes straight to the codex rebuild, and
    $scratch/.config/enclave/ gains no config.json. A bare run update does
    ask and saves.
  5. Overrides still win. With {"tool": "codex"} saved, run --tool pi
    uses pi for that run and leaves the saved key at codex.
  6. Nothing changed for you. Run enclave normally, without the scratch
    HOME: an existing tool in your own config is used and no question
    appears. Clean up with rm -rf "$scratch".

Follow-ups

enclave tools marks claude as (selected) while the tool is unset, because
engine-free verbs resolve to the fallback. That is what a non-interactive run
would use, but it no longer tells the whole story; printing no marker in that
state would need the unresolved value threaded through to the listing.

Breaking changes

  • This PR introduces breaking changes and has been coordinated with maintainers.

On its first invocation without an explicit --tool <name>, enclave now prompts
instead of implicitly starting claude.

Review checklist

@xai xai added the enhancement New feature or request label Sep 17, 2026
@github-actions

github-actions Bot commented Sep 17, 2026 •

Copy link
Copy Markdown
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-09-18 10:54 UTC

@xai
xai marked this pull request as ready for review September 17, 2026 16:23

@EclipseSourceAI EclipseSourceAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

Autonomous AI review.

This review was done by an AI agent and therefore may contain mistakes. Feel free to ignore any comment you disagree with. A thumbs-down reaction on a comment marks it as rejected for follow-up reviews. Noting why in a reply helps, since replies are read too.

Resolving all AI comments does not lead to an automatic approval. A maintainer still needs to review and sign off on the overall architecture and design.

To get an updated review after pushing changes, a maintainer may re-request a review from this account.

Running in Eclipse Enclave, submitted via review-guard-mcp

What this PR does

The tool default moves from claude to an unset auto, and app.Run resolves it once (resolveTool) before anything reads the tool name, re-layering options with config.ResolveOptionsForTool when the answer differs. Only the session-starting verbs (run, shell, continue, resume, exec, and a bare update) may ask; everything else, plus non-terminal/--json/--yes invocations, keeps claude. The answer is written to the global config with the same WriteGlobalDefault seam #74 used for backend, and the backend prompt helpers are renamed to shared names (promptUsable, promptAllowed). Docs are updated consistently across README, docs/, and the website.

The wiring is clean and fits the existing option-resolution flow well, the seam/test structure mirrors backend.go, and go test ./... passes here.

Where to focus

The interesting part is toolHasCredentials and the menu narrowing, which is where most of the new code sits:

  • Narrowing to credentialed tools hides installed agents that prompt.Choose then refuses to accept, and the dead end falls back to claude. A single exported ANTHROPIC_API_KEY is enough to trigger it.
  • The "signed in on the host" signal does not actually mean the session can authenticate: host auth files are deliberately blocked from passthrough and only reach the store via enclave auth import.
  • The auth-store check treats any existing auth.json as a session, which is weaker than the authSession checks opencode and pi declare.

Whether the credential probing is worth its complexity at all (versus offering every installed agent) is a maintainer call. Smaller items are in the inline comments.

Comment thread internal/app/tool.go Outdated
Comment thread internal/app/tool.go Outdated
Comment thread internal/app/tool.go Outdated
Comment thread internal/app/tool.go Outdated
Comment thread internal/app/tool.go Outdated
Comment thread internal/app/tool_test.go Outdated
Comment thread internal/app/tool_test.go Outdated
Comment thread website/docs/docs/getting-started.md

@EclipseSourceAI EclipseSourceAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

Autonomous AI review.

This review was done by an AI agent and therefore may contain mistakes. Feel free to ignore any comment you disagree with. A thumbs-down reaction on a comment marks it as rejected for follow-up reviews. Noting why in a reply helps, since replies are read too.

Resolving all AI comments does not lead to an automatic approval. A maintainer still needs to review and sign off on the overall architecture and design.

To get an updated review after pushing changes, a maintainer may re-request a review from this account.

Running in Eclipse Enclave, submitted via review-guard-mcp

Follow-up review. Since my last pass, the credential-probing subsystem (toolCandidate, promptableTools, toolHasCredentials, authStoreHasSession, hostAuthFilesExist, fileExists) was removed entirely and replaced with a much simpler model: the menu just offers every installed agent, and a host with exactly one installed agent uses it without asking on both the interactive and non-interactive paths (toolWithoutAsking). Tests and docs were updated to match. go build ./... and go test ./internal/app/... pass, gofmt is clean.

This resolves every open thread from my earlier review, all of them for the reasons above. No new issues found in the changes since then.

These previous comments can be resolved as they are now handled:

I can't resolve them myself as I would need write permission on this repository.

The tool default is no longer claude. It is unset (auto), and the first
command that starts a session or builds its image asks once which
installed agent to run, then saves the answer as "tool" in the global
config -- the same shape #74 gave backend.

Scripts, CI, --json, --yes and every other verb keep using claude
without asking, so nothing outside an interactive first run changes.
A host that installed exactly one agent uses that one either way.

Closes #89.
@xai

xai commented Sep 17, 2026

Copy link
Copy Markdown
Collaborator Author

@EclipseSourceAI

@EclipseSourceAI EclipseSourceAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

Autonomous AI review.

This review was done by an AI agent and therefore may contain mistakes. Feel free to ignore any comment you disagree with. A thumbs-down reaction on a comment marks it as rejected for follow-up reviews. Noting why in a reply helps, since replies are read too.

Resolving all AI comments does not lead to an automatic approval. A maintainer still needs to review and sign off on the overall architecture and design.

To get an updated review after pushing changes, a maintainer may re-request a review from this account.

Running in Eclipse Enclave, submitted via review-guard-mcp

Second follow-up. Since my last review (95ebcc3), the only changes are: docs (README, website/docs/configuration.md) updated to spell out that non-interactive runs fall back to the sole installed agent when there's exactly one, and two template-y comments removed from tool_test.go above the test funcs. Both match the current toolWithoutAsking behavior and the second-review state, no functional changes.

All threads from my previous reviews were already resolved before this pass, nothing new to raise.

@tortmayr tortmayr left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general code looks good to me and the change seems to work as expected.
I have one inline comment/question regarding the documented behavior.

Comment thread docs/cli-reference.md Outdated
A command that needs a tool asks once in a terminal; otherwise it fails
naming --tool and the "tool" key. Verbs that never read the default tool
leave it unresolved. The single-installed-agent shortcut is gone: built-in
tool extensions cannot be removed, so it was unreachable in practice.
@xai

xai commented Sep 17, 2026

Copy link
Copy Markdown
Collaborator Author

@EclipseSourceAI

@EclipseSourceAI EclipseSourceAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

Autonomous AI review.

This review was done by an AI agent and therefore may contain mistakes. Feel free to ignore any comment you disagree with. A thumbs-down reaction on a comment marks it as rejected for follow-up reviews. Noting why in a reply helps, since replies are read too.

Resolving all AI comments does not lead to an automatic approval. A maintainer still needs to review and sign off on the overall architecture and design.

To get an updated review after pushing changes, a maintainer may re-request a review from this account.

Running in Eclipse Enclave, submitted via review-guard-mcp

Third follow-up review. Since my last pass (af63932), one commit landed (3c4d5ee), and it's a direct response to tortmayr's inline feedback on this PR: an unresolved tool now fails naming --tool and the tool key instead of silently falling back to claude, actions that never read the tool (ps, status, tools, config, attach, …) no longer resolve it at all via the new actionNeedsTool/toolFreeActions split in internal/app/actions.go, and the unreachable single-installed-agent shortcut is gone.

I checked actionNeedsTool against every CLI action string in the codebase (network-status/print/diff/apply/add-domain/remove-domain/set-mode, auth-import/export, devcontainer-generate, img-import, info, user-command, …) and each one's tool-need matches whether its handler actually reads opts.Tool for image/store keys. go build ./..., go test ./internal/app/..., and gofmt are all clean. No new issues found.

All threads from my earlier reviews were already reported resolved in my previous pass.

@xai
xai requested a review from tortmayr September 17, 2026 23:04

@tortmayr tortmayr left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! 👍🏼

@xai
xai merged commit 15a15b5 into main Sep 18, 2026
10 checks passed
@xai
xai deleted the feat/tool-prompt branch September 18, 2026 10:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ask which tool to use on first run instead of defaulting to Claude

3 participants