AI Agent
AI Agent puts the agent you already run inside the browser page: a view beside whatever is open, where you talk to Claude Code, Codex, or any command that speaks the Agent Client Protocol, and the page hands over what is on screen as context. The agent runs in the root, reads the same instructions and me.md every agent does, and works under the same role contract. On by default (eidos plugin disable agent switches it off); the plugin’s page names the agent this machine talks to.
Nothing of eidosmd’s own is in the loop: no model, no key, no endpoint. Nothing leaves the machine but through the agent you configured, under its own permissions, except what dictation does: it downloads its speech model once, and sends a recording out only when you choose hosted transcription with your own key.
In the browser
Section titled “In the browser”- A Chat view in the Auxiliary Sidebar: a conversation with the agent, started in the root on the first message with
EIDOS_ROOTset. - Context without asking. What the page has open rides each message: a blueprint by title, id, and file; a canvas page; a collection’s table and its filter; a settings tab; a top-level doc. It shows in the composer’s row as a small indicator by its id (its full name on hover), which a click leaves out of your messages or brings back, and the plugin words it to the agent. The first message of a session carries a standing note: where the agent is, what to read first, that its job is the root folder and nothing outside it, that the docs are
eidos standardandeidos instructions, and the persona. - Your message shows the moment you send it, the reply’s place held under it while the agent starts, a new conversation’s first message too.
- The reply streams as the agent answers, as full markdown: tables, lists, and code coloured by its language with a copy button on each block. The files it changed are listed under the answer, and the reader and the tables refresh as for any change on disk. The scroll stays where you put it, with Jump to latest while the end is out of view.
- Ids are links. An id the root holds, in a reply or in your own message (a blueprint’s, a task’s, a decision’s, a saved view’s, or a former id a task or a decision keeps), opens its page in the main area, with ⌘ or Ctrl, or the middle button, in a new tab; hovering one shows its title, and a task’s or a decision’s status. An id in a code block, or one naming nothing, stays as written.
- The chat zooms on its own. With focus in the chat, Ctrl or ⌘ with + and - make it larger or smaller and 0 puts it back; with focus anywhere else the same keys zoom the app as always.
- Tool calls stay quiet. Each call the agent makes is one line: an icon for its kind, a few words (
Ran pnpm test,Read specs/a.md,Edited 2 files), and a spinner, a tick, or a cross. A click opens what went in and what came out, long output cut with Show more. Calls made back to back are one line that counts them (“Ran 6 commands, read 4 files”) and opens to the list. A failed call is marked in red, on its own line and on its group’s. - Every message has its actions on hover: copy it; edit one of yours and send it again, which takes back everything after it, so the agent answers again in a new session told the turns that are left; and retry the last answer.
- The message box grows with what you type and keeps a draft for each conversation. Under it sits one row: +, the slash commands, the page open, the agent’s mode, model, and effort as a chip each, and Send. Paste, drop, or attach an image or a text file (+, then Upload from computer): an image goes as an image where the agent takes one (Claude Code does), a text file as a file the agent reads, and anything else is refused.
@(or +, then Add context) offers blueprints, tasks, and decisions by id, title, or file (arrows to move, Enter or Tab to pick), and the one picked is a token by its id,@B-8R9V, that Backspace deletes whole; an id typed out in full is one too. A tab or a sidebar entry dragged onto the box lands as the same token. A message sent while the agent works waits in a queue under the answer and goes when it is done. Enter sends, Shift+Enter breaks a line, Esc stops the answer, and Up and Down walk the messages you sent in the conversation as a shell’s history does, Down past the newest giving back what you were writing. - Permissions are the agent’s. A permission request the agent raises is shown as the agent worded it and answered in the view; nothing is approved on your behalf, and you are in the view for every message. The agent’s file reads and writes are answered inside the root only.
- Grilling.
/grillin the message box (offered as you type the slash, with anything after it as your opening) starts a conversation in which the AI Agent questions what is open: it reads the blueprint, or the framework, and asks one question at a time about what the text leaves unsaid, never answering for you. It asks only what your role can answer, in its words and depth: the role of the user picked as you under Users, else the one in.eidos/me.md, with its contract, and your calibration fromme.mdwhen its role is the same. Picking a user of another role is standing in for them: the AI Agent grills you as that user, by their role alone. What did we find? closes it with each gap, what you said, and where in the blueprint it belongs, the gaps for another role listed apart with the role that decides each, and offers to write them in through the agent’s usual permission. - Slash commands.
/at the start of a message, or the slash button, lists them:/new,/clear(the conversation back to its start),/rename(to what follows),/done(deletes the conversation and opens the next),/settings,/check(the root’s check, its findings written into the conversation),/explain(the agent summarizes what the message carries), and/grill; with Backlog on,/taskasks the agent to make a task, and with Decisions on,/decideto log a decision. With Git on,/git-commitasks the agent to commit your changes at once, and/git-publishand/git-fetchrun Publish and Fetch and say how it went in the conversation./migrateappears only while the root is behind the standard this app carries: the agent shows youeidos migrate --dry-run’s plan, migrates when you say yes, then runs the check and fixes what is left. Slash commands on the plugin’s page lists each with where it comes from, and adds your own: a name, a description, and the prompt it sends ($ARGUMENTStakes what follows the command), kept shared with the root or local. - Dictation. The microphone beside Send, or Start dictation (
⇧⌘D, Ctrl+Shift+D off a Mac, yours to change under Hot keys; pressed again it stops), opens a panel over the message box: pick the microphone, watch its level, talk as loosely as you like, and press Stop or Enter. What you said lands where the caret is, as text to edit; it is sent only when you send it. Esc or Cancel drops it. While it listens the message box takes no typing, so with focus in the chat Enter and Esc are the dictation’s, never Send or stopping the answer; anywhere else in the app they keep their own meaning, so you can move around and keep talking. Whisper writes it down in the page, offline after the first dictation, which downloads the speech model once for the whole computer (about 175 MB with ONNX Runtime on a GPU, about 105 MB without). Tidy with AI, off until you turn it on, has your agent take out filler words and false starts and fix the punctuation before it lands, in an agent of its own on the fastest model it offers (a Haiku for Claude Code), never the conversation’s; Use literal, or ⌘Z (Ctrl+Z), puts back what you said word for word. How it’s written holds your own instructions for it: tone, spellings, names. The Dictation section of the plugin’s page holds the same switches, the model to tidy on, and Hosted transcription with your own OpenAI key instead of Whisper in the page. - A commit message for Git. With the Git plugin on, Summarize in Source control and each auto save ask the AI Agent for a one-line commit message. It answers through an agent of its own, kept in no conversation, with no edit and no tool allowed, so a conversation in progress is neither waited on nor touched; when no answer comes, the auto save uses a plain message instead. Commit messages on the plugin’s page words what it is asked, the changes following; empty, one subject line in the imperative under 100 characters.
- Check for duplicates with AI. On a task not started yet (in the Backlog’s default status or a status of the board’s first column), Check for duplicates with AI sits above its properties, on its page and in its modal, while an agent is configured. Pressed, and only then, the task and the rest of the backlog go to an agent of its own, with no edit and no tool allowed, and the likely duplicates come back each with a reason: Link as duplicate or Link as related writes the link on the task as
eidos backlog linkdoes, and Not a duplicate keeps the pair out of every later check from either task, saying who dismissed it and when, with Undo. The last check is kept, so it is there when you come back; Check again replaces it and keeps every Not a duplicate. - AI Agent: Focus Chat (
⌃⌘I, Ctrl+Alt+I off a Mac, yours to change under Hot keys) shows the view and puts the caret in its message box; it is the Chat view’s one Focus command. AI Agent: Focus Chat Response puts the cursor on the latest reply, and the up and down arrows step from one message to the next. AI Agent: New conversation (⌥⌘N, Ctrl+Alt+N off a Mac) starts a new one there. - Several conversations run at once. Each has an agent process of its own, so starting, stopping, or leaving one never waits on another. A conversation goes on when you move to another or close the page, and shows its reply so far when you come back. Each shows where it stands in the list and beside its title: working, waiting for you (a permission it asks), done, or failed. One that needs you while you look elsewhere is said once, in a toast, and in the desktop’s own notification while the page is not in front (the browser asks once whether it may); the Chat tab counts them. Up to four agents run at once: past that, an idle one makes way, and with all four working a new message is refused and says so. An agent left idle for ten minutes is ended, and the conversation’s next message takes its session up again.
- The title switches conversations. With only one, the title is just its title, New conversation beside it. With others, the title opens on them, the pinned first, each with where it stands and when it last moved, and All conversations under them opens the whole list. The list holds every conversation, the latest to move first, each titled from its first message until you rename it, with when it last moved. Search finds one by its title or by what was said in it. A row’s menu opens, renames, pins, makes it local or shared, and deletes it (asked once); deleting the one shown opens the next in the list, and a new conversation only when none is left. Pinned conversations come first, in the order you drag them to; pins and their order are yours, kept in the root’s
local.yaml. A local conversation wears the laptop. - Conversations are shared with the root, so anyone on it can open and continue one, or local; an unsaved one’s Save asks which. A conversation continued after the agent restarts goes on in the agent’s own session, reloaded through ACP’s
session/loadwhere the agent offers it; otherwise a new session is told the turns so far, and nothing extra shows in the conversation.
Connecting the agent
Section titled “Connecting the agent”AI Agent does not bring an agent; it starts the one on your computer through that agent’s ACP adapter, fetched with npx the first time. So a machine needs three things: Node.js (which gives npx), the agent’s own sign-in, and a model the account can use.
- Codex signs in with
npx -y @openai/codex login(a ChatGPT account) or an OpenAI key inOPENAI_API_KEY, which the AI Agent hands to the adapter when nothing else is signed in. It reads its model from~/.codex/config.toml; amodel =line naming a model the account cannot use makes every answer an error. - Claude Code signs in with
/logininclaude(ornpx -y @anthropic-ai/claude-code).
The bar under the agent on the plugin’s page tests the agent picked, and picking one tests it: Node.js found, the agent started, signed in, and answering one short message, each step marked, with what to do for the step that failed and Copy details to send to whoever helps. The test runs an agent of its own, so a conversation in progress is not touched.
The persona
Section titled “The persona”By default the AI Agent answers in one voice: curious, plain, a little dry, fond of a good question and of a short answer. That is a voice and nothing more; the role contract in me.md and the instructions decide what it surfaces and who holds a decision. The plugin’s page offers that default voice, your own text, or none.
On disk
Section titled “On disk”.eidos/plugins/agent/local.yaml, local: theagent(claude-code,codex, orcustom),command(the ACP command to run; unset, the named agent’s adapter throughnpx, fetched on first use),persona_mode(default,own,off),persona(your own text),chat_zoom(the chat’s own zoom, in percent), and dictation’stranscription(localorhosted),dictation_tidy,dictation_instructions, anddictation_model. Never committed: the agent you talk to does not travel with the root.- In the folder Eidos keeps what belongs to no root (
~/Library/Application Support/eidosmdon a Mac,%APPDATA%\eidosmdon Windows,~/.config/eidosmdon Linux):models/, the speech model dictation downloaded once, shared by every root, andtranscription.yaml, your hosted transcription key, readable by you alone and never read back to the page. .eidos/plugins/agent/settings.yaml:commit_prompt, what Git’s commit message is asked with, shared with everyone in the root; and AI Agent as a user (as_user, on by default) with AI Agent takes actions as (acts_as): the user the AI Agent’s comments are signed as, by default the plugin’s own user AI Agent (@agent, holding the root’sagentrole when it has one), listed as the plugin’s on the Users page while the plugin is on and written to the root’s users the first time it is needed. Pick another user (say, Sammy) and the AI Agent signs as them; switch it off and the AI Agent comments as nobody, its comments refused. From a shell,eidos plugin set agent as_user offoreidos plugin set agent acts_as sammy. Let the agent change the framework (may_change_framework, off by default) decides whether@agentmay run aconfigure:command that writes; off, the command refuses and says where to turn it on. A root that marks no person an editor lets everyone, the agent too, whatever the setting. Only a framework editor turns it on..eidos/plugins/agent/conversations/<id>.yaml: a shared conversation, committed..eidos/plugins/agent/local/conversations/<id>.yaml: a local one, never leaving the machine. Each holds the messages, the context each carried as it was worded, the files an answer changed, and the agent’s session id..eidos/plugins/agent/duplicates.yaml: each task’s last duplicate check (the candidates, the agent’s reasons, when it ran) and every pair marked Not a duplicate, shared with the root.
From the shell
Section titled “From the shell”Nothing in the shell talks to the agent: asking the CLI to ask your agent, from your agent, is a loop with nothing in it. The page is the only surface for a conversation. Its settings are written from the shell as any plugin’s are:
eidos plugin set agent agent codex # the agent, local, in local.yamleidos plugin set agent command "my-agent --acp" # a command of your own that speaks ACPeidos plugin set agent agent --unset # back to Claude Code, the defaultThe composer’s custom slash commands are edited with eidos agent, as the Slash commands list on the plugin’s page edits them:
eidos agent commands # every command and where it comes from; --json for a scripteidos agent configure:command add review --prompt 'Review $ARGUMENTS for gaps' --description 'review what is open'eidos agent configure:command set review --rename critique # --prompt, --description; --local for a local oneeidos agent configure:command remove critique # --dry-run shows the change and writes nothingA command is shared with the root unless --local keeps it on this machine. A name the Chat view or a plugin already uses is refused, and so is one another custom command has. Only a framework editor writes the shared ones; your local ones are always yours to change.
What the check reports
Section titled “What the check reports”Nothing. Off or unconfigured, there is no process, nothing is sent anywhere, and the plugin’s page says which.