diff --git a/docs/specs/agent-config-ui.md b/docs/specs/agent-config-ui.md
index 90d3753767..1b1090de77 100644
--- a/docs/specs/agent-config-ui.md
+++ b/docs/specs/agent-config-ui.md
@@ -2,7 +2,9 @@
## Current implementation (2026-09-07)
-The shipped new-agent flow starts from **Agents → New Agent**. A small dialog collects a name and an enabled adapter, then opens a setup page with numbered navigation. Claude and Codex have a subscription/API-key connection step. Configuration provides a searchable, free-text model selector and an environment selector; additional settings remain on the full agent page. **Finish setup** submits the existing governed hire request. Confirmation links to configuration and opens a new task with the created agent assigned; agents awaiting approval cannot be assigned work yet.
+The shipped new-agent flow starts from **Agents → New Agent**. A small dialog collects a name and an enabled adapter, then opens a setup page with numbered navigation. Claude, Codex, and Grok have a subscription/API-key connection step. Configuration provides a searchable, free-text model selector and an environment selector; additional settings remain on the full agent page. **Finish setup** submits the existing governed hire request. Confirmation links to configuration and opens a new task with the created agent assigned; agents awaiting approval cannot be assigned work yet.
+
+On Cloud, the new-agent picker and direct setup links allow Claude, Codex, OpenCode, and Grok. Four available adapters use a two-column grid on desktop and mobile. Grok uses the existing `grok_local` adapter with an xAI subscription or API-key connection and the managed sandbox environment. The picker and connection step share provider marks that adapt to light and dark mode. An adapter must also be loaded and enabled to be available.
Paperclip Runner offers native Codex (app server), Claude via ACPX, and OpenCode. The selected provider is passed through the existing runner configuration builder. Codex's default is the adapter catalog default. OpenCode and Pi require a provider/model ID; OpenRouter uses `openrouter//` and `OPENROUTER_API_KEY`. Entered keys are tested through the probe-only `testCredentials` field without storage. Finishing setup saves each key as an isolated user secret so a failed test cannot overwrite another agent’s credential, and an existing organization secret can also be bound. Agent configuration and revisions contain references, never the entered key.
diff --git a/ui/src/components/NewAgentDialog.test.tsx b/ui/src/components/NewAgentDialog.test.tsx
index 8ec88550b4..3259e030f0 100644
--- a/ui/src/components/NewAgentDialog.test.tsx
+++ b/ui/src/components/NewAgentDialog.test.tsx
@@ -132,7 +132,7 @@ it.each([false, undefined])(
},
);
-it("offers only Claude, Codex, and OpenCode on Cloud, even with the runner enabled", async () => {
+it("offers Claude, Codex, OpenCode, and Grok on Cloud, even with the runner enabled", async () => {
await act(async () => {
cache.setQueryData(queryKeys.health, {
status: "ok",
@@ -160,8 +160,15 @@ it("offers only Claude, Codex, and OpenCode on Cloud, even with the runner enabl
[...document.querySelectorAll('input[type="radio"]')].map(
(input) => input.value,
),
- ).toEqual(["claude_local", "codex_local", "opencode_local"]);
+ ).toEqual(["claude_local", "codex_local", "opencode_local", "grok_local"]);
expect(document.body.textContent).not.toContain("CLI harness");
+ await act(async () =>
+ document.querySelector('input[value="grok_local"]')!.click(),
+ );
+ await click("Configure agent");
+ const query = new URL(state.navigate.mock.calls[0][0], "http://local").searchParams;
+ expect(query.get("adapterType")).toBe("grok_local");
+ expect(query.get("name")).toBe("Ada & Co");
});
it("keeps agent-only invitations reachable from the new-agent flow", async () => {
diff --git a/ui/src/components/new-agent/AgentBasicsDialog.tsx b/ui/src/components/new-agent/AgentBasicsDialog.tsx
index de8a3f7a84..173e1cd248 100644
--- a/ui/src/components/new-agent/AgentBasicsDialog.tsx
+++ b/ui/src/components/new-agent/AgentBasicsDialog.tsx
@@ -226,7 +226,7 @@ export function AgentBasicsDialog({
{error.message}