# Empryo Cells — task map for agents > A Cell is one JSON file (.empryo/morphs/.json) that extends the Empryo desktop app: panels, status chips, toolbar buttons, /commands, key chords, live feeds, triggers, and an agent layer (rules, lookups, guards, state). A cell can also BE the workspace: a canvas board takes the window in place of the chat, its lanes and columns filled from an API, a folder of the checkout (files://specs/*.md), a live socket (wss://) or the engine itself, and its cards start real agent runs. Each section link below returns JSON containing the exact reference text and citation URLs. Validate a file against the JSON Schema: https://empryo.com/morphs.schema.json · full page: https://empryo.com/docs/tools/morphs.md · search: https://empryo.com/api/docs/search?q=&scope=morphs ## Retrieval prompt Fetch https://empryo.com/docs/tools/morphs/llms.txt, pick the sections for the task, fetch each sectionUrl (fragments are citation anchors, not HTTP section selectors), then write the cell and check it against https://empryo.com/morphs.schema.json. Cite sections by their .md#anchor URL. ## Create a cell - [Work it directly](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=work-it-directly): A morph's panel is yours to use, not a row of buttons that write prompts. Every control has three ways to act, and the author picks per control: (~372 tokens) - [The agent layer › Example: a morph the agent works inside](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=example-a-morph-the-agent-works-inside): With this morph live, "look up PROJ-142" makes the agent call the lookup; finishing a ticket, it runs `cells set` with `done: 3` and the progress bar moves; `rm -rf` is refused with the reason; an edit under `infra/` parks the permission… (~325 tokens) - [Shapes](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=shapes): The domain is yours — these are shapes people have made, not a menu. The same morphs make: (~266 tokens) - [Example: the one-page work hub](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=example-the-one-page-work-hub): Tickets, pull requests, and docs in one panel, so the agent can work on a ticket without you switching apps. (~628 tokens) - [Manage](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=manage): **Cells & Morphs** lists every morph with its hooks, its state (live, off, or broken with the reason), and a switch. Search, filter by live/off/broken or by morph, delete with a two-step confirm. **Share** copies a morph's JSON. **Import… (~115 tokens) ## Surfaces (panels, chips, buttons, commands) - [The UI layer](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=the-ui-layer): An action may carry `layout`: `{ "sidebar": false, "map": false, "context": true, "terminal": false }` — a **Focus** button that arranges the window, only on the click. It may also carry `run` — the one control that starts work rather… (~899 tokens) - [Toolbar](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=toolbar): Up to six buttons. `label` is the tooltip. `glyph` is one of `sparkles zap bug rocket book git list bell chart globe shield wrench clock flag star terminal` or any Lucide icon name; an unknown glyph shows the morph mark. Each button has… (~73 tokens) - [Icons](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=icons): Any [Lucide](https://lucide.dev/icons) icon, by its kebab-case name: `music`, `git-pull-request`, `circle-check`, `triangle-alert`. Put `icon` on an action, a board row, a stat, a badge, a `kv` row, a `links` tile, a tab, the surface… (~142 tokens) - [Helper](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=helper): A morph that needs the machine — Spotify's track over AppleScript, a build's state, a sensor — declares the process that serves it: (~410 tokens) ## A board instead of the chat: canvas, grid, lanes, runs, slots - [The agent layer › Grid — putting things where you want them](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=grid-putting-things-where-you-want-them): Every other block says *what* to paint. `grid` says *where*: (~238 tokens) - [The agent layer › How a board arranges itself](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=how-a-board-arranges-itself): `layout` decides the shape, and the default is the one you want: (~201 tokens) - [The agent layer › The canvas — a board instead of the chat](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=the-canvas-a-board-instead-of-the-chat): `"place": "canvas"` gives a morph the whole window. Chat is not closed — it steps aside, and every tab keeps working behind the board. Press **Chat** (or `/canvas` again) to swap back. (~398 tokens) - [The agent layer › A pipeline, not just a list](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=a-pipeline-not-just-a-list): A board can have a second axis. Give the board `lanes` and every lane is a row of cards crossing the columns: the lane is the thing moving (a spec, a ticket, a release), the column is the stage it is in. `laneField` names the row field… (~301 tokens) - [The agent layer › Motion, when the movement is the point](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=motion-when-the-movement-is-the-point): A morph's own code (a `view` block) is handed the app's animation engine — the same one the app animates itself with, already loaded, nothing to install: (~292 tokens) - [The agent layer › Runs — cards that do the work](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=runs-cards-that-do-the-work): Any action, row action, or a kanban's `onMove` may carry a **run**: (~855 tokens) - [The agent layer › Slots — a morph instead of part of the app](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=slots-a-morph-instead-of-part-of-the-app): `place` puts a morph where the app left room for it. A **slot** goes further: the morph *becomes* that part of the window, and what the app would have drawn there is not drawn at all. (~258 tokens) ## Sources: a folder of files, a live socket, the engine - [The agent layer › A folder of files as the data](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=a-folder-of-files-as-the-data): A feed's `url` can be `files://specs/*.md` — files in the project you already have open. No network, no keys. One file per card: the `key: value` block at the top becomes the card's fields, the first `#` heading becomes its title, and… (~309 tokens) - [The agent layer › Live sources — the feed pushes, you don't poll](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=live-sources-the-feed-pushes-you-dont-poll): A feed's `url` can be `wss://…` (or `ws://127.0.0.1:…` for something running on your own machine). The app holds that connection open while the morph is on, and every message the server sends becomes rows straight away — no interval, no… (~394 tokens) - [The agent layer › The engine as a source, and buttons that act](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=the-engine-as-a-source-and-buttons-that-act): A pulse's `url` may read Empryo itself: `engine://git/changes`, `git/branches`, `git/log`, `worktrees`, `diff/changes`, `sessions/recent`, `memory/recent`, `review/ledger`, `agents/background`, `agents/custom`, `tasks/open`,… (~437 tokens) - [The agent layer › Naming the facts a row carries](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=naming-the-facts-a-row-carries): A `map` key the row model knows (`text`, `detail`, `badge`, `group`, `tone`, `href`, `id`, `desk`, `tab`, `image`, `attach`, `icon`, `prompt`) fills that part of the card. **Any other name is a fact carried on the row** — reachable as… (~237 tokens) ## Blocks and backdrops - [Blocks](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=blocks): `stats`, `progress`, `badges`, `divider`, and: (~1019 tokens) - [Blocks › Views — the free mode](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=views-the-free-mode): The schema is deliberately small; a `view` block is where everything it cannot say goes. It works like module federation: the morph ships an ES module, the app loads it and renders the component it returns **inside the surface** — same… (~1237 tokens) - [Blocks › Views — the free mode › Intents — hands for views](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=intents-hands-for-views): An intent is an action declared once by name at the top of the file (≤16): the same verbs a button has — `call`, `run`, `desk`, `open`, `state`, `prompt`/`send`, `href`, `copy` — with `label` defaulting to the name. A view invokes one… (~701 tokens) - [Blocks › Nothing is enforced](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=nothing-is-enforced): Every piece of app chrome around a surface is the morph's to keep or drop. `"chrome": "plain"` drops the card frame; `"header": false` drops the header (the morph mark, eyebrow, refresh and fold — and on a canvas the app's own header with… (~170 tokens) - [Blocks › Backdrops](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=backdrops): `surface.backdrop` is an image (https, or `http://127.0.0.1`) or a template that resolves to one: `"{{pulses.np.rows.0.image}}"`. The app paints it blurred and dimmed behind the panel, drifting slowly, and crossfades to the next picture… (~125 tokens) ## Settings, vars, where a cell lives - [Settings, conditions, and where a morph lives](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=settings-conditions-and-where-a-morph-lives): **Settings.** A morph may declare `vars` — its parameters. `{{var:HOST}}` works anywhere in the file: a URL, a header, a prompt, a row template. Your values are typed once in Cells & Morphs and kept out of the file, so one shared morph… (~745 tokens) - [The agent layer › Which sessions morphs reach](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=which-sessions-morphs-reach): By default a morph reaches the agent **only in morph mode** — the dedicated Cellwright tab that builds morphs. An ordinary coding session carries no `cells` tool, no morph instructions, no board context: the morph is your UI, not the… (~110 tokens) - [The agent layer › Signed morphs](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=signed-morphs): A morph may carry an Ed25519 `signature` over its canonical JSON (everything but `signature`, `source`, `enabled`, `state`). The showcase shows **Signed by Empryo** for a key Empryo ships, **Signed · key …** for any other, **Signature… (~116 tokens) - [The agent layer › Reach](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=reach): Every morph shows its **reach** before you enable it, computed from the file so a morph cannot under-report: the hosts it talks to, whether it gives the agent rules, how many lookups it exposes, how many guards it sets, whether the agent… (~96 tokens) ## Pulses (live feeds) and templates - [Pulses](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=pulses): A pulse is a URL, a heartbeat, a root path, and a map. (~358 tokens) - [Templates](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=templates): These fields may hold `{{holes}}`: `status.text`, `surface.body`, stats `value` and `hint`, progress `hint`, `text` blocks, `kv` values. (~98 tokens) ## Triggers (events) - [Triggers](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=triggers): Holes: `{{name}}` and `{{tab}}` always. `{{cost}}`, `{{duration}}`, `{{files}}`, `{{tools}}`, `{{steps}}` on `turn.done`; `{{error}}` on `turn.failed` / `turn.stopped` / `error`; `{{tool}}`, `{{ok}}`, `{{summary}}` on `tool.done`;… (~866 tokens) ## The agent layer: instructions, lookups, guards, state - [The agent layer](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=the-agent-layer): None of this is a hook. A hook is a shell command that observes or vetoes the agent. A morph gives the agent capabilities and a shared, visible workspace. Guards are the one overlap, and they stay data: no shell, no rewriting a call. (~270 tokens) - [The agent layer › The agent layer needs its own yes](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=the-agent-layer-needs-its-own-yes): Enabling a morph turns its UI on. Its agent layer — instructions, lookups, guards — is **held** until you approve it in Cells & Morphs, where you read exactly what it declares. The approval records a hash of that layer on your machine,… (~241 tokens) - [The agent layer › Hidden from the agent](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=hidden-from-the-agent): Any morph can be hidden from the agent from its card in Cells & Morphs — **Agent access → hidden**. A hidden morph still paints (its board, chip, buttons, popups all work), but the agent cannot see it at all: not in `cells list`, no rows,… (~274 tokens) - [The agent layer › Desks — one click from a board row to its own tab](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=desks-one-click-from-a-board-row-to-its-own-tab): The research is old and consistent: switching tasks leaves attention behind (Leroy 2009), a short ready-to-resume note when you leave cuts the cost of coming back (Leroy & Glomb 2018), and only one programmer in ten resumes editing within… (~304 tokens) - [The agent layer › Credentials](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=credentials): A pulse or lookup may send headers: `"headers": { "authorization": "Bearer {{secret:JIRA_TOKEN}}" }`. `{{secret:NAME}}` reads Empryo's key store (`/keys`), `{{env:NAME}}` the environment. Values are filled on the sidecar at request time… (~384 tokens) - [The agent layer › Instructions, per mode](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=instructions-per-mode): `instructions` is normally one line the agent always reads (it arrives on the wire as `instructions`, or as `instructionsByMode` when you split it). It can also be written per mode — `{ "plan": "…", "architect": "…", "*": "…" }` — so a… (~116 tokens) - [The agent layer › Organisation policy](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=organisation-policy): In the **global** config (`~/.empryo/config.json`, never a repo's): `"cells": { "requireSigned": "official" | "trusted" | "any", "trustedKeys": [""], "directories": ["https://git.example/cells/index.json"],… (~132 tokens) - [The agent layer › What the agent is holding](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=what-the-agent-is-holding): When you ask for a morph, the agent that answers is the **Cellwright** — a dedicated agent, not the coding one wearing a hat. Its whole toolbelt, so you know what it can and cannot do while it builds: (~280 tokens) - [The agent layer › Build your own picker](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=build-your-own-picker): When the app's own control is a menu a morph cannot reach, build the picker instead of linking at it. Three parts you already have: (~211 tokens) - [The agent layer › The agent drives its own work](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=the-agent-drives-its-own-work): Beyond reading (`debug`) and looking (`shot`), the agent has hands and ears on a live morph: `press` runs a control exactly as a click would — an intent by name, a surface action or button block by label, a row by its text, `" ›… (~210 tokens) - [The agent layer › The agent looks at its own work](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=the-agent-looks-at-its-own-work): Two questions, two answers. `cells debug ` says what the morph **is** — the validated structure, what dropped, which feed is empty. `cells shot ` says what it **looks like**: the app paints the morph and hands the agent the… (~136 tokens) - [The agent layer › The agent checks its own work](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=the-agent-checks-its-own-work): `cells debug ` returns the **validated wire** of a morph — what the renderer will actually paint, not the JSON that was written: its place, the block tree, a kanban's columns with the number of cards in each (plus any row group… (~128 tokens) - [The agent layer › The agent opens desks too](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=the-agent-opens-desks-too): `cells` has a `desk` action: "let's work on PROJ-142" → the agent opens (or returns to) that row's tab for you. `engine://desks` lists every tab bound to a row (title, working or idle, tab) — a "where was I" morph is one pulse. (~57 tokens) - [The agent layer › The engine pushes too](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=the-engine-pushes-too): An `engine://` pulse no longer waits for its beat. The moment the engine announces something a feed reads — a turn starts or ends (`tabs/open`, `desks`, `attention`, `usage/models`, `sessions/recent`), a background agent moves… (~244 tokens) - [The agent layer › Every host](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=every-host): The desktop draws a morph's surfaces; the agent layer — the `cells` tool, the morph's instructions, its lookups, its guards — is the same in the TUI and in `--headless` runs. `/cells` in the TUI lists morphs, approves or revokes an agent… (~104 tokens) - [The agent layer › Where morphs live, and sharing](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=where-morphs-live-and-sharing): A new morph is **yours in every repo by default**: `~/.empryo/morphs/*.json` (the showcase shows "every project" beside it). A morph that is about one repository — its board, its tests, its deploys — lives in that repo's… (~308 tokens) - [The agent layer › What reaches the model](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=what-reaches-the-model): Pulse rows are built from `map` templates: only the fields the morph named leave the payload. Lookups do the same with `map`, or with `pick` — a list of dot paths; only those travel. Raw JSON is the fallback when neither is set, capped at… (~105 tokens) ## Limits - [Limits](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=limits): The loader clamps long strings with an ellipsis, drops extras, and drops one broken block, row, action, or pulse. The morph stays. (~489 tokens) ## Everything else - [Try it in five minutes](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=try-it-in-five-minutes) (~167 tokens) - [Template holes and filters](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=template-holes-and-filters) (~318 tokens) - [How morphs compare](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=how-morphs-compare) (~785 tokens) - [What a morph cannot do](https://empryo.com/api/docs/section?page=tools%2Fmorphs&anchor=what-a-morph-cannot-do) (~174 tokens) ## Examples - [Blog: Morphs and Cells](https://empryo.com/blog/morphs-and-cells.md): the why, with screenshots - Starter cells: the public directory in the Empryo repo (Start from… → Directory in the app)