pharo-agentic-browser brings Pharo AI coding to your image as a native agentic coding environment: a Pharo-native UI tool for managing multiple AI coding agent sessions — Claude Code, Gemini CLI, OpenCode, and others — in parallel from inside your Pharo image. It enables AI-assisted Smalltalk development by letting each session, called a topic, work as an autonomous agent on your code: you type a request, the agent works, and pauses only when it needs your approval.
- Introducing Pharo Agentic Browser
- pharo-agentic-browser in 3 minutes — a demo of generating a URL-routing Trie class from a simple prompt, using OpenCode with the GPT-5.6 Terra model.
+---------------------+-------------------------------------------+
| Topics | [Human] @QueryClass refactor this |
| | |
| +-------------------------------------------+
| ❇️DB Optimization | [AI] I'll refactor QueryClass. First, |
| UI Improvement | let me check the current code... |
| ✓Fix Tests | |
| | [System] UserList-Core was modified; |
| [+ New Topic] | .st files have been updated |
| | [AI] May I modify DBAdapter#connect? |
| | [Human] yes |
+---------------------+-------------------------------------------+
The core workflow:
- Create a topic and select an ACP-compatible agent (Gemini CLI, Claude Code, OpenCode, etc.)
- Type a request in the chat pane — mention code context with
@ClassNameor@ClassName>>method - The AI starts working (task decomposition, code changes, tests)
- When the AI needs human judgment, it pauses and asks in the chat
- Respond in plain text — the AI resumes
- Topic status is always visible in the sidebar
- Native to the image — runs inside Pharo itself, with
@ClassNamecode mentions and automatic tracking of package changes made by human and the agent, instead of bolting an external tool onto your workflow - Mobile access — the Web UI is a browser-based interface served over WebSocket, so you can check on and steer topics from a phone or tablet, not just a desktop Pharo image
- Multi-agent orchestration — the Scripting DSL coordinates multiple coding agents across sequential and parallel steps, with automatic result injection between them, instead of driving one agent session at a time
- Agent-agnostic — works with any ACP-compatible agent (Claude Code, Gemini CLI, OpenCode, and others), so you aren't locked into a single vendor's CLI or IDE plugin
- Conversational human-in-the-loop — approvals happen as chat replies, not modal dialogs, so you can steer a topic without breaking flow
- Multi-topic management — run multiple AI agent sessions in parallel
- Status tracking — per-topic state machine (
initial → working → waitingForHuman → endTurn → goalAchieved) - Human-in-the-loop — conversation-style approval flow (no modal dialogs)
- Agent-agnostic — works with any ACP-compatible agent
- Goal setting — set a completion condition; the AI works autonomously until the goal is achieved, then reports back
- Session persistence — topic list and state are saved to
ab-topics.fuelvia Fuel and survive image restarts - Code mentions — type
@ClassNameor@ClassName>>methodNamein chat to embed the Tonel source as ACP resources - MCP server support — configure MCP servers via
mcp.json; built-in Smalltalk MCP servers can be auto-merged - Working directory management — per-topic working directory for better context; custom paths for existing projects
- Topic template — seed every new topic's working directory from
topic-template, so coding-agent config (CLAUDE.md,AGENTS.md,.claude,.opencode, etc.) doesn't need to be set up per topic - Multiple package prefixes — track multiple package families (e.g.
#('ACP-*' 'BaselineOfACP')) per topic - Image change watching —
AbTopicRelatedPackagesWatchermonitors image changes, inserts system messages into chat, and asks for confirmation before synching packages - Code review with crit — review the agent's changes in the browser with crit; review comments are fed back to the agent in the topic
- Web UI — browser-based interface via WebSocket (docs/web-ui.md)
- Scripting API — headless DSL for coordinating multiple topics from code; supports sequential and parallel steps with automatic result injection (docs/scripting.md)
- Pharo 12+
- pharo-acp
- SState
- PharoSmalltalkInteropServer
- At least one ACP-compatible agent installed (e.g.
claude-agent-acp,agent acp)-
Whether usage is billed to your subscription plan or as pay-as-you-go API key usage depends on each agent's own authentication and billing scheme
-
Claude Code and Codex do not support ACP out of the box. To use them, install the ACP adapters claude-agent-acp and codex-acp separately (requires Node.js, which provides
npm):npm install -g @agentclientprotocol/claude-agent-acp npm install -g @agentclientprotocol/codex-acp
-
In a Pharo image, open a Playground and evaluate:
Metacello new
baseline: 'AgenticBrowser';
repository: 'github://mumez/pharo-agentic-browser:main/src';
load.To also load the test suite:
Metacello new
baseline: 'AgenticBrowser';
repository: 'github://mumez/pharo-agentic-browser:main/src';
load: 'Tests'.Load the server-side package:
Metacello new
baseline: 'AgenticBrowser';
repository: 'github://mumez/pharo-agentic-browser:main/src';
load: 'WebUI'.For client setup and full usage, see docs/web-ui.md.
Load the Scripting package to create and coordinate multiple topics from code, with no UI:
Metacello new
baseline: 'AgenticBrowser';
repository: 'github://mumez/pharo-agentic-browser:main/src';
load: 'Scripting'.For the full DSL reference and examples, see docs/scripting.md.
If you'd like to install all of these packages at once, you can use the 'all' group.
Metacello new
baseline: 'AgenticBrowser';
repository: 'github://mumez/pharo-agentic-browser:main/src';
load: 'all'.Note: Loading
WebUI(and therefore'all') updates Zinc, which triggers a warning dialog during installation. To avoid getting stuck on the dialog (e.g., in headless environments), install as follows:
[Metacello new
baseline: 'AgenticBrowser';
repository: 'github://mumez/pharo-agentic-browser:main/src';
onConflict: [ :e | e useIncoming ];
onUpgrade: [ :e | e useIncoming ];
ignoreImage;
load: 'all'] on: MCMergeOrLoadWarning do: [ :ex | ex load ] Open the browser window:
AgenticBrowser open.- Click + New Topic
- Enter a title and select an agent
- (Optional) Enter an existing project directory
- Click Create — the topic appears in the left sidebar
- Right-click the topic and choose Set Target Packages... to configure which packages to watch
- Type a request and press Send — status changes to
❇️(working) - When the AI requests permission, the Send button changes to Allow and Cancel to Deny, and status shows
? - Click Allow to approve or Deny to reject
- The AI resumes; when finished, status changes to
●(endTurn)
You can also right-click a topic to Rename..., Delete, or Set Goal....
Note: The first message in each topic is automatically prefixed with the
initialPromptSkillsetting (default/st-buddy) and a space to activate the Smalltalk buddy agent mode. Change it in Initial Prompt Skill of the Settings dialog for other agents or custom skills (e.g.$st-buddyfor codex/junie), or leave it empty to send the first message as is.
In the chat input, you can reference Pharo classes or methods by prefixing them with @:
@QueryClass @DBAdapter>>connect please refactor this
When you send the message, AgenticBrowser resolves each mention to its Tonel source and attaches it as an ACP text resource alongside the prompt. The AI agent receives the exact code without any copy-paste.
You can also drag and drop directly from Pharo tools into the input field:
- Drag a class from the System Browser class list → inserts
@ClassName - Drag a method from the System Browser method list → inserts
@ClassName>>methodName
Click the [ ] button in the status bar to capture a screen area and attach it to your next message.
- Click the button — the cursor changes to a crosshair
- Drag to select the area you want to capture
- A mention like
@sc-20260528-001.pngis inserted into the input field - Send — the PNG is attached to the prompt as an image resource
The file is saved to <agenticBrowserRoot>/screenshots/sc-YYYYMMDD-NNN.png. You can also reference a previously captured file manually by typing @sc-YYYYMMDD-NNN.png in the input field.
Click the + button in the status bar to attach any file from disk.
- Click the button — a file selection dialog opens
- Choose a file — a mention like
[filename]is inserted into the input field - Send — the file's contents are attached to the prompt as a text resource
Deleting the [filename] mention text before sending removes the attachment. If the file's contents exceed AbSettings >> maxAttachmentSize (default: 5 MB), the attached text is truncated.
When a new topic's working directory is created, AgenticBrowser copies the contents of <agenticBrowserRoot>/topic-template into it.
By default this template holds a CLAUDE.md and AGENTS.md tailored for the smalltalk-dev plugin, generated the first time the template directory is accessed. You can replace these with your own customized versions.
You can also place coding-agent project config directories here, such as .claude or .opencode, containing skills, commands, and rules shared across topics. This saves you from reconfiguring the coding agent for every new topic.
Note: The template is only copied into working directories created under the AgenticBrowser root. It is not copied when you set a custom directory path pointing at an existing project.
Right-click a topic and choose Set Goal... to enter a completion condition (e.g., all tests pass). AgenticBrowser sends a goal notification prompt to the AI:
Goal has been set: all tests pass. When the goal is achieved, summarize and
report in result-<topic-id>.md. Keep retrying until the goal is achieved.
The AI works autonomously. When it creates result-<topic-id>.md in the working directory, AgenticBrowser reads it, stores the result, and transitions the topic to ✓ (#goalAchieved). From that state, the topic can only be reset to initial (effectively archived).
Two hooks fire when a goal is achieved:
- Announcement —
AbTopicGoalAchievedis announced via the topic's own announcer, carrying thetopicandgoal(AbTopicGoal). Subscribe with:topic announcer when: AbTopicGoalAchieved do: [:ann | Transcript crShow: ann topic title , ' achieved: ' , ann goal result]. - Callback block — register an optional block on the topic with
whenGoalAchieved:. The block receives theAbTopicGoalas its argument (or takes zero arguments):topic whenGoalAchieved: [:goal | Transcript crShow: goal result].
Topics are saved automatically to ab-topics.fuel in the AgenticBrowser root directory using Pharo's Fuel serializer. You can also save and restore manually:
AbTopicManager save.
AbTopicManager load.Place a mcp.json file in your AgenticBrowser root directory (default: <imageDir>/agentic-browser/mcp.json) to configure MCP servers passed to the agent on session start:
{
"mcpServers": {
"extra-server": {
"command": "uvx",
"args": ["extra-server-package"],
"env": {"EX_SERVER_PORT": 12345}
}
}
}When AbSettings >> useDefaultMcpServers is true (the default), the built-in smalltalk-interop and smalltalk-validator MCP servers are automatically merged with your mcp.json entries. User entries take precedence over the defaults. Set useDefaultMcpServers to false to use only your mcp.json.
Watching starts automatically when a topic first connects (on the first Send).
crit is a tool for reviewing changed files from a web browser. With the crit integration, you can start crit from AgenticBrowser through a menu (or a button in the Web UI) instead of running it yourself. When you finish a review, the agent picks up your comments and its responses flow into the topic's conversation in AgenticBrowser.
To enable it, check Use crit review in the Settings dialog and make sure the crit command is on your PATH. Then, when the agent's turn has ended, right-click the topic and choose Review by crit.
For installation and the review flow, see docs/use-crit.md.
Any ACP compatible coding agent can be used. The following agents are available as presets in the New Topic dialog:
| Agent | Command + Arguments | Install |
|---|---|---|
| Claude Code | claude-agent-acp |
npm install -g @agentclientprotocol/claude-agent-acp |
| Codex | codex-acp |
npm install -g @agentclientprotocol/codex-acp |
| Gemini CLI | gemini --acp |
ACP is built-in |
| OpenCode | opencode acp |
ACP is built-in |
| GitHub Copilot CLI | copilot --acp --stdio |
ACP is built-in |
| Cursor CLI | cursor-agent acp |
ACP is built-in |
| Kilo Code | kilo acp |
ACP is built-in |
| Kiro CLI | kiro-cli acp |
ACP is built-in |
| Devin CLI | devin acp |
ACP is built-in |
| Grok Build | grok agent stdio |
ACP is built-in |
Strongly Recommended: Install the smalltalk-dev-plugin in your agent. It provides Smalltalk-aware skills and MCP servers that agents can use to work directly with Pharo inside the session.
To add a custom agent, edit ab-settings.json directly in a text editor. Alternatively, from a Playground:
AbSettings default codingAgents: (AbSettings default codingAgents copyWith:
{'name' -> 'my-agent'.
'command' -> #('my-agent' '--acp')} asDictionary).
AbSettings save.| Package | Contents |
|---|---|
AgenticBrowser-Core |
Domain model: AbTopic, AbTopicSession, AbTopicManager, AbTopicGoal, AbMessage, AbWorkingDirectory, AbMcpServersLoader, AbCodeMentionParser, AbCodeMentionEmbedder, AbTopicRelatedPackagesWatcher, announcements |
AgenticBrowser-Handler |
ACP callback bridge: AbTopicHandler |
AgenticBrowser-UI |
Spec2 presenters: browser, topic list, chat, new-topic dialog, settings dialog, and other dialogs |
AgenticBrowser-Tests |
SUnit tests for Core |
AgenticBrowser-WebUI |
Ripple WebSocket server: AbTopicManagerRipple |
AgenticBrowser-WebUI-Tests |
SUnit tests for WebUI |
AgenticBrowser-Scripting |
Scripting DSL: AbTopicOrchestration, AbTopicOrchestrationBuilder, AbTopicBuilder, AbCodingAgentBuilder, AbSequentialStep, AbParallelStep |
AgenticBrowser-Scripting-Tests |
SUnit tests for Scripting |
BaselineOfAgenticBrowser |
Metacello baseline |
Each topic has an FSM with five states:
#initial ──promptSent──▶ #working ──permissionRequested──▶ #waitingForHuman
▲ │
└──────────humanResponded──────────────┘
│
turnEnded
▼
#endTurn ──promptSent──▶ #working
│
goalReached
▼
#goalAchieved ──reset──▶ #initial
When the AI requests permission, AbTopicHandler#requestPermission: puts the UI into approval mode (Send button becomes Allow, Cancel becomes Deny). When the user clicks a button, the UI returns to normal mode.
AbTopicGoal holds the goal description, result text (once achieved), and an optional callback block. It manages the result file path (result-<topicId>.md in the working directory). After each end_turn, AbTopic>>checkGoalAchievement checks whether the file exists; if so, the topic transitions to #goalAchieved and fires an AbTopicGoalAchieved announcement.
AbCodeMentionParser scans raw chat input for @Foo and @Foo>>bar tokens and returns AbCodeMention value objects. AbCodeMentionEmbedder resolves each mention to its Tonel source using TonelWriter and produces URL→content associations. AbChatPresenter calls both before sending and passes the resolved resources to AbTopic>>sendPrompt:withResources:.
AbMcpServersLoader reads mcp.json from AbSettings>>defaultAgenticBrowserRootDirectory, optionally merges built-in Smalltalk server definitions (controlled by AbSettings>>useDefaultMcpServers), and returns an OrderedCollection of ACPMcpServer. AbTopicSession calls it on every connect and passes the result to the ACP session params (newSessionBy:, resumeSessionBy:, loadSessionBy:).
Each topic has a working directory at <imageDir>/agentic-browser/<safe-topic-name>-<uuid8>/. The UUID suffix ensures stability even if the topic title changes.
You can also set a custom working directory path when creating a topic from an existing project directory.
AbTopicRelatedPackagesWatcher subscribes to SystemAnnouncer for MethodAnnouncement and ClassAnnouncement. When a method or class is saved:
- If the package matches any of the topic's
packagePrefixes, it inserts a message into the chat (e.g."AgenticBrowser-Core was modified; .st files have been updated") and confirms exporting the package - If the package does not match, it add the package to
updatedExternalPackageNames. They can be moved to tracked packages by 'Apply Updated External Packages' menu - Changes during import are suppressed to avoid re-export loops
Settings are managed by AbSettings and persisted as ab-settings.json in the AgenticBrowser root directory. There are two levels: global defaults and per-topic overrides.
Open the Settings dialog from the Settings… menu in the browser window's menu bar. The dialog covers timeout values, timeout options, MCP server preferences, the monitoring interval, and crit review settings.
| Key | Default | Description |
|---|---|---|
codingAgents |
(built-in list) | Array of {name, command} dicts shown in the New Topic dialog |
useDefaultMcpServers |
true |
Merge built-in Smalltalk MCP servers into mcp.json |
aiPermissionWaitTimeoutSeconds |
1800 |
Seconds to wait for human response to an AI permission request |
aiPermissionTimeoutOption |
#reject_once |
Auto-response on timeout: #allow_once or #reject_once (Allow / Deny in the Settings dialog). #allow_always can be set only via scripting or the API, and only takes effect if the agent offers an "always allow" option |
exportApprovalWaitTimeoutSeconds |
30 |
Seconds to wait for human approval of a package export |
exportApprovalTimeoutOption |
#reject_once |
Auto-response on export timeout |
watcherMessageThrottleSeconds |
2 |
Minimum seconds between watcher system messages for the same package |
maxAttachmentSize |
5242880 (5 MB) |
Max characters of a file attachment's contents embedded into a prompt |
initialPromptSkill |
'/st-buddy' |
Skill invocation prepended (with a space) to the first prompt of a topic, e.g. '$st-buddy' for codex/junie; empty disables the prefix. Replaces the former boolean useStBuddySkillOnInitialPrompt; an ab-settings.json with the old key is still read (true → default skill, false → empty) |
useCommandOnGoalSet |
false |
Prefix the goal notification prompt with goalSetCommand |
goalSetCommand |
'/goal' |
Command prefix used when useCommandOnGoalSet is true |
monitoringIntervalSeconds |
15 |
Seconds between the periodic topic checks: resuming stalled goal topics and sending finished crit reviews to their agents (Monitoring interval (seconds) in the Settings dialog; must be a positive integer). Formerly stallMonitoringIntervalSeconds; an ab-settings.json with the old key is still read, and is saved with the new key |
useCrit |
false |
Offer Review by crit for topics whose working directory is a git repository (Use crit review in the Settings dialog) |
critAllowUnauthenticatedNetwork |
true |
Let crit accept unauthenticated access from other hosts in the LAN; when false, crit binds to localhost only (Allow crit access within LAN in the Settings dialog) |
critPortRange |
'9080-9100' |
Inclusive port range (<low>-<high>, 1-65535) from which a free port is picked when crit starts |
Each topic starts with a copy of the global settings. Right-click a topic in the sidebar and choose Edit Settings... to open the settings dialog for that topic alone.
The monitoring interval and the crit settings are global only; they are hidden in the per-topic settings dialog because the monitoring loop and crit read only the global settings.
Per-topic settings are persisted with the topic via Fuel when AbTopicManager save is called.
- skills/ — Agent skills for coding agents, for use by anyone with AgenticBrowser installed (e.g.
ab-scripting-feature-dev, which generates and runs Scripting DSL orchestrations for feature development in your own project)
- pharo-acp — ACP client library for Pharo
- SState — Simple state machine library for Pharo
- PharoSmalltalkInteropServer — HTTP API server for Pharo package import/export/test
- smalltalk-dev-plugin — AI agents plugin providing Smalltalk-aware skills and slash commands
MIT
