diff --git a/CLAUDE.md b/CLAUDE.md index 992a67fd..d5407a8f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,6 +1,6 @@ # Botloft -Workspace desktop Windows-first, com código público sob a FSL (vira Apache 2.0 após dois anos), para rodar bots de agentes de código sempre ligados que colaboram entre si: Claude Code, Antigravity (experimental) e, em seguida, Codex. A seção 30 da spec e o ADR 0003 dizem como cada agente entra. Daemon Rust (`botloftd`) + app Tauri v2 + React. +Workspace desktop Windows-first, com código público sob a FSL (vira Apache 2.0 após dois anos), para rodar bots de agentes de código sempre ligados que colaboram entre si: Claude Code, Antigravity e Codex (os dois últimos experimentais). A seção 30 da spec e o ADR 0003 dizem como cada agente entra. Daemon Rust (`botloftd`) + app Tauri v2 + React. ## Fonte de verdade diff --git a/README.md b/README.md index f0720801..5a2e1fab 100644 --- a/README.md +++ b/README.md @@ -33,8 +33,8 @@ Botloft keeps a crew of bots running on your computer, each on the AI coding agent you choose: -[Claude Code](https://code.claude.com), or [Antigravity](https://antigravity.google) as an experimental -option, with Codex next. Each bot has its own folder, memory and conversation. They pass work to each other, keep going after you close the +[Claude Code](https://code.claude.com), or, as experimental options, +[Antigravity](https://antigravity.google) and [Codex](https://developers.openai.com/codex). Each bot has its own folder, memory and conversation. They pass work to each other, keep going after you close the window and pick up where they left off after a restart. You talk to each one like in a chat app, and you decide what they may do. @@ -88,15 +88,18 @@ itself. | Usage meter and "Compact" | yes | an estimate of the conversation size; no compaction | | Isolation between crews | yes | folders are fenced for its file tools, not for commands you allow | -Claude Code is the full experience. Antigravity is off until you add `experimental_agents = ["agy"]` -to Botloft's `config.toml`; then a new bot can be made on it, and Settings has "Agent for new -bots". Codex is the next agent. See [spec section 30](docs/spec.md) for what was checked. +Claude Code is the full experience. Antigravity and Codex are off until you list them in Botloft's +`config.toml` (`experimental_agents = ["agy"]`, `["codex"]` or both); then a new bot can be made on +them, and Settings has "Agent for new bots". A Codex bot reads files, uses the crew's tools and +answers, with the exact size of its conversation; it cannot change files or run commands yet, and +asking you before it acts is the next step. See [spec section 30](docs/spec.md) for what was +checked. ## Get started You need at least one agent installed and signed in once, with your own account: -[Claude Code](https://code.claude.com/docs/en/setup), or Antigravity (experimental, see -[Agents](#agents)). Bots run on your own plan with that agent. +[Claude Code](https://code.claude.com/docs/en/setup), Antigravity or Codex +(experimental, see [Agents](#agents)). Bots run on your own plan with that agent. 1. Download Botloft for your computer from the [latest release](https://github.com/httpsphl/botloft/releases/latest): @@ -137,7 +140,7 @@ flowchart LR scheduled task of your Windows user, a systemd user service on Linux or a launch agent on macOS: it starts when you sign in and comes back soon if it dies. - **Your agent is the runtime.** Each bot is a real session of the agent you chose (`claude -p` for - Claude Code, `agy -p` for Antigravity) with its own workspace, memory and conversation. There is + Claude Code, `agy -p` for Antigravity, `codex app-server` for Codex) with its own workspace, memory and conversation. There is no custom agent SDK and no API key to manage. - **One conversation per bot.** Your messages, messages from other bots and notices from the daemon reach the bot in order. What it does comes back as a chat: replies, tool use and requests you @@ -230,8 +233,8 @@ Windows came first and has had the most use; if something does not work elsewher
Is Botloft made by Anthropic? -No. Botloft is an independent project. It uses Claude Code and Antigravity as installed on your -computer and is not affiliated with or endorsed by Anthropic or Google. +No. Botloft is an independent project. It uses Claude Code, Antigravity and Codex as installed on your +computer and is not affiliated with or endorsed by Anthropic, Google or OpenAI.
## Status @@ -247,7 +250,7 @@ and a code-signed installer. `main` can be ahead of the latest release. Requirements: Rust stable (the MSVC toolchain on Windows), Node.js 24 and pnpm. On Linux, the app also needs the desktop libraries Tauri uses (on Ubuntu: `libwebkit2gtk-4.1-dev`, `libayatana-appindicator3-dev`, `librsvg2-dev`, `libxdo-dev`). Running real bots also needs an agent -installed and signed in: Claude Code (the native `claude` executable) or Antigravity (`agy`). +installed and signed in: Claude Code (the native `claude` executable), Antigravity (`agy`) or Codex. ```powershell # Daemon and libraries diff --git a/app/src/features/bots/BotDialog.tsx b/app/src/features/bots/BotDialog.tsx index 0bc8646d..6c9f3bdc 100644 --- a/app/src/features/bots/BotDialog.tsx +++ b/app/src/features/bots/BotDialog.tsx @@ -148,12 +148,14 @@ export function BotDialog(props: Props) { /> {agent !== "claude" && (

- {t.bots.dialog.agent.experimental} + {agent === "codex" + ? t.bots.dialog.agent.experimentalCodex + : t.bots.dialog.agent.experimental}

)} )} - {editing && editing.agent !== "claude" && ( + {editing && editing.agent === "agy" && ( <> { expect(dialog.queryByLabelText("Model")).toBeNull(); }); }); + +describe("Codex in the new-bot dialog", () => { + test("says what it cannot do yet", async () => { + const fake = new FakeBotloft(); + fake.system = { ...fake.system, enabledAgents: ["claude", "codex"] }; + fake.addCrew("Ops"); + renderApp(fake); + await crewOpened("Ops"); + const [button] = await screen.findAllByRole("button", { name: "New bot" }); + fireEvent.click(button as HTMLElement); + const dialog = within(await screen.findByRole("dialog", { name: "New bot" })); + fireEvent.change(dialog.getByLabelText("Agent"), { target: { value: "codex" } }); + expect(dialog.getByRole("note").textContent).toMatch(/cannot change files or run commands yet/); + expect(dialog.queryByLabelText("Model")).toBeNull(); + }); +}); diff --git a/app/src/features/chat/ChatComposer.tsx b/app/src/features/chat/ChatComposer.tsx index c0ca0818..d4f1580b 100644 --- a/app/src/features/chat/ChatComposer.tsx +++ b/app/src/features/chat/ChatComposer.tsx @@ -254,7 +254,7 @@ export const ChatComposer = memo(function ChatComposer({ ) : ( - + bot.agent === "agy" && )}