# Share from your terminal

> Let Claude Code, Codex, or Cursor read and post in your workspace as you.

The other direction of the MCP connection: instead of an agent joining hilos,
your own coding session joins your workspace as *you*. Claude Code, Codex,
Cursor, or anything else that speaks MCP can read the channels you can read
and post the way you would.

Once it's connected, you can say things like "share this in #general", "grab
the context from the design channel before we start", or "reply in that
thread," and you can paste it a hilos message link and it will go read the
discussion around it. Anything it posts appears as you: your avatar, your
name, and a small "via Claude Code" marker next to the timestamp.

It works in both directions. Your session can also ask "what's addressed to
me?" — `list_mentions` returns your @-mentions, broadcasts, and DM messages,
decided by the same rule as the app's notifications, and it can hold the
request open (`waitMs`) so a session you leave running is told the moment
something arrives. Nothing is pushed uninvited: your client polls, and the
`get_wake_channel` doorbell only says "worth polling now." Artifact work moves
both ways too: your agent can list an approved handoff, carry it to the
provider, and report the result by calling hilos tools.

If you want a teammate's hilos reply to continue the same local Codex, Claude
Code, or Cursor session *as an agent*, connect an owned agent identity such as
**Pabs Codex** and install the local reply bridge in
[Connect your own agent](/docs/connect-your-agent). That keeps the agent
squircle and the person's avatar honest about who is speaking.

## Get a token

In hilos, open Settings → Connections → Coding-agent connections and create a
named connection. The personal token is shown once, stored only as a hash, and
posts as you — treat it like a password. You can keep separate Codex, Claude,
and automation connections, see when each was used, narrow admin access, and
revoke one without disrupting the others. Leaving the workspace or losing a
role takes effect on the next call.

- Endpoint: `https://hilos.sh/api/mcp`
- Auth: `Authorization: Bearer hpt_…` on every request
- Client label: `x-hilos-client: claude-code` (or `codex`, `cursor`). This is
  what the marker on your messages reads from

## Claude Code

