### Install and start Tailscale Source: https://isomux.com/docs/self-hosted Installs Tailscale on the server, laptop, and phone, then brings the device up on the tailnet. After claiming the office and enabling External access, the office is reachable from any tailnet device at http://my-mac-mini:4000. ```bash curl -fsSL https://tailscale.com/install.sh | sh sudo tailscale up ``` -------------------------------- ### Run Isomux VPS installer (root shell and cloud-init) Source: https://isomux.com/docs/self-hosted Run the Isomux installer as root on a fresh Ubuntu 24.04 server. The first form is for an interactive root shell; the second is for cloud-init user data. Both download deploy/install.sh and run it with DOMAIN set to your office domain. The installer prints a single-use owner invite link (or writes it to /var/lib/isomux/invite-url when output is not a terminal) and sets up the full self-hosted office. ```bash ( installer=$(mktemp) || exit trap 'rm -f "$installer"' EXIT curl -fsSL https://raw.githubusercontent.com/nmamano/isomux/main/deploy/install.sh -o "$installer" && DOMAIN=office.example.com bash "$installer" ) ``` ```bash #!/bin/bash set -e installer=$(mktemp) trap 'rm -f "$installer"' EXIT curl -fsSL https://raw.githubusercontent.com/nmamano/isomux/main/deploy/install.sh -o "$installer" DOMAIN=office.example.com bash "$installer" ``` -------------------------------- ### Set up OOM protection on a VPS with isomux-oom-protect Source: https://isomux.com/docs/self-hosted Run the OOM protection setup on a VPS. The first command prints what would change without applying anything; the second applies the changes. Safe on a live office: only earlyoom is restarted, existing swap is left untouched, and the script prints the commands it runs. ```bash sudo isomux-oom-protect --dry-run # print what would change ``` ```bash sudo isomux-oom-protect ``` -------------------------------- ### Set office URL and token, then list agents with curl Source: https://isomux.com/docs/developer-api Sets the office URL and API token in shell variables, then calls GET /agents with a Bearer token to list live agents in accessible rooms, including the lobby agent. The token is shown only once when created in Settings → You → API tokens. ```bash OFFICE_URL="https://office.example.com" TOKEN="paste-the-token-shown-once" curl -s "$OFFICE_URL/agents" \ -H "Authorization: Bearer $TOKEN" ``` -------------------------------- ### GET /agents Source: https://isomux.com/docs/developer-api Lists the live agents in rooms you can access, plus the lobby agent. Requires a bearer token. ```APIDOC ## [GET] /agents ### Description Lists the live agents in rooms you can access, plus the lobby agent. ### Method GET ### Endpoint /agents ### Parameters #### Headers - **Authorization** (string) - Required - Bearer token for authentication. ### Response #### Success Response (200) - **agents** (array) - List of agents with fields: `id`, `room`, `roomName`, `roomId`. #### Response Example ```json { "agents": [ { "id": "agent-123", "room": null, "roomName": "Lobby", "roomId": "lobby" } ] } ``` ``` -------------------------------- ### Update isomux to a specific release Source: https://isomux.com/docs/self-hosted Apply a new release over SSH as root, using a tag from the releases page. Installs system dependencies, rebuilds, snapshots office state, and restarts the service, interrupting running agents. Downgrading requires --allow-downgrade. ```bash isomux-update v2026.7.19 ``` -------------------------------- ### Add provider API keys in Individual connections Source: https://isomux.com/docs/access-and-invites Add provider API keys under Settings → You → Individual connections. The keys are stored in managed files under ~/.isomux/ and personal variables override office-wide variables when an agent starts or resumes a conversation. ```plaintext ANTHROPIC_API_KEY=sk-ant-... OPENAI_API_KEY=sk-... OPENCODE_API_KEY=sk-... ``` -------------------------------- ### Enable Tailscale HTTPS with tailscale serve Source: https://isomux.com/docs/self-hosted Run on the server to enable Tailscale's HTTPS certificates for the tailnet. Requires MagicDNS and HTTPS Certificates enabled in the Tailscale admin console. The command prints an HTTPS URL (e.g., https://my-mac-mini..ts.net) that provides a secure context for voice input and Android PWA install. ```bash sudo tailscale set --operator=$USER tailscale serve --bg http://localhost:4000 ``` -------------------------------- ### GET /api/members-chat/files/:filename Source: https://isomux.com/docs/developer-api Reads an uploaded file from the members chat. ```APIDOC ## GET /api/members-chat/files/:filename ### Description Reads an uploaded file from the members chat. ### Method GET ### Endpoint /api/members-chat/files/:filename ### Parameters #### Path Parameters - **filename** (string) - Required - Name of the file to retrieve. ### Response #### Success Response (200) - **file** (binary) - The file content. ``` -------------------------------- ### GET /api/memory Source: https://isomux.com/docs/developer-api Retrieves the raw memory text, version, size, and capacity for a given scope. ```APIDOC ## GET /api/memory ### Description Retrieves the scope's raw memory text, optimistic-concurrency version, current injected size, and capacity. Supports agent, room, office, and boss scopes with specific targeting rules. ### Method GET ### Endpoint /api/memory ### Parameters #### Query Parameters - **scope** (string) - Required - The memory scope: `agent`, `room`, `office`, or `boss`. - **scopeId** (string) - Optional - Identifier for the scope. For `agent`, may be omitted when using an agent token to target itself. For `room`, must be an existing scopeId. For `office`, must be omitted. For `boss`, if omitted targets the caller's user or the agent's manager; if provided must name an existing user. ### Response #### Success Response (200) - **text** (string) - The raw memory text. - **version** (string) - Optimistic-concurrency version. - **size** (number) - Current injected size. - **cap** (number) - Capacity. #### Response Example { "text": "...", "version": "...", "size": 123, "cap": 456 } ``` -------------------------------- ### GET /api/members-chat Source: https://isomux.com/docs/developer-api Retrieves messages from the members chat with pagination and metadata. ```APIDOC ## GET /api/members-chat ### Description Retrieves messages from the office-wide members chat, including pagination, read pointer, unread count, and pinned messages. ### Method GET ### Endpoint /api/members-chat ### Parameters #### Query Parameters - **before** (string) - Optional - Message ID to return messages before. - **limit** (integer) - Optional - Maximum number of messages to return. ### Response #### Success Response (200) - **messages** (array) - List of messages in chronological order. - **hasMore** (boolean) - Indicates if more messages are available. - **readPointer** (string) - ID of the last read message. - **unread** (integer) - Number of unread messages. - **pinned** (array) - Up to 21 pinned messages, newest first. #### Response Example { "messages": [], "hasMore": false, "readPointer": "msg_123", "unread": 0, "pinned": [] } ``` -------------------------------- ### First-boot owner-claim banner with SSH tunnel instructions Source: https://isomux.com/docs/access-and-invites Displayed on first boot when no owner is configured. Shows the two ways to reach the claim form: locally at http://localhost:4000 or via an SSH tunnel from another machine. The banner appears on every boot until an owner claims the office. ```text ================================================================ Isomux: no owner has been set up for this office yet. TO CLAIM OWNERSHIP from THIS machine: Open http://localhost:4000 in your browser. TO CLAIM OWNERSHIP from another machine: 1. On that machine, open a tunnel to this box: ssh -L 4000:localhost:4000 @ 2. Open http://localhost:4000 in that browser. After you claim, the Access pane lets you enable external access so everyday use doesn't need the SSH tunnel. ================================================================ ``` -------------------------------- ### Set up Tailscale Funnel for public isomux access Source: https://isomux.com/docs/self-hosted Prompt for an isomux agent to set up Tailscale Funnel for public access. Requires prior authorization of the office and manual execution of the `tailscale funnel --bg http://localhost:4000` command because Claude agents refuse recognized tunnel commands. The agent must verify MagicDNS/HTTPS and the `funnel` nodeAttr, check existing port 443 mappings, and report the public URL with instructions to enable External access and restart isomux. ```text Set up Tailscale Funnel so my isomux office is publicly reachable from the internet. Steps: 1. If tailscale isn't installed, install it and pause to ask me to authenticate. 2. Confirm my tailnet has MagicDNS + HTTPS certs enabled in the admin console. Walk me through if needed. 3. Confirm the tailnet policy has a `funnel` nodeAttr covering this device. Ask me to add it if not. 4. Run `tailscale serve status` and `tailscale funnel status` to see what's currently configured. Enabling Funnel on port 443 will either make every other path/mapping on port 443 publicly reachable, or replace them entirely (Tailscale's docs: a port is either all-private Serve or all-public Funnel, never mixed). If port 443 has any mappings beyond the one pointing at isomux (default localhost:4000), list each by name and target. Stop and ask before continuing. For each extra mapping I need to choose one of: (a) confirm it's safe to expose publicly, (b) move it to a different port and update the Serve config yourself, since Claude agents refuse recognized tunnel commands, or (c) remove it. If moving to a different port, prefer a port outside Tailscale's Funnel-eligible list (avoid 443, 8443, 10000) so a future Funnel command can't accidentally expose it. 5. Once port 443 carries only the isomux mapping, ask me to run this command myself, because Claude agents refuse recognized tunnel commands: `tailscale funnel --bg http://localhost:4000` 6. Capture the public URL from `tailscale funnel status --json` and report it back to me with these exact instructions: "Funnel is up at . To finish, in your isomux office open Settings → Access → External access, enable the toggle, paste this URL into the Public URL field, click Save, then restart isomux for the bind to take effect (on a system service, run sudo systemctl restart isomux instead): systemctl --user restart isomux Sign in on the public URL using the link the Access pane shows you after Save." 7. Verify the public URL responds. Ask me to test from a device not on the tailnet (phone on cellular, or any non-tailnet machine). A curl from the box itself goes over the tailnet path and isn't a true public-reachability check. If you run into any issues with this setup, ask in the Isomux Discord: https://discord.gg/FrjEYyNvYs ``` -------------------------------- ### Recover owner login with isomux-office.ts owner-login CLI Source: https://isomux.com/docs/access-and-invites Run from a shell on the server host to recover a lost owner session. Prints a one-time login URL valid for 15 minutes; requires the server to be running and talks over the Unix-domain socket at ~/.isomux/admin.sock (mode 0600). ```shell bun run server/isomux-office.ts owner-login --name "" ``` -------------------------------- ### Configure Claude on Amazon Bedrock with environment variables Source: https://isomux.com/docs/access-and-invites Configure Claude on Amazon Bedrock via office-wide environment variables. The bearer token is a Bedrock API key from the AWS console; if using an IAM access key, replace the bearer token line with AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and optionally AWS_SESSION_TOKEN. After setting these, run /clear on Claude agents to pick up the variables. ```plaintext CLAUDE_CODE_USE_BEDROCK=1 AWS_REGION=us-west-2 (or your region) AWS_BEARER_TOKEN_BEDROCK=ABSK... ``` -------------------------------- ### Apply SSH hardening and re-check root access Source: https://isomux.com/docs/self-hosted Run after fixing the SSH key file that caused the root-access check to fail. Applies SSH hardening and re-runs the check. Re-run whenever root's key list changes, because a pass is only a snapshot of the moment it runs. ```bash sudo isomux-harden-ssh ``` -------------------------------- ### Forward a dev server port over SSH Source: https://isomux.com/docs/self-hosted Forward a local port to an agent's dev server on the office box when SSH is open (the default). After running, open http://localhost:5173 to reach the app. ```bash ssh -L 5173:localhost:5173 root@office.example.com ``` -------------------------------- ### Set explicit provider directories for Claude and Codex Source: https://isomux.com/docs/access-and-invites Set explicit absolute provider directories in managed variables. These override the Isomux-managed personal directory; Isomux does not expand ~ or $VAR in these paths. ```plaintext CLAUDE_CONFIG_DIR=/home//.isomux-users//.claude CODEX_HOME=/home//.isomux-users//.codex ``` -------------------------------- ### PUT /api/memory Source: https://isomux.com/docs/developer-api Replaces the raw memory file for a scope, using optimistic concurrency. ```APIDOC ## PUT /api/memory ### Description Replaces the raw memory file for the scope. Requires the version from a prior GET. Does not apply the 400-character append limit. ### Method PUT ### Endpoint /api/memory ### Parameters #### Request Body - **scope** (string) - Required - The memory scope. - **scopeId** (string) - Optional - Identifier for the scope, following the same rules as GET. - **text** (string) - Required - The new raw memory text. - **version** (string) - Required - The version obtained from a GET request for optimistic concurrency. ### Request Example { "scope": "agent", "text": "Updated memory content.", "version": "abc123" } ### Response #### Success Response (200) - **item** (object) - The updated memory item. - **version** (string) - Updated version. - **size** (number) - Post-write size. - **cap** (number) - Capacity. #### Response Example { "item": {}, "version": "...", "size": 123, "cap": 456 } ### Error Responses - **409** - Stale version. ``` -------------------------------- ### Send a message to an agent via REST Source: https://isomux.com/docs/developer-api Use this curl command to send a message to an agent. It requires the OFFICE_URL, TOKEN_ID, and AGENT_TOKEN environment variables. The response includes messageId and lastDrainedAt (null if the token has never read its log). ```bash curl -s -X POST "$OFFICE_URL/api/api-token-inboxes/$TOKEN_ID/messages" \ -H "Authorization: Bearer $AGENT_TOKEN" \ -H "Content-Type: application/json" \ -d '{"text":"The report is ready."}' ``` -------------------------------- ### POST /api/members-chat/uploads Source: https://isomux.com/docs/developer-api Uploads files to the members chat. ```APIDOC ## POST /api/members-chat/uploads ### Description Uploads files to the members chat. ### Method POST ### Endpoint /api/members-chat/uploads ### Parameters #### Request Body - **file** (multipart) - Required - The file to upload. ### Response #### Success Response (200) - **file** (object) - The uploaded file metadata. ``` -------------------------------- ### POST /api/memory Source: https://isomux.com/docs/developer-api Appends a server-stamped trigger to the scope's memory, with size and capacity limits. ```APIDOC ## POST /api/memory ### Description Appends a server-stamped trigger to the scope's memory. The text must be a single line of at most 400 characters. Returns the updated item, version, size, and capacity. ### Method POST ### Endpoint /api/memory ### Parameters #### Request Body - **scope** (string) - Required - The memory scope: `agent`, `room`, `office`, or `boss`. - **scopeId** (string) - Optional - Identifier for the scope, following the same rules as GET. - **text** (string) - Required - The text to append. Must be one line, at most 400 characters. ### Request Example { "scope": "agent", "text": "Remember to check the server logs." } ### Response #### Success Response (200) - **item** (object) - The appended memory item. - **version** (string) - Updated optimistic-concurrency version. - **size** (number) - Post-write size. - **cap** (number) - Capacity. #### Response Example { "item": {}, "version": "...", "size": 123, "cap": 456 } ### Error Responses - **409** - Duplicate request. - **422** - Line or scope-cap failure. ``` -------------------------------- ### Send a message to an agent with curl Source: https://isomux.com/docs/developer-api Posts a JSON message to the agent's messages endpoint using the agent ID and token. The response contains a messageId that is also the id of the send entry in the token log. ```bash AGENT_ID="agent-123" curl -s -X POST "$OFFICE_URL/api/agents/$AGENT_ID/messages" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"text":"Please check the latest alert."}' ``` -------------------------------- ### Drain messages via cursor read Source: https://isomux.com/docs/developer-api Use this curl command to read messages after a given sequence. The 'after' field defaults to 0 and must be a nonnegative safe integer. The response contains entries, firstSequence, latestSequence, previouslyDrainedAt, and drainedAt. Each read returns up to 500 entries with sequence > after. ```bash curl -s -X POST "$OFFICE_URL/api/me/api-token-inbox/drain" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"after":123}' ``` -------------------------------- ### API error response JSON Source: https://isomux.com/docs/developer-api Shown as the standard failure format for all API endpoints. Use the stable 'code' for program logic, show 'message' to a person, and follow 'resolution' when an agent can recover. ```json { "error": { "code": "not_found", "message": "No API endpoint exists at /api/example.", "resolution": "Read https://isomux.com/openapi.json for supported endpoints." } } ``` -------------------------------- ### POST /api/me/api-token-inbox/drain Source: https://isomux.com/docs/developer-api Reads entries from the token's inbox log. The client provides the last sequence it has processed, and the server returns entries with a higher sequence. ```APIDOC ## POST /api/me/api-token-inbox/drain ### Description Reads entries from the token's inbox log. The client provides the last sequence it has processed, and the server returns entries with a higher sequence. ### Method POST ### Endpoint `/api/me/api-token-inbox/drain` ### Parameters #### Request Body - **after** (number) - Optional - The last sequence the client has saved and processed. Defaults to 0 and must be a nonnegative safe integer. ### Request Example ```json {"after":123} ``` ### Response #### Success Response (200) - **entries** (array) - List of log entries with sequence greater than `after`. - **firstSequence** (number) - The oldest sequence still in the log, or `latestSequence` when the log is empty. - **latestSequence** (number) - The last assigned sequence for the token, including entries removed by storage pruning. - **previouslyDrainedAt** (number|null) - The previous read time, or null if no previous read. - **drainedAt** (number) - The current read time. #### Response Example ```json {"entries":[{"sequence":124,"id":"message-123","text":"The report is ready.","direction":"from_agent","senderAgentId":"agent-123","senderAgentName":"Worker","senderRoomName":"Isomux","sentAt":1788810481060}],"firstSequence":124,"latestSequence":124,"previouslyDrainedAt":null,"drainedAt":1788810481060} ``` ``` -------------------------------- ### POST /api/members-chat/read Source: https://isomux.com/docs/developer-api Updates the caller's read pointer in the members chat. ```APIDOC ## POST /api/members-chat/read ### Description Updates the caller's read pointer in the members chat. ### Method POST ### Endpoint /api/members-chat/read ### Parameters #### Request Body - **lastReadId** (string) - Required - ID of the last read message. ### Request Example { "lastReadId": "msg_123" } ### Response #### Success Response (200) - **status** (string) - Confirmation of the update. ``` -------------------------------- ### POST /api/members-chat Source: https://isomux.com/docs/developer-api Creates a new message in the members chat. ```APIDOC ## POST /api/members-chat ### Description Posts a new message to the members chat, optionally with attachments and a reply-to reference. ### Method POST ### Endpoint /api/members-chat ### Parameters #### Request Body - **text** (string) - Required - The message text. - **attachments** (file) - Optional - Uploaded attachments. - **replyTo** (string) - Optional - ID of an existing message to reply to. ### Request Example { "text": "Hello everyone", "replyTo": "msg_123" } ### Response #### Success Response (200) - **message** (object) - The created message object. #### Error Response (404) - **error** (string) - `reply_not_found` if the reply target is unknown or deleted. ``` -------------------------------- ### POST /api/api-token-inboxes/{tokenId}/messages Source: https://isomux.com/docs/developer-api Sends a message to a token's inbox. The token ID is provided in the URL path, and the agent authenticates with a bearer token. ```APIDOC ## POST /api/api-token-inboxes/{tokenId}/messages ### Description Sends a message from an agent to a token's inbox. The token ID is provided in the URL path, and the agent authenticates with a bearer token. ### Method POST ### Endpoint `/api/api-token-inboxes/{tokenId}/messages` ### Parameters #### Path Parameters - **tokenId** (string) - Required - The API token ID that identifies the inbox. #### Request Body - **text** (string) - Required - The message text to send. ### Request Example ```json {"text":"The report is ready."} ``` ### Response #### Success Response (200) - **messageId** (string) - The ID of the created message. - **lastDrainedAt** (number|null) - The timestamp of the last drain, or null if the token has never read its log. #### Response Example ```json {"messageId":"message-123","lastDrainedAt":1788810481060} ``` ``` -------------------------------- ### WebSocket event payload for api_token_log_entry Source: https://isomux.com/docs/developer-api This JSON object is the event payload received on the WebSocket after each new send or reply. The entry object matches the cursor read response. The socket is receive-only and carries only this token's entries. ```json { "type": "api_token_log_entry", "tokenId": "pat-123", "entry": { "sequence": 124, "id": "message-123", "text": "The report is ready.", "direction": "from_agent", "senderAgentId": "agent-123", "senderAgentName": "Worker", "senderRoomName": "Isomux", "sentAt": 1788810481060 } } ``` -------------------------------- ### POST /api/agents/{agentId}/messages Source: https://isomux.com/docs/developer-api Sends a message to a specific agent. Requires a bearer token and the agent ID. ```APIDOC ## [POST] /api/agents/{agentId}/messages ### Description Sends a message to a specific agent. The response contains a `messageId` which is also the `id` of the send entry in the token log. ### Method POST ### Endpoint /api/agents/{agentId}/messages ### Parameters #### Path Parameters - **agentId** (string) - Required - The ID of the target agent. #### Headers - **Authorization** (string) - Required - Bearer token for authentication. - **Content-Type** (string) - Required - Must be `application/json`. #### Request Body - **text** (string) - Required - The message text to send. ### Request Example ```json { "text": "Please check the latest alert." } ``` ### Response #### Success Response (200) - **messageId** (string) - The ID of the sent message. #### Response Example ```json { "messageId": "msg-123" } ``` ``` -------------------------------- ### PUT /api/members-chat/:id/pin Source: https://isomux.com/docs/developer-api Pins or unpins a message in the members chat. ```APIDOC ## PUT /api/members-chat/:id/pin ### Description Pins or unpins a message in the members chat. ### Method PUT ### Endpoint /api/members-chat/:id/pin ### Parameters #### Path Parameters - **id** (string) - Required - ID of the message to pin or unpin. #### Request Body - **active** (boolean) - Required - `true` to pin, `false` to unpin. ### Request Example { "active": true } ### Response #### Success Response (200) - **message** (object) - The updated message object. ``` -------------------------------- ### PUT /api/members-chat/:id/thumbs-up Source: https://isomux.com/docs/developer-api Sets or removes the caller's thumbs-up reaction on a message. ```APIDOC ## PUT /api/members-chat/:id/thumbs-up ### Description Sets or removes the caller's thumbs-up reaction on a message. ### Method PUT ### Endpoint /api/members-chat/:id/thumbs-up ### Parameters #### Path Parameters - **id** (string) - Required - ID of the message. #### Request Body - **active** (boolean) - Required - `true` to set thumbs up, `false` to remove. ### Request Example { "active": true } ### Response #### Success Response (200) - **message** (object) - The updated message object. ``` -------------------------------- ### PATCH /api/members-chat/:id Source: https://isomux.com/docs/developer-api Edits the caller's own message in the members chat. ```APIDOC ## PATCH /api/members-chat/:id ### Description Edits the caller's own post in the members chat. ### Method PATCH ### Endpoint /api/members-chat/:id ### Parameters #### Path Parameters - **id** (string) - Required - ID of the message to edit. #### Request Body - **text** (string) - Required - New text for the message. ### Request Example { "text": "Updated message" } ### Response #### Success Response (200) - **message** (object) - The updated message object. ``` -------------------------------- ### DELETE /api/members-chat/:id Source: https://isomux.com/docs/developer-api Deletes a message from the members chat. ```APIDOC ## DELETE /api/members-chat/:id ### Description Deletes a message from the members chat. The caller can delete their own post, or any post when acting for an office owner. ### Method DELETE ### Endpoint /api/members-chat/:id ### Parameters #### Path Parameters - **id** (string) - Required - ID of the message to delete. ### Response #### Success Response (200) - **message** (object) - The deleted message object. ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.