Multiplayer by Default
Section titled “Multiplayer by Default”For thirty years, “collaboration” on computers has meant taking turns. Screen sharing where one person drives and everyone else watches. Pair programming where two people share one keyboard. Code reviews where changes move through a queue, one at a time.
Google Docs proved that real-time collaboration does not require turn-taking. Multiple cursors. Simultaneous editing. Instant visibility. It changed how the world writes documents.
Hoody does the same thing for entire computers.
Share a URL. Everyone is in. Multiple people in the same terminal, the same file system, the same database, the same browser, the same desktop. Not watching each other work — working together, simultaneously, in the same environment. One person in a browser tab, another over ssh hoody.com on a plane — same container, same terminals, same state, real-time.
This is not a feature we bolted on. It is the natural consequence of making everything HTTP. When every service is a URL, multiplayer is automatic. And when even the Hoody Agent itself runs in a container, sharing your whole working view is as natural as sharing any other URL.
How Sharing Works
Section titled “How Sharing Works”Every Hoody service has a URL. URLs are shareable by nature. That is the entire mechanism.
Your terminal: https://PROJECT-CONTAINER-terminal-1.SERVER.containers.hoody.icuYour display: https://PROJECT-CONTAINER-display-1.SERVER.containers.hoody.icuYour VS Code: https://PROJECT-CONTAINER-code-1.SERVER.containers.hoody.icuYour database: https://PROJECT-CONTAINER-sqlite-1.SERVER.containers.hoody.icuYour agent: https://PROJECT-CONTAINER-agent-1.SERVER.containers.hoody.icuSend any of those URLs to someone. They open it in their browser. They are now in your environment. No installation. No invitation system. No account creation at your end. No VPN. No SSH key exchange.
Multiplayer Terminals
Section titled “Multiplayer Terminals”Multiple people in the same terminal. Everyone sees the identical live screen. Anyone can type. Every keystroke appears for everyone in real-time.
What It Looks Like
Section titled “What It Looks Like”┌─────────────────────────────────────────────────┐│ root@container:~# ││ ││ $ npm test ← Alice ││ Running 47 tests... ││ ✓ All tests passed ││ ││ $ git status ← Bob ││ On branch feature/auth ││ modified: src/auth.ts ││ ││ $ cat src/auth.ts ← the agent ││ // AI reviewing the file... ││ │└─────────────────────────────────────────────────┘Three participants — two humans and an AI agent — attached to the same live shell. It is one terminal: one screen, one cursor, one stream of output, identical for everyone. Everyone sees everything the moment it happens. No one waits for a screen share.
Set It Up
Section titled “Set It Up”There is nothing to set up. Open the terminal URL from multiple browsers:
# Read the container details -- that's the entire setuphoody containers get $CONTAINER_ID
# Output includes id, project_id, name, status, server_name, etc.# Construct and share the terminal URL:# https://PROJECT-CONTAINER-terminal-1.SERVER.containers.hoody.icuimport { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.icu', token: process.env.HOODY_TOKEN });
// Get the terminal URLconst container = await client.api.containers.get(CONTAINER_ID);
const terminalUrl = `https://${container.data.project_id}-${container.data.id}-terminal-1.${container.data.server_name}.containers.hoody.icu`;
// Share this URL -- anyone who opens it joins the terminal sessionconsole.log('Share this URL:', terminalUrl);# Get container details to construct the terminal URLcurl "https://api.hoody.icu/api/v1/containers/$CONTAINER_ID" \ -H "Authorization: Bearer $HOODY_TOKEN"
# The terminal URL is:# https://{project_id}-{container_id}-terminal-1.{server}.containers.hoody.icu# Share it. Anyone who opens it is in.Multiple Terminal Instances
Section titled “Multiple Terminal Instances”Need separate terminal sessions for different tasks? Use instance numbers:
terminal-1 → Alice and Bob debug the backend togetherterminal-2 → Carol and the AI agent work on the frontendterminal-3 → Dave monitors logs independentlyterminal-4 → Shared team standup terminal for commandsEach instance is a separate URL. Each is independently shareable. Each supports multiple simultaneous users.
Shared Displays
Section titled “Shared Displays”Shared displays bring graphical application sharing to the same level. Multiple people see the same desktop, the same browser, the same GUI application — and can interact with it simultaneously.
Display URL: https://PROJECT-CONTAINER-display-1.SERVER.containers.hoody.icu
Alice sees: The React app running in the container's ChromeBob sees: The exact same view, in real-timeCarol clicks: A button in the app -- Alice and Bob see the result instantlyThis is not screen sharing. No one is rebroadcasting their monitor — every participant connects to the same live display session, with full input, straight from the source. The experience is identical for every participant.
Use Cases for Shared Displays
Section titled “Use Cases for Shared Displays”Live debugging: Everyone sees the same browser. One person triggers the bug. Everyone watches the network tab, the console, the DOM simultaneously.
Design review: A designer opens Figma in the container’s browser. The team reviews together, pointing at elements, making live changes.
AI observation: The agent runs browser automation in display-1 while the team watches. The agent navigates, clicks, fills forms. The team verifies the behavior is correct.
Collaborative File Editing
Section titled “Collaborative File Editing”hoody-code gives everyone VS Code in a browser. Multiple people editing the same codebase simultaneously.
https://PROJECT-CONTAINER-code-1.SERVER.containers.hoody.icuOpen this URL from different browsers. Each person gets a full VS Code instance connected to the same filesystem. File changes propagate instantly.
Workspace Sharing
Section titled “Workspace Sharing”Share the Whole View
Section titled “Share the Whole View”The Hoody Agent puts your whole working context in one multi-pane view — AI chat beside live terminals, files, and a display preview. And because the Agent is streamed as a shared session, its URL is multiplayer like everything else: everyone who opens it sees the same panes, live.
https://PROJECT-CONTAINER-agent-1.SERVER.containers.hoody.icuPrefer to compose your own view? Every service is an iframe-able URL — put terminal-1, display-1, code-1, and sqlite-1 side by side in a plain HTML page and send the link. Each pane is the real, live service; each is independently multiplayer.
┌──────────────────────────────────────────────────────────────┐│ SHARED WORKSPACE: "Team Dashboard" ││ ││ ┌─────────────────────┐ ┌──────────────────────────────┐ ││ │ Terminal-1 │ │ Display-1 │ ││ │ (Backend logs) │ │ (App preview) │ ││ │ │ │ │ ││ │ Alice & Bob here │ │ Everyone sees this │ ││ └─────────────────────┘ └──────────────────────────────┘ ││ ││ ┌─────────────────────┐ ┌──────────────────────────────┐ ││ │ Code-1 │ │ SQLite-1 │ ││ │ (VS Code) │ │ (Database browser) │ ││ │ │ │ │ ││ │ Carol editing │ │ Dave checking data │ ││ └─────────────────────┘ └──────────────────────────────┘ ││ │└──────────────────────────────────────────────────────────────┘One URL. Four services. Four participants. Everything in sync.
This is what Google Docs did for documents, applied to entire computing environments. Nothing here is a static screenshot — every pane is the live service itself, open to everyone at once.
Permission Layers
Section titled “Permission Layers”Open-by-default does not mean open-forever. When you are ready to control access, Hoody provides granular proxy permissions:
# Build the permissions document one field at a time with the granular commands.# Writes are optimistic-concurrency guarded, and every successful write bumps# file_version -- so read a fresh ETag before each mutation (a stale --if-match# is rejected with 412).v() { hoody containers proxy permissions get -c $CONTAINER_ID -o json | jq -r '.file_version'; }
# Set a password on the containerhoody containers proxy groups password set -c $CONTAINER_ID \ --group-name team \ --auth-username team --auth-password 'team-access-2026' \ --salt team-salt-2026 --algorithm sha256 \ --if-match "file:v$(v)"
# Grant the services the group may reach, one program per callfor program in terminal files display; do hoody containers proxy groups permissions set -c $CONTAINER_ID \ --group-name team --program $program --access true --if-match "file:v$(v)"done
hoody containers proxy groups permissions set -c $CONTAINER_ID \ --group-name team --program http --access '[8080]' --if-match "file:v$(v)"
# Everything not granted above is deniedhoody containers proxy default --default deny -c $CONTAINER_ID --if-match "file:v$(v)"
# Alternative: reset this container's permissions document, then restrict by IP.# Each IP group takes one CIDR; add multiple groups for multiple ranges.hoody containers proxy permissions delete -c $CONTAINER_ID --if-match "file:v$(v)" -yhoody containers proxy default --default deny -c $CONTAINER_ID --if-match "file:v$(v)"
hoody containers proxy groups ip set -c $CONTAINER_ID \ --group-name office-vpn --range 203.0.113.50/32 --if-match "file:v$(v)"hoody containers proxy groups ip set -c $CONTAINER_ID \ --group-name office-lan --range 198.51.100.0/24 --if-match "file:v$(v)"
for group in office-vpn office-lan; do for program in terminal files display; do hoody containers proxy groups permissions set -c $CONTAINER_ID \ --group-name $group --program $program --access true --if-match "file:v$(v)" done hoody containers proxy groups permissions set -c $CONTAINER_ID \ --group-name $group --program http --access '[8080]' --if-match "file:v$(v)"done
# Alternative: reset this container's permissions document, then use a shared-secret token carried in a header.hoody containers proxy permissions delete -c $CONTAINER_ID --if-match "file:v$(v)" -yhoody containers proxy default --default deny -c $CONTAINER_ID --if-match "file:v$(v)"
hoody containers proxy groups token set -c $CONTAINER_ID \ --group-name realm --if-match "file:v$(v)" \ --body '{"header":"Authorization","value":"'$REALM_TOKEN'"}'
for program in terminal files display; do hoody containers proxy groups permissions set -c $CONTAINER_ID \ --group-name realm --program $program --access true --if-match "file:v$(v)"done
hoody containers proxy groups permissions set -c $CONTAINER_ID \ --group-name realm --program http --access '[8080]' --if-match "file:v$(v)"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.icu', token: process.env.HOODY_TOKEN });
// Writes need an If-Match precondition (the current file_version is returned// as a header by GET). Pass it via the `ifMatch` option, e.g. { ifMatch: 'file:v1' }.
// Password protectionawait client.api.proxyPermissionsContainer.replace(CONTAINER_ID, { project: PROJECT_ID, container: CONTAINER_ID, groups: { team: { type: 'password', username: 'team', password: 'team-access-2026', salt: 'team-salt-2026' } }, permissions: { team: { terminal: true, files: true, display: true, http: [8080] } }, default: 'deny'}, { ifMatch: 'file:v1' });
// Or IP restrictionawait client.api.proxyPermissionsContainer.replace(CONTAINER_ID, { project: PROJECT_ID, container: CONTAINER_ID, groups: { office_primary: { type: 'ip', range: '203.0.113.50/32' }, office_subnet: { type: 'ip', range: '198.51.100.0/24' } }, permissions: { office_primary: { terminal: true, files: true, display: true, http: [8080] }, office_subnet: { terminal: true, files: true, display: true, http: [8080] } }, default: 'deny'}, { ifMatch: 'file:v1' });# Password protection# Writes require an If-Match precondition (read the current file_version via GET first)curl -X PUT "https://api.hoody.icu/api/v1/containers/$CONTAINER_ID/proxy/permissions" \ -H "Authorization: Bearer $HOODY_TOKEN" \ -H "Content-Type: application/json" \ -H "If-Match: file:v1" \ -d '{"project":"'$PROJECT_ID'","container":"'$CONTAINER_ID'","groups":{"team":{"type":"password","username":"team","password":"team-access-2026","salt":"team-salt-2026"}},"permissions":{"team":{"terminal":true,"files":true,"display":true,"http":[8080]}},"default":"deny"}'
# Or IP restrictioncurl -X PUT "https://api.hoody.icu/api/v1/containers/$CONTAINER_ID/proxy/permissions" \ -H "Authorization: Bearer $HOODY_TOKEN" \ -H "Content-Type: application/json" \ -H "If-Match: file:v1" \ -d '{"project":"'$PROJECT_ID'","container":"'$CONTAINER_ID'","groups":{"office_primary":{"type":"ip","range":"203.0.113.50/32"},"office_subnet":{"type":"ip","range":"198.51.100.0/24"}},"permissions":{"office_primary":{"terminal":true,"files":true,"display":true,"http":[8080]},"office_subnet":{"terminal":true,"files":true,"display":true,"http":[8080]}},"default":"deny"}'The progression:
- Development — Wide open. Share the URL, everyone is in. Maximum collaboration velocity.
- Staging — Password protected. Team members know the password. External parties need to ask.
- Production — IP restricted or token-gated. Only authorized traffic reaches the services.
Permissions apply at the proxy level, which means they protect ALL services in the container simultaneously. Set once, enforced everywhere.
Real-Time Collaboration Patterns
Section titled “Real-Time Collaboration Patterns”Pattern 1: Pair Programming
Section titled “Pattern 1: Pair Programming”Two developers. One container. Two browser tabs.
Developer A: Opens code-1 URL → Edits src/components/Header.tsxDeveloper B: Opens code-1 URL → Edits src/components/Footer.tsxBoth: Open terminal-1 URL → See each other's commandsBoth: Open display-1 URL → See the app update liveNo screen sharing latency. No “let me take control.” Both have full access to everything. The filesystem is the single source of truth.
Pattern 2: Client Demo
Section titled “Pattern 2: Client Demo”Show a client the work-in-progress. Live. Interactive.
You: Open display-1 URL → Present the running applicationClient: Opens the same URL → Clicks around, tests features, asks questionsYou: Open terminal-1 → Make live changes in response to feedbackClient: Sees changes immediately in display-1The client does not install anything. They do not need an account. They open a URL in their browser. That is the entire onboarding process.
Pattern 3: Team Debugging
Section titled “Pattern 3: Team Debugging”Production issue. Everyone needs to see the same thing at the same time.
Lead: Opens terminal-1 → Tails the error logsBackend: Opens terminal-2 → Queries the database for corrupted recordsFrontend: Opens display-1 → Reproduces the bug in the browserDevOps: Opens terminal-3 → Checks network configurationEveryone: Opens each other's terminal URLs — every perspective one click awayFour people. Four perspectives. One container. Real-time coordination without a single Zoom call.
Pattern 4: AI + Human Collaboration
Section titled “Pattern 4: AI + Human Collaboration”The most powerful pattern: humans and AI agents working together in the same container.
# Open an agent session, then dispatch a blocking turn into itSESSION_ID=$(hoody agent sessions create --realm global --container "$CONTAINER_ID" -o json | jq -r '.id')
hoody agent sessions prompt-sync \ --id "$SESSION_ID" \ --text "Implement the user profile page based on the design in /docs/profile-mockup.png" \ --policy auto_approve \ --realm global
# While the agent works, you and your team observe in real-time:# terminal-1 URL → Watch the agent execute commands# code-1 URL → Watch the agent write code# display-1 URL → Watch the app update# agent-1 URL → Send prompts to steer the agent (HTTP API / hoody CLI)import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.icu', token: process.env.HOODY_TOKEN });
// First open a session, then dispatch a blocking turn into it.const session = await client.agent.sessions.createSession({ realm: 'global', container: CONTAINER_ID });
const result = await client.agent.sessions.promptSync( session.id, { text: 'Implement the user profile page based on the design in /docs/profile-mockup.png' }, { policy: 'auto_approve' },);
// Or call the HTTP surface directly with raw fetch:// const agentBase = `https://${PROJECT_ID}-${CONTAINER_ID}-agent-1.${SERVER}.containers.hoody.icu`;// await fetch(`${agentBase}/api/v1/agent/sessions/${session.id}/prompt:sync?policy=auto_approve`, {// method: 'POST',// headers: { 'Content-Type': 'application/json' },// body: JSON.stringify({ text: 'Implement the user profile page...' }),// });
// Team observes via URLs:// terminal-1 → Agent commands in real-time// code-1 → Code changes as they happen// display-1 → App preview updates live// agent-1 → Send prompts to steer the agent (HTTP API / hoody CLI)# 1. Create a sessionAGENT_BASE="https://$PROJECT_ID-$CONTAINER_ID-agent-1.$SERVER.containers.hoody.icu"SESSION_ID=$(curl -sX POST "$AGENT_BASE/api/v1/agent/sessions?realm=global" \ -H "Content-Type: application/json" -d '{}' | jq -r '.id')
# 2. Dispatch a blocking turn (auto-approve via the ?policy query param,# or pass -H "X-Hoody-Gate-Policy: auto_approve" instead)curl -X POST "$AGENT_BASE/api/v1/agent/sessions/$SESSION_ID/prompt:sync?policy=auto_approve" \ -H "Content-Type: application/json" \ -d '{ "text": "Implement the user profile page based on the design in /docs/profile-mockup.png" }'
# Team watches via service URLs:# terminal-1.containers.hoody.icu → Agent's commands# code-1.containers.hoody.icu → Code changes# display-1.containers.hoody.icu → Live preview# agent-1.containers.hoody.icu → Send prompts to steer the agentThe team watches the AI work. Someone notices a mistake and corrects the agent with a follow-up prompt. Someone else opens the terminal and fixes a configuration issue the agent missed. The agent continues building, now on the right track. Human judgment and AI execution, simultaneously.
Use Instance Numbers for Organization
Section titled “Use Instance Numbers for Organization”When multiple people and agents share a container, use instance numbers to avoid stepping on each other:
terminal-1 → Team lead (oversight, commands)terminal-2 → AI agent (automated execution)terminal-3 → Backend developer (database queries)terminal-4 → Frontend developer (build tools)
display-1 → App preview (shared)display-2 → AI agent's browser automation (shared observation)
agent-1 → Primary AI agent (feature work)agent-2 → Secondary AI agent (testing)
code-1 → Developer A's VS Codecode-2 → Developer B's VS CodeAll instances share the same container filesystem and network. But each instance is a separate access point that can be independently shared.
The Multiplayer Advantage
Section titled “The Multiplayer Advantage”Traditional collaboration tools add layers on top of single-user systems. Hoody’s multiplayer is not a layer — it is the architecture itself.
| Traditional | Hoody |
|---|---|
| Install screen sharing software | Share the URL |
| One person drives at a time | Everyone has full control |
| Video encoding introduces lag | Direct HTTP connection, no encoding |
| Requires same time zone for effectiveness | Asynchronous access to the same URL |
| Setup per collaboration session | No setup ever — URLs are permanent |
| Cannot share with AI agents | Agents use the same URLs as humans |
The URL IS the collaboration mechanism. There is nothing to configure, nothing to install, nothing to negotiate. Open the URL. You are in.
What’s Next
Section titled “What’s Next”- Building a Full-Stack Application — Build something together
- The Vibe Coding Revolution — AI + human collaborative development
- Deploying Autonomous AI Agents — Multi-agent orchestration patterns
- Proxy Permissions — Fine-grained access control