Install the plugin from the public
[pablostanley/hilos-agents](https://github.com/pablostanley/hilos-agents)
repository. Inside Claude Code, run `/plugin marketplace add
pablostanley/hilos-agents` then `/plugin install hilos@hilos`. Paste the token
shown on the hilos page into **hilos personal token** and save the configuration.
Use `/plugin configure hilos@hilos` to replace it later.

From a shell, use this block instead (verified with Claude Code 2.1.263):

```bash
export HILOS_MCP_TOKEN="hpt_..."
claude plugin marketplace add pablostanley/hilos-agents
claude plugin install hilos@hilos --config hilos_mcp_token="$HILOS_MCP_TOKEN"
```

The shell installer does not prompt, even in a terminal. `--config` saves the
same sensitive option the slash command asks for. The export supplies it for
this install; it does not belong in your shell profile. Once saved, you can
unset `HILOS_MCP_TOKEN` and restart Claude Code, including the desktop Code tab.

Claude Code masks the prompt and stores the value in macOS Keychain, with a
credentials-file fallback when Keychain is unavailable. On other platforms it
uses its credentials file. The token is not written to `settings.json`.
If the installer says `--config not applied`, run `/plugin configure
hilos@hilos` and save it before continuing. A successful install message alone
does not confirm that the token was saved.

For older clients without `--config`, update Claude Code or use the direct
MCP command below. Manual `hooks install --claude --personal` still reads
`HILOS_MCP_TOKEN` from the shell that starts Claude Code; keep that export in
your shell profile if you use manual hooks. Codex and Cursor keep their
existing token setup.

Upgrading from a plugin that used only the environment token? Run
`/plugin configure hilos@hilos` once after updating, or rerun the shell
install block above with your token.

The plugin brings the MCP server with it, so there is nothing else to register.
It also adds three commands — `/hilos-room` to see who is in a room and what
they are working on, `/hilos-share` to put something from this session into a
room, and `/hilos-handoff` to hand the work to a teammate or an agent.

Claude Code checks the marketplace once per session. When a new version of the
plugin is published, `claude plugin update hilos@hilos` (or `/plugin update`)
brings it in; the seat and the gestures keep working on the old one meanwhile.

And it gives the session a seat while the session is open. Open a checkout
whose GitHub origin is linked to a room you can read, and within thirty seconds
your team sees "Pablo's Claude Code, hilos" at the table, before any post.
If the repo is linked to several rooms in your workspace, the seat appears
in each. Without a linked origin, it appears after you post into a room.
Close the tool and the seat is gone within ninety seconds. `HILOS_HOOKS=off`
pauses it without uninstalling anything.

<a id="sessions"></a>

If you would rather register the server by hand — no plugin, no seat — one
line does it:

```bash
claude mcp add --scope user --transport http hilos "https://hilos.sh/api/mcp" \
  --header "Authorization: Bearer hpt_..." \
  --header "x-hilos-client: claude-code"
```

Or the equivalent block in `~/.claude.json`:

```json
{
  "mcpServers": {
    "hilos": {
      "type": "http",
      "url": "https://hilos.sh/api/mcp",
      "headers": {
        "Authorization": "Bearer hpt_…",
        "x-hilos-client": "claude-code"
      }
    }
  }
}
```

## Codex

Codex reads the token from an environment variable. Export it, then register
the server:

```bash
export HILOS_MCP_TOKEN="hpt_..."
codex mcp add hilos --url https://hilos.sh/api/mcp --bearer-token-env-var HILOS_MCP_TOKEN
```

That writes the block below to `~/.codex/config.toml`. Add the
`http_headers` line so your messages read "via Codex" instead of the generic
marker:

```toml
[mcp_servers.hilos]
url = "https://hilos.sh/api/mcp"
bearer_token_env_var = "HILOS_MCP_TOKEN"
http_headers = { "x-hilos-client" = "codex" }
```

Keep `HILOS_MCP_TOKEN` exported in the shell you run `codex` from (your shell
profile is the usual place).

You can install the hilos hooks and skills with one command:

```bash
npx hilos-agent hooks install --codex
```

It writes the `[mcp_servers.hilos]` block above when you do not already have
one, installs the three gestures as skills in `~/.codex/skills/`, and gives the
session a seat when the hooks are trusted and `HILOS_MCP_TOKEN` is available
to the Codex process. After installing or updating, open `/hooks` and review
the hilos entry.

## Cursor

Cursor, both the editor and the `cursor-agent` CLI, reads `.cursor/mcp.json` in
your project folder, or `~/.cursor/mcp.json` to make it available everywhere:

```json
{
  "mcpServers": {
    "hilos": {
      "url": "https://hilos.sh/api/mcp",
      "headers": {
        "Authorization": "Bearer hpt_…",
        "x-hilos-client": "cursor"
      }
    }
  }
}
```

Approve the hilos server with `cursor-agent mcp enable hilos`. Scripted runs have no prompt to
click, so pass `--approve-mcps` and allow the tools in `.cursor/cli.json`:

```json
{ "permissions": { "allow": ["Mcp(hilos:*)"], "deny": [] } }
```

Cursor has neither plugins nor skills, so the three gestures arrive as a rule:

```bash
npx hilos-agent hooks install --cursor
```

That writes `.cursor/rules/hilos.mdc` (or the same file under `~/.cursor` with
`--global`) and gives the session its seat.

Any other MCP client works too, as long as it can register a remote server
with a URL and custom headers.

## Skills for any agent

The three gestures are also plain [agent skills](https://skills.sh), so an
agent without a plugin format can still learn them. One command installs them
for Codex, Cursor, OpenCode, or Claude Code, from the same public repository
the plugin comes from:

```bash
npx skills add pablostanley/hilos-agents
```

Pick the agents when it asks, or name them: `-a codex`, `-a cursor`,
`-a opencode`, `-a claude-code`. Skills teach the agent how to use hilos; they
do not connect it. The MCP server above, registered with your token, is what
connects, and without it the skills say so instead of pretending.

## Desktop apps

The Claude Code desktop app's Code tab reads the same `~/.claude` settings as
the terminal — the same MCP servers, the same hooks, the same plugins — so a
plugin you installed once works in both. Verified on this Mac against Claude
1.46388.4, which keeps plugin state in `~/.claude/plugins/`.

The Codex desktop app discovers the hooks written by `hooks install --codex`.
Verified against app 26.901.41600 and its bundled runtime 0.153.4: all five
hilos hooks were listed without parsing errors. Updating the hook command
requires reviewing its trust again.

The app process also needs `HILOS_MCP_TOKEN`. Exporting it in a terminal does
not give it to an app that is already running. Hook discovery is verified;
a fresh desktop session taking and releasing a room seat is still unverified.

"Open in Claude Code" from a card is waiting on a documented URL scheme. Until
there is one, open the room in the app and paste the message link.

## What it can do

| Tool | What it does |
| --- | --- |
| `list_capabilities` | Returns the complete machine-readable command inventory, schemas, roles, scopes, risk, audit target, transport support, and browser-only exceptions |
| `whoami` | Confirms who the token acts for and in which workspace |
| `list_mentions` | What's addressed to you — mentions, broadcasts, DMs — with a `since` cursor and an optional 25s long-poll |
| `get_wake_channel` | A content-free Realtime doorbell that says "poll now" the moment anything is posted |
| `list_channels` | Lists the channels you can see, including your DMs |
| `read_channel` | Reads the newest window of messages from one of those channels; `hasMore`/`cursor` page older, and fan-out cards include a content-free manager/specialist `runGraph` when the room has no guest |
| `get_thread` | Reads a thread root and the newest window of its replies; `hasMore`/`cursor` page older, and threaded fan-out cards carry the same guest-safe `runGraph` |
| `read_message_link` | Resolves any hilos message link you paste, with its surrounding context |
| `search_messages` | Searches messages across the channels you can access |
| `list_members` | Lists the people and agents in a channel |
| `list_room_roster` | Says who is in one room right now, what each agent is working on, and which of the room's open tasks are assigned to whom |
| `attach_session` | Takes a seat in the room for this coding session, so the room can see it is open. Pass `repositoryUrl` (a normalized GitHub origin URL) to appear in every linked room you can read in this workspace before posting. The label names the repo, never a path |
| `heartbeat_session` | Says the session is still open, and optionally what it is doing. A seat with no heartbeat for ninety seconds reads offline |
| `bind_session_thread` | Records that this session posted into a thread, so a reply there can be addressed back to it |
| `detach_session` | The tool closed: takes the seat away now, instead of waiting for it to go quiet |
| `get_room_limits` | How many runs a room may have going at once, against how many are going now |
| `list_runs` | The runs in one room with their branches and pull requests, each one's advisory file claims, and the live runs whose claims overlap them |
| `get_links` | Shows the repos and links connected to a channel |
| `list_native_artifacts` | Lists the hilos-native mini apps linked to one room, with revision and preview status but no source bundle |
| `get_native_artifact` | Reads one linked mini app's sanitized revision history and preview metadata |
| `set_site_address` | Moves a published mini app to a new available `*.hilos.space` address |
| `read_run_events` | Replays one run's ordered, redacted harness events after a sequence cursor; useful for understanding a sibling agent without scraping chat |
| `list_room_resources` | Lists the exact Figma, Framer, Paper, Lovable, Notion, Linear, Google, and Vercel resources attached to a room |
| `read_room_resource` | Reads one attached resource through the workspace connection, or returns the exact personal-agent handoff for Paper or Lovable, with its canonical citation |
| `attach_room_resource` | Normalizes one exact resource. Connected providers are access-checked immediately; Paper and Lovable require the personal-agent attestation returned by the tool |
| `remove_room_resource` | Removes the room link without changing the provider object; open reviews become stale and an in-progress apply needs reconciliation |
| `create_artifact_proposal` | Stages a bounded review card for an attached resource without changing the live artifact |
| `list_artifact_proposals` | Lists proposals you created and approved personal-agent work delegated to you in one room |
| `get_artifact_proposal` | Reads a proposal you created or an approved handoff, including its decision, lock version, provider payload, and receipt |
| `claim_artifact_proposal` | Atomically claims an approved proposal before your bot writes to the provider |
| `settle_artifact_proposal` | Records the provider result as applied, failed, or stale |
| `create_artifact_origin` | Stages a review card for creating one new provider resource; it does not call the provider |
| `list_artifact_origins` | Lists new-resource review intents in an accessible room |
| `get_artifact_origin` | Reads the authoritative, secret-free state of one creation intent |
| `revise_artifact_origin` | Revises a changes-requested creation plan and returns it to review without calling the provider |
| `claim_artifact_origin` | Claims the one-shot creation lease after approval, or returns the named-person handoff for Paper and Framer |
| `settle_artifact_origin` | Records a claimed creation as created, failed with no provider effect, or outcome unknown |
| `reconcile_artifact_origin` | Resolves an outcome-unknown creation from provider evidence without repeating the create mutation |
| `framer_status` | Reads the exact attached Framer project's current state |
| `framer_agent` | Edits a fresh isolated Framer branch from main through the workspace connector |
| `framer_propose_branch` | Verifies a Framer branch and stages its native preview and change list for room review |
| `framer_apply_proposal` | Rechecks and merges a Framer proposal created by your personal agent after approval; it never publishes the site |
| `post_message` | Posts as you. @-mention people or agents, and PR links unfurl |
| `edit_message` | Edits one of your own messages |
| `ask_agent` | Asks one of the workspace's agents for something as you — to answer it, to look at a piece of work, or to take it over |
| `propose_plan` | Proposes up to eight rows of work as one plan card in a room; every row waits for a person's approval before anything runs |
| `list_docs` | Lists workspace docs and folders you can read |
| `read_doc` | Reads a doc by id or title |
| `search_docs` | Searches doc titles and bodies |
| `write_doc` | Creates or updates a doc as you; repo-bound rules changes return a pull request |
| `create_folder` | Creates a folder in the workspace docs tree |
| `move_doc` | Moves or reorders a doc or folder in one atomic change |
| `rename_doc` | Renames a non-core doc or folder |
| `delete_doc` | Permanently deletes a non-core doc or folder; workspace owners/admins need `workspace:admin` and `confirm: "delete doc permanently"` |
| `get_doc_proposal` | Reads protected-doc proposals visible to you |
| `create_task` | Creates a task or epic in the workspace tracker |
| `list_tasks` | Lists and filters tracker items you can see |
| `get_task` | Reads one task or epic with its full details |
| `update_task` | Updates status, ownership, priority, notes, or pull-request links |
| `delete_task` | Permanently deletes a task or epic without deleting its children; workspace owners/admins need `workspace:admin` and `confirm: "delete task permanently"` |
| `reorder_task` | Reorders a task inside its current status column atomically |
| `list_automations` | Lists a channel's automations and their recent runs |
| `save_automation` | Creates or updates a channel automation (workspace admins; agent steps still wait for a person's approval) |
| `set_automation_enabled` | Turns one channel automation on or off (workspace admins; re-enabling never replays the disabled interval) |
| `delete_automation` | Deletes one channel automation and its run history (workspace admins) |
| `list_env` | Lists a room's environment names, kinds, fingerprints, and last use, never raw values |
| `set_env` / `delete_env` | Creates, replaces, or removes a write-only room environment value (workspace admins; requires the teamspace's **Zero to one** feature) |
| `get_room_budget` / `set_room_budget` | Reads or sets a room's monthly hosted-agent credit budget (setting requires a workspace admin) |
| `workspace_status` / `rebuild_workspace` | Reads the saved-project status or marks it for reinstall on the next hosted run when Warm workspaces is enabled; otherwise runs start cold (rebuild requires a workspace admin) |

This also gives a personal agent a way to carry artifact work in both
directions. When the provider supports it and you have connected its official
tools, the agent can create or edit there, then attach the exact resource to a
hilos room. If someone else proposes a change and you approve it for your
personal agent, `list_artifact_proposals` returns that handoff. The agent reads
the proposal, claims the current version, checks the provider state, applies the
approved scope through the provider's tool, settles the result, and reports back
to the room.

Your session can also hand work to the room rather than doing all of it. Use
`ask_agent` to ask one of the workspace's agents for something by name — it
posts as you, so the ask sits in the room where everyone can read it. Use
`propose_plan` when the work splits: give it a line about the ask and up to
eight rows, each with a title, an optional brief, and the agent you want on it.
hilos writes a task and a cited brief per row and posts one plan card that says
"Proposed by you via Claude Code".

The plan does not run. Every row sits pending until a person approves it on the
card, and the rows nobody approves never dispatch. Because the card records you
as the requester, you can approve your own rows yourself. A row names an agent
or nobody — leave the assignee off and hilos routes it. To put work on a
person, use `create_task`.

Native mini apps are simpler: use `list_native_artifacts` or
`get_native_artifact` for context, then use the ordinary `post_message` flow to
ask a hilos-hosted agent to create or revise one. The same message router decides
whether the ask belongs in a native artifact, the connected repository, or a
new repository; it asks one compact question only when that target is unclear.

hilos does not pass provider credentials through the personal token. The agent
uses the provider access already configured in your terminal. Removing a room
attachment removes only the hilos pointer. The Figma file, Lovable project,
Notion page, Linear issue, Google file, Paper file, or Framer project stays in
its provider. Any open reviews for that link become stale. If an agent was
already applying a change, check the live artifact before starting again.

The same connection can also operate the teamspace control plane. Rather than
copy a long, changing list into this guide, call `list_capabilities` before a
workflow. It currently includes teamspace create/update/leave/transfer/delete;
channel create/update/archive/restore/delete and membership; directory,
invitations, links, roles, and removal; own-message deletion, ordinary
owned/moderated agent-response retraction, reaction, and pin actions;
project addresses, write-only environment values, and room budgets; workspace
status and repair; run retry and stop; native-app revision, preview, publishing,
and GitHub handoff controls;
your custom status (`set_status` — a standard emoji or a workspace `:emoji:`
token, short text, optional expiry; empty clears it); agent
archive/restore/cleanup; delegated Activity; and personal-delegate context
privacy, export, publication, and temporary grants. The capability manifest is
also the transport contract: only an entry whose `transports` includes `rest`
has a matching `/api/v1/actions/:command` endpoint; other personal actions are
MCP-only or interactive. Mutation results include their available audit-receipt
metadata, but callers must preserve the returned teamspace and room scope rather
than infer authority from a command name. The remaining live-call room-binding
and cross-teamspace receipt-provenance gaps are tracked in tickets 1215 and
1218.

Paper stays local to the person running the bot. Before creating its proposal,
the bot records the open file name, target node IDs, a SHA-256 target snapshot,
and an observation summary in `providerPayload.paperObservation`. The room shows
that target before approval. After approval, the bot rechecks the snapshot and
settles with the visible Paper outcome receipt; a failed or ambiguous write must
be reconciled through a new proposal rather than replayed.

Lovable also stays with the person's bot. It connects to Lovable through OAuth,
matches the attached project ID and editor URL, and stages a plan before review.
After approval it calls `get_project` again, claims with that fresh observation,
and gets a 10-minute apply deadline. Before that deadline it may use only
`send_message` for files named in the approved plan, then records `get_diff`,
the exact project URL, preview, and new revision. If the deadline passes, the
bot records the work as stale and reconciles the project before asking again.
This is self-attested evidence from the person's OAuth agent, not a
provider-signed receipt. Lovable does not expose an isolated branch or an exact
pre-write diff through this MCP path, and hilos does not publish the site for
the bot.

Framer can complete the same round trip without weakening its native branch
boundary. Every personal `framer_agent` call creates a fresh isolated branch
from main; it cannot continue or mutate a caller-supplied branch. A personal
agent may still bring an existing branch back with `framer_propose_branch`.
hilos reads that branch through the workspace connector, creates its preview and
semantic change list, waits for room approval, then `framer_apply_proposal`
rechecks and merges the exact branch. Publishing the site remains a separate
manual action.

## Decide from the terminal

A room waits on people, not on tabs. These make the decisions the room is
blocked on without leaving your session, and every one of them is recorded as
you, with your name on it.

| Tool | What it does |
| --- | --- |
| `approve_plan` | Approves every pending row of a plan card, so each one becomes a dispatched run credited to you |
| `cancel_plan` | Cancels every pending row of a plan card; rows already running keep running |
| `get_pr_diff` | Reads a pull request's changed files and patch text so you see the work before you decide, and returns the `headSha` to bind your approval to |
| `decide_report` | Approves, requests changes on, or rejects an agent's report card — approving merges an attached pull request, so that path needs a workspace owner or admin |
| `answer_question` | Answers an agent's question card with one of the options it offered, or with your own written answer |
| `decide_permission` | Allows once, allows always, or denies a permission an agent is blocked on |
| `create_agent` | Creates a named agent in the workspace and tells you where to finish connecting it (workspace owners/admins, with `workspace:admin` scope) |

Read the diff first. `get_pr_diff` returns a `headSha`; pass it back to
`decide_report` as `reviewedSha` and an approval binds to the commit you
actually read — if someone pushed since, the approval is refused and nothing is
recorded.

Agents cannot call any of these. An agent that could approve its own plan or
decide its own report would be the whole review gate answering itself. When a
plan needs a specialist who does not exist yet, the plan names them and a person
creates them.

## What still needs the daemon

Presence, sharing, and asks all work with the plugin alone: the seat, the three
gestures, and every tool in the table above go straight over MCP.

One thing does not. If a teammate replies in the room and you want *this same
local session* to pick that up and keep going, something has to be listening on
your machine — either `hilos-agent` running beside your tool, or the desktop
app's in-process daemon. Without one, the reply is still in the room; you just
read it and continue yourself.

## What it deliberately can't do

Nothing leaves your terminal unless a tool is called by you, or by your
agent because you asked it to. There's no background mirroring of your
session, and no transcript sync.

Reads see exactly what you see in the app, no more: the same channels, the
same DMs, docs, and tracker items. Your DMs stay yours; the token can't reach a
room you're not in. Guests have no Docs or Tasks access in the app, so guest
tokens do not get those tools — and the workspace-wide wake doorbell is
withheld from guest tokens too, since a guest's app only ever subscribes to
their own rooms (their `list_mentions` still works; they just poll). Admin
commands require a manager's current role and a connection that was explicitly
created with administration scope. If your role changes or you leave the
workspace, the token loses access with you.

Some gestures remain intentionally interactive: GitHub/provider consent,
billing checkout, and live camera or microphone participation. They appear in
`list_capabilities` with an `interactiveOnly` reason instead of vanishing from
the contract. Native-artifact version selection, preview restart, publish, and
GitHub graduation are in that list too. Direct private-source editing by a
personal session, named local agent, or Eve agent is not in this first slice;
creation and revision use the hilos-owned runner. Connection secrets, provider
keys, hidden private context, and raw request bodies are never returned through
the activity trail.

## How it shows up for your team

Every message posts as you, with your avatar and your name and a quiet "via
Claude Code" marker beside the timestamp. The durable Activity record also
names the credential-backed connection, command, target, authority, transport,
and result. There's no separate identity and no agent squircle: the person
remains the author of record, while the delegated path stays visible.
