feat: ask which tool to use on first run - #91
Conversation
|
EclipseSourceAI
left a comment
There was a problem hiding this comment.
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.Choosethen refuses to accept, and the dead end falls back toclaude. A single exportedANTHROPIC_API_KEYis 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.jsonas a session, which is weaker than theauthSessionchecks 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.
3227ed2 to
95ebcc3
Compare
EclipseSourceAI
left a comment
There was a problem hiding this comment.
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:
- credential narrowing hid installed tools with a dead-end fallback; the whole narrowing mechanism was removed
- "signed in on the host" did not mean the session could authenticate; that check was removed
- bare
auth.jsonexistence contradicted the documented authSession checks; that check was removed - duplicate of
util.FileExists; the local copy is gone along with the code that used it - single-installed-agent case now behaves the same on interactive and scripted runs
- test no longer hardcodes the full bundled tool list, only asserts agent vs IDE membership
- test now locates the repo root with the same
filepath.Join("..", "..")convention used elsewhere in the package - getting-started.md now mentions the first-run question where it first tells users to just run
enclave
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.
95ebcc3 to
af63932
Compare
EclipseSourceAI
left a comment
There was a problem hiding this comment.
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
left a comment
There was a problem hiding this comment.
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.
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.
EclipseSourceAI
left a comment
There was a problem hiding this comment.
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.
What it does
Closes #89.
The
tooldefault is no longerclaude. It is unset (auto), and the firstcommand 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 gavebackend.run,shell,continue,resume,exec, and a bareupdate. Anupdatewith explicit tool arguments rebuilds exactly thoseimages and never reads the default tool, so it does not ask.
--json,--yes, or when stdin/stdout/stderr are not allterminals, and never by the other verbs (
ps,status,stop,cleanup,tools,features,config,review-target, …). Those keep usingclaude,so scripts and CI are unaffected. An unanswered question does the same for
that run and saves nothing.
theia,theia-next) are never offered; they attach a host IDE rather than running anagent in the terminal.
--tool theiastill selects them.is never asked — and the non-interactive path uses that agent too, rather than
a
claudethat may not be installed there. An empty inventory falls back toclaude.--tooland a configuredtoolskip the question entirely."tool": "auto"asks again.
How to test
A scratch
HOMEkeeps your real config and stores untouched. From the reporoot, after
make build:runin a terminal. The question listsclaude/codex/mistral-vibe/opencode/pi— notheiaentries — and names theconfig file the answer goes to. Answer
codex. The run then proceedsnormally (from an empty scratch state that means an image build; Ctrl-C is
fine, the answer is already saved).
cat $scratch/.config/enclave/config.jsonshows{"tool": "codex"}. Runrunagain: no question.autoasks again. Write{"tool": "auto"}to$scratch/.config/enclave/config.jsonandrunin a terminal: the questionis back. The same config resolves to
claudewithout asking when it cannotask —
run config --jsonreportstooleffective asclaude.rm $scratch/.config/enclave/config.json, thenrun < /dev/null,run ps --json,run tools,run config. None asks,none writes
config.json, andrun configshowstooleffective asclaude.run update codexgoes straight to the codex rebuild, and$scratch/.config/enclave/gains noconfig.json. A barerun updatedoesask and saves.
{"tool": "codex"}saved,run --tool piuses pi for that run and leaves the saved key at
codex.enclavenormally, without the scratchHOME: an existingtoolin your own config is used and no questionappears. Clean up with
rm -rf "$scratch".Follow-ups
enclave toolsmarksclaudeas(selected)while the tool is unset, becauseengine-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
On its first invocation without an explicit
--tool <name>, enclave now promptsinstead of implicitly starting
claude.Review checklist