Unsloth start: add local subagents for Claude Code, Codex, OpenCode and Pi - #7316
Conversation
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 904765eb5e
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c644b5de80
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d55d511487
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@codex review |
|
Codex Review: Didn't find any major issues. Breezy! Reviewed commit: ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
…s for PR unslothai#7316 - Stop surviving tool processes when the Claude child leader already exited, and fall back to terminate when a Windows taskkill reports failure - Surface Pi message_end error events as tool failures instead of success, since Pi exits 0 on model/API errors - Warn when the loaded GGUF variant cannot be verified so a silent fallback to a bare repo id does not go unnoticed - Reject --as-subagent for openclaw and hermes before connecting instead of forwarding the unknown flag to the agent binary
|
Pushed 23d3f31 with a few fixes on top of the convergence commit:
All covered by new tests: 297 focused tests pass including the bun-based Pi error test, plus ruff and compileall are clean. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 23d3f3180f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| yolo = yolo and not native_auto, | ||
| as_subagent = True, | ||
| ) | ||
| env = {"OPENCODE_CONFIG": str(config_path)} |
There was a problem hiding this comment.
Keep the subagent credential out of OpenCode's tool environment
When unsloth start opencode --as-subagent is used with a cloud parent model, _launch merges this OPENCODE_CONFIG value into the parent OpenCode process environment, and every Bash/tool subprocess inherits it. That path names a session file containing options.apiKey (written by write_opencode_config), so the cloud parent can run cat "$OPENCODE_CONFIG" and exfiltrate the local/remote Unsloth key before delegating anything. Use an extension/private credential mechanism or otherwise avoid exposing a key-bearing config path to the parent tool environment.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
The @unsloth subagent runs inside the parent OpenCode process, which must itself authenticate to Studio, and every OpenCode credential mechanism (config apiKey, env or file interpolation, plaintext auth.json) is readable by its same-privilege bash tools, so no placement can hide the key. The Claude and Pi fixes work because those keys live in separate child processes. The key is a loopback session credential with the same exposure as normal mode.
| _subdict(config, "agent")[_SUBAGENT_NAME] = { | ||
| "description": _SUBAGENT_DESCRIPTION, | ||
| "mode": "subagent", | ||
| "model": opencode_model, | ||
| "prompt": _SUBAGENT_INSTRUCTIONS, |
There was a problem hiding this comment.
Prevent project agents from overriding the local subagent
When the opened project already defines agent.unsloth (for example with mode: "primary" or another model), that project config outranks the generated OPENCODE_CONFIG overlay, so it replaces these fields and @unsloth is no longer the local subagent despite the launch message. Put the agent definition in the highest-priority inline overlay or use a collision-resistant agent name so --as-subagent is reliable in projects with an existing agent configuration.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 5105fc0: the agent definition now rides in OPENCODE_CONFIG_CONTENT, which outranks project config, so a repo's own agent.unsloth cannot shadow it.
| const args = [ | ||
| "--mode", | ||
| "json", | ||
| "--print", | ||
| "--no-session", | ||
| "--provider", | ||
| provider, | ||
| "--model", | ||
| model, | ||
| "--no-extensions", | ||
| "--extension", | ||
| extension, | ||
| `Task: ${params.task}`, |
There was a problem hiding this comment.
Propagate Pi yolo approval to the spawned child
With unsloth start pi --as-subagent --yolo, --approve is applied only to the parent command; the extension starts a separate Pi child without it. Since Pi's approval gate is project trust, a local subagent that needs tools can still stop for trust approval (or fail with stdin ignored) even though the session requested yolo. Carry the yolo/trust setting into this child invocation as well.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Pi's approve flag governs project trust, not per-tool approval, and non-interactive modes (--mode json --print) never show a trust prompt; they fall back to defaultProjectTrust, so the child cannot stall (stdin is ignored). Omitting --approve on the isolated --no-extensions child is the safer default since it avoids auto-trusting an untrusted project's packages.
A project opencode.json outranks the OPENCODE_CONFIG session file, so a repo defining its own agent.unsloth would field-merge over the session entry and silently shadow the local subagent. Carry the definition in OPENCODE_CONFIG_CONTENT, which outranks project config.
|
@codex review |
|
Codex Review: Didn't find any major issues. 🚀 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 37cfac7e0d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| executable = _which_with_install_dirs("opencode") | ||
| if executable is None: | ||
| typer.echo( | ||
| f"Warning: OpenCode is not installed, so provider filters could not be checked. " | ||
| f"The target configuration must allow '{_OPENCODE_PROVIDER}'.", | ||
| err = True, | ||
| ) |
There was a problem hiding this comment.
Recompute OpenCode provider filters after installing it
When opencode is initially absent and the user's global or project config has an enabled_providers allowlist, this branch returns without adding unsloth-studio to the inline overlay. The configuration is built before _run offers/install OpenCode, so the subsequent launch inherits that allowlist and filters out the newly registered provider; @unsloth then resolves as unavailable. Re-run the effective-config inspection after installation (or otherwise merge the existing filters) before launching.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 3bfac61: on a first launch with no opencode binary, the install is offered before the provider-filter inspection, so a global or project allowlist is merged instead of being read only after _launch installs OpenCode.
| *ctx.args, | ||
| "--allowedTools", | ||
| _CLAUDE_SUBAGENT_TOOL, |
There was a problem hiding this comment.
Place Claude's allowed-tools flag before passthrough arguments
When callers use the standard -- delimiter to forward Claude arguments (for example, unsloth start claude --as-subagent -- --resume <id>), everything appended after that delimiter is positional. This puts --allowedTools into Claude's prompt/arguments rather than its option parser, so the MCP tool is no longer pre-approved and the forwarded Claude flags are also not honored. Add the allowed-tools option before ctx.args.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 3bfac61: --allowedTools now precedes the forwarded arguments, so a passthrough -- cannot make it positional.
- Put --allowedTools before forwarded arguments so a passthrough -- does not turn it positional and drop the tool pre-approval - Offer the OpenCode install before inspecting provider filters so a global or project allowlist is honored on the first launch
|
@codex review |
1 similar comment
|
@codex review |
This comment was marked as low quality.
This comment was marked as low quality.
|
Codex Review: Didn't find any major issues. More of your lovely PRs please. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
d994800
into
unslothai:pr/daniel-unsloth-start-audit
…nd Pi (#7326) Bring the local-subagent support onto main. The original change (#7316) merged into the stacked pr/daniel-unsloth-start-audit branch rather than main, and #7313 reached main via squash, so these files never landed on main. Adds --as-subagent for claude, codex, opencode and pi: the parent agent keeps its own cloud model while a locally served GGUF is registered as a delegated subagent, using ephemeral per-session config that never touches the user's real agent config.
…nd Pi (unslothai#7326) Bring the local-subagent support onto main. The original change (unslothai#7316) merged into the stacked pr/daniel-unsloth-start-audit branch rather than main, and unslothai#7313 reached main via squash, so these files never landed on main. Adds --as-subagent for claude, codex, opencode and pi: the parent agent keeps its own cloud model while a locally served GGUF is registered as a delegated subagent, using ephemeral per-session config that never touches the user's real agent config.
* Add Agents settings tab for unsloth start Adds a Settings > Agents tab documenting the `unsloth start` command: quickstart, supported agents with click-to-copy commands, model selection, common options, remote Studio setup, argument pass-through, and a dry-run preview. Agent CLIs found on PATH are badged as installed. Also removes the "New" badge from the System and Chat tabs. * Use official brand logos for agents, invert Ollama and OpenRouter in dark mode Claude Code and OpenAI Codex now use the Anthropic and OpenAI logos from the provider-logos registry; agents without an official asset keep the monogram tile. Also inverts the Ollama and OpenRouter logos in dark mode so their monochrome marks stay visible. * Title Agents tab "Agents (unsloth start)" and move it below Connections The in-tab header now reads "Agents (unsloth start)" while the sidebar label stays "Agents". Reorders the tab to sit below Connections. * Address review: guard PATH detection, fix copy timeout, OS-aware remote snippet - Only probe agent PATH in the desktop app on a loopback backend, so Installed badges are not driven by a remote server's environment. - Show the "none found" note only when detection actually ran and returned empty, not when the call failed. - Share one copy hook that resets its timeout on rapid clicks and clears it on unmount. - Render the Remote Studio snippet with PowerShell syntax on Windows. - Note that --no-launch can still load a model when --model is set. - Drop unused quickstart translation keys. * Add interactive Agents command builder * Add local subagent command guidance * Add official coding agent icons * Use client OS for remote commands, fix copy a11y and model wording (#7303) - Pick the remote snippet shell from the client platform, not the server deviceType - Single-line the model examples so they paste in POSIX, PowerShell and cmd - Split the pass-through block into independent one-command copies - Derive detection visibility instead of clearing state in the effect - Announce copy success to assistive tech - Correct the quickstart/model copy: bare start uses the loaded model * Shell-quote the model, forward the HF token, and fix the quant placeholder - Quote the --model value in the generated and subagent commands so a local path with spaces or metacharacters stays a single argument (client-OS aware) - Pass the saved Hugging Face token to listGgufVariants so gated repos resolve - Show 'No separate quantization' instead of a stuck 'Loading quantizations...' when a model has no variants; clear the failure once a later request succeeds * Fix Agents command discovery and routing * Unsloth start improvements: download progress, server reuse, and safe model switching (#7313) * Improve unsloth start runtime lifecycle * Remove speculative Gemma prompt override * Polish model download progress output * Refine unsloth start status output * Clarify unsloth readiness banner * Clarify model reuse and switching output * Queue model switches behind active inference * Tighten unsloth start model switching * Reduce model switch bookkeeping * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fix Studio re-exec compatibility * Recheck sidecar reservation after inference drain * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Pass start marker through child environment * Fix key redaction, switch-waiter ordering, and stop/messaging gaps for PR #7313 - Redact minted sk-unsloth keys from the startup-failure log tail: the early key marker lands in the server log before the model load finishes, so a load-phase crash printed a live key to the terminal - Deregister a finished switch waiter before releasing the swap gate so a swap on another event loop cannot count it as still queued and unload the model the finished request is about to generate against - Warn on same-repo quant switches: an explicit variant replaces the resident weights for every attached session, but the repo ids match so no switch warning was printed - Note the agent exit code when it is nonzero so the server keep-alive message does not read as a successful session - Use taskkill /T in unsloth studio stop so llama-server children stop too * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Tighten comments in start, studio, and inference changes --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Daniel Han <danielhanchen@gmail.com> * Unsloth start: add local subagents for Claude Code, Codex, OpenCode and Pi (#7326) Bring the local-subagent support onto main. The original change (#7316) merged into the stacked pr/daniel-unsloth-start-audit branch rather than main, and #7313 reached main via squash, so these files never landed on main. Adds --as-subagent for claude, codex, opencode and pi: the parent agent keeps its own cloud model while a locally served GGUF is registered as a delegated subagent, using ephemeral per-session config that never touches the user's real agent config. * Fix Agents builder defaults and flag validation * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fix Agents variant and provider fallbacks * Fix local model and Pi subagent edge cases * Agents tab: flag the Codex row when the loaded model is not GGUF * Agents tab: target the active Studio server, wrap narrow rows, index the tab's search terms * Agents tab: build copied commands from the browser-reachable Studio and show the key placeholder * Preserve cache load ids and path variants in built commands for PR #7312 A GGUF outside the active Hugging Face cache only loads by its snapshot path, so keep that load_id for --model while still listing the row by repo id. Path based models carry their quant in --gguf-variant rather than a ":variant" suffix, and the active selection now keeps the variant inference status reports for them. * Agents tab: index the intro for agent-name searches and keep long commands inside the panel * List GGUF variants from the cache the command loads from for PR #7312 A snapshot outside the active Hugging Face cache was offering the remote variant list, so a quant absent from that snapshot could be selected and the generated command would fail to load it. * Agents tab: omit --api-key so the CLI can replay a saved key for the base * Agents tab: label the indexed heading rows and fall back to the active desktop API base * Agents tab: name every supported agent in the indexed intro for PR #7303 * Send the cached GGUF load path and fix the agents tab search targets for PR #7312 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Tighten the agents tab comments for PR #7303 * Build the agents tab example commands from the active Studio base for PR #7303 * Keep the resident model on its active cache load for PR #7312 * Tighten the agents tab and cached GGUF comments for PR #7312 * Take the agent command shell from the Studio host for PR #7303 * Stop emitting snapshot paths as --model and keep unsloth start searchable for PR #7312 * Pick the command shell from where the CLI runs for PR #7303 * Match a path load by its advertised id and follow the resident model for PR #7312 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Keep an explicit quantization and retire superseded native-grant labels for PR #7312 * Scope the remembered quant, stop following unloaded models and keep local GGUF paths for PR #7312 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Stop shadowing the path classifier, match snapshot ordering and sequence status polls for PR #7312 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Release stale native-grant picks, keep local GGUF identities and index snapshot aliases for PR #7312 * Index inactive-cache snapshots, widen local GGUF detection and clear retired quants for PR #7312 * Classify cached repos by snapshot, merge repo ids case-insensitively and keep loose GGUFs variantless for PR #7312 * Fix snapshot alias, partial split and mmproj-only handling for PR #7312 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Trust scanned model_format and drop incomplete snapshot ids for PR #7312 * Exclude mmproj and partial downloads, keep path case and drop duplicate scan for PR #7312 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Restrict revision aliases and require complete snapshot variants for PR #7312 * Index revisions individually and hide partial variants for PR #7312 --------- Co-authored-by: shimmyshimmer <107991372+shimmyshimmer@users.noreply.github.com> Co-authored-by: Daniel Han <danielhanchen@gmail.com> Co-authored-by: oobabooga <oobabooga4@gmail.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
unsloth startcurrently points the coding agent itself at the local model. Claude Code, Codex, OpenCode, and Pi can also keep their current model and delegate selected tasks to a local agent, but there was nounsloth startpath for setting that up.What changed
Add
--as-subagentfor Claude Code, Codex, OpenCode, and Pi:The command starts or reuses Unsloth Studio, loads the requested local model, and registers it as an additional agent without replacing the coding agent's current model.
Claude Code local agent plugin
Claude Code receives a session plugin with a model-invoked skill and an
unsloth_agenttool. This provides the plugin bridge suggested for Claude while keeping the parent on its existing model:The tool starts a separate Claude Code child against the local Unsloth model. The child works in the same project, has its own context and tools, and returns its result to the parent. The plugin tool is pre-approved without replacing or disabling the parent's other tools.
Without
--yolo, the child uses Claude'sacceptEditspermission mode. Unsloth's--yolooption maps to Claude's native--dangerously-skip-permissionsflag for the parent andbypassPermissionsmode for the child.Cancelling the plugin call stops the local Claude child and any tool processes it started.
Codex custom agent
Codex receives a session-scoped
unslothcustom agent. It can be selected through normal delegation:The parent keeps its existing model, provider, configuration, and sessions.
OpenCode subagent and model
OpenCode receives an
@unslothsubagent backed by the local model:The same Unsloth model is also available in
/models, while the parent keeps its existing main and small models. Session provider filters keep the parent's allowed providers and add Unsloth without changing the user's configuration.Pi local agent and model
Pi loads a bundled extension that adds the Unsloth model to
/modeland registers anunsloth_agenttool. Calling it starts a separate local Pi child with its own context and tools, then returns the result to the parent.The child runs in the same working directory, but does not inherit the parent conversation or register another copy of the agent tool.
Keep the exact local model configuration
The registered model includes the selected GGUF variant, so a later reload cannot silently choose a different cached quant. The generated configurations use the loaded model's context length, and OpenCode and Pi receive output limits derived from that window. Generated configuration is isolated to the Unsloth session. Claude, Codex, and Pi keep the local API credential out of the parent's tool environment. Windows agent paths are translated when launched through WSL.
Verification
@unsloth; the local model also appeared in/models.unsloth_agent; the local model also appeared in/model.git diff --checkpass.