happy Documentation

Mobile and Web client for Codex and Claude Code, with realtime voice, encryption and fully featured

23,294 stars TypeScript TypeScript 1 file ยท ~9,803 tokens #claude-code#claude-desktop#claude-mobile#codex#codex-cli#hacktoberfest
RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy happy on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name happy -p 3005:3005 --restart always slopus/happy:latest

1. Project Overview & Quickstart (slopus/happy)

File: README.md

Mobile and Web Client for Claude Code & Codex

Use Claude Code or Codex from anywhere with end-to-end encryption.

Step 1: Download App

Step 2: Install CLI on your computer

bash
npm install happy

Migrated from the happy-coder package. Thanks to @franciscop for donating the happy package name!

Step 3: Start using `happy` instead of `claude` or `codex`

bash
# Instead of claude, use:
happy claude
# or
happy codex

How does it work?

On your computer, run happy instead of claude or happy codex instead of codex to start your AI through our wrapper. When you want to control your coding agent from your phone, it restarts the session in remote mode. To switch back to your computer, just press any key on your keyboard.

๐Ÿ”ฅ Why Happy Coder?

  • ๐Ÿ“ฑ Mobile access to Claude Code and Codex - Check what your AI is building while away from your desk
  • ๐Ÿ”” Push notifications - Get alerted when Claude Code and Codex needs permission or encounters errors
  • โšก Switch devices instantly - Take control from phone or desktop with one keypress
  • ๐Ÿ” End-to-end encrypted - Your code never leaves your devices unencrypted
  • ๐Ÿ› ๏ธ Open source - Audit the code yourself. No telemetry, no tracking

๐Ÿ“ฆ Project Components

  • Happy App - Web UI + mobile client (Expo)
  • Happy CLI - Command-line interface for Claude Code and Codex
  • Happy Agent - Remote agent control CLI (create, send, monitor sessions)
  • Happy Server - Backend server for encrypted sync

๐Ÿ  Who We Are

We're engineers scattered across Bay Area coffee shops and hacker houses, constantly checking how our AI coding agents are progressing on our pet projects during lunch breaks. Happy Coder was born from the frustration of not being able to peek at our AI coding tools building our side hustles while we're away from our keyboards. We believe the best tools come from scratching your own itch and sharing with the community.

๐Ÿ“š Documentation & Contributing

License

MIT License - see LICENSE for details.


File: docs/README.md

Happy Docs

This folder documents how Happy works internally, with a focus on protocol, backend architecture, deployment, and the CLI tool. Start here.

Index

  • protocol.md: Wire protocol (WebSocket), payload formats, sequencing, and concurrency rules.
  • realtime-sync-and-rpc.md: High-level overview of realtime socket management and RPC control flow.
  • api.md: HTTP endpoints and authentication flows.
  • encryption.md: Encryption boundaries and on-wire encoding.
  • backend-architecture.md: Internal backend structure, data flow, and key subsystems.
  • deployment.md: How to deploy the backend and required infrastructure.
  • cli-architecture.md: CLI and daemon architecture and how they interact with the server.
  • multi-process.md: Deeper multi-replica Socket.IO + Redis streams behavior, failure modes, and integration-test history.
  • dev-environments.md: Local environments/data/ workflow, lab-rat project provisioning, env:cli passthrough behavior, and daemon usage.
  • session-protocol.md: Unified encrypted chat event protocol.
  • session-protocol-claude.md: Claude-specific session-protocol flow (local vs remote launchers, dedupe/restarts).
  • plans/provider-envelope-redesign.md: Proposed replacement for the current provider/session envelope design.
  • permission-resolution.md: State-based permission mode resolution across app and CLI (including sandbox behavior).
  • happy-wire.md: Shared wire schemas/types package and migration notes.
  • voice-architecture.md: ElevenLabs voice assistant integration, session routing, context batching, and VAD detection.
  • research/: general research notes and exploratory writeups.
  • competition/: competitor research, protocol analysis, and comparison notes.
  • competition/AGENTS.md: structure and rules for storing competitor research results without committing raw checkouts.

Conventions

  • Paths and field names reflect the current implementation in packages/happy-server.
  • Examples are illustrative; the canonical source is the code.

2. Official Technical Reference & Guides (slopus/slopus.github.io)

Privacy Policy

Last updated: July 15, 2026

About Happy

Happy is a free, open-source mobile and web client for Claude Code and Codex, released under the MIT License. The source code is publicly available, and anyone can inspect, modify, and distribute it according to the terms of the MIT License.

Data Collection

Happy collects limited, pseudonymous product analytics through PostHog. We use them to understand whether core actions succeed and to find bugs earlier. Analytics never include your message content, code, or other encrypted session content.

  • We record simple product actions and outcomes, such as connecting, sending a message, starting or ending a voice session, and app updates.
  • Events may include basic technical context such as app, operating-system, and device details so we can diagnose reliability issues.
  • Analytics use a pseudonymous app identifier, not your code or conversation content.
  • You can turn off analytics in the app settings.

Encrypted Session Data

Your messages, code, and session data are encrypted on your device before they are sent. Happy's relay stores encrypted blobs only to synchronize your devices; it cannot read their contents.

To operate sync and notifications, Happy processes limited service metadata, including device, session, and message identifiers, timestamps, and push-notification tokens. This metadata is not your code or conversation content.

Third-Party Services

Happy may connect to external AI services, such as Claude Code and Codex, based on your configuration. When using those services:

  • You are subject to their respective privacy policies and terms of service
  • Happy does not send your code or conversation content to PostHog
  • Push-notification delivery uses Expo's push-notification service; push tokens are used only to deliver notifications

Disclaimers

We are not responsible for:

  • Any damages, losses, or issues arising from the use of Happy
  • The accuracy, reliability, or performance of the software
  • Any data loss or security breaches on your local device
  • The behavior or policies of third-party AI services you choose to use

Happy is provided "AS IS" without warranty of any kind. Use at your own risk.

Independence

Happy is an independent, community-driven project. We are not associated with, affiliated with, or endorsed by Anthropic, Claude, or any other AI service providers. Happy is a third-party client that works with various AI APIs.

Open Source Commitment

As an open-source project under the MIT License:

  • All source code is publicly auditable
  • You can verify our privacy practices yourself
  • You can modify and distribute the software freely
  • Community contributions and security reviews are welcome

Changes to Privacy Policy

Since Happy is open source, changes to this privacy policy will be reflected in the source code repository. We recommend checking the repository periodically for updates.

Contact

For questions about this privacy policy or Happy in general, please visit our GitHub repository or open an issue in the project's issue tracker.


Happy โ€” Free & Open Source Mobile and Web Client for Coding Agents

MIT Licensed ยท Community Driven ยท Privacy First


Terms of Use

Last updated: July 15, 2026

Acceptance of Terms

By downloading, installing, or using Happy, you agree to be bound by these Terms of Use. If you do not agree to these terms, do not use Happy.

About Happy

Happy is a free, open-source mobile and web client for Claude Code and Codex, released under the MIT License. The software is provided as-is by the open-source community without any warranties or guarantees.

License

Happy is licensed under the MIT License. This means you are free to:

  • Use the software for any purpose, including commercial use
  • Modify the source code
  • Distribute copies of the software
  • Distribute modified versions

The full MIT License text is available in the source code repository.

Acceptable Use

You agree to use Happy responsibly and in compliance with all applicable laws. You must not:

  • Use Happy for any illegal or unauthorized purpose
  • Attempt to harm, disable, or impair the functionality of Happy
  • Use Happy to generate harmful, offensive, or inappropriate content
  • Violate the terms of service of any AI services you connect to through Happy
  • Attempt to reverse engineer security features or encryption protocols

Third-Party Services

Happy may connect to third-party AI services (such as Claude, OpenAI, etc.). You acknowledge that:

  • You are responsible for complying with their terms of service
  • You need valid API keys and accounts with these services
  • Happy is not responsible for the availability or performance of third-party services
  • Costs associated with API usage are your responsibility

Independence and Disclaimers

Happy is an independent, community-driven project. We are not affiliated with, endorsed by, or connected to Anthropic, Claude, OpenAI, or any other AI service providers. Happy is a third-party client that works with publicly available APIs.

Limitation of Liability

IMPORTANT: Happy is provided "AS IS" without warranty of any kind. The developers, contributors, and distributors of Happy shall not be liable for:

  • Any direct, indirect, incidental, or consequential damages
  • Data loss, corruption, or security breaches
  • Interruption of business or loss of profits
  • Costs of substitute goods or services
  • Any claims arising from your use of third-party AI services
  • Any damages resulting from software bugs, errors, or malfunctions

Your use of Happy is entirely at your own risk.

Data and Privacy

Happy collects limited, pseudonymous product analytics to measure core action success and identify bugs. We do not collect message content, code, or other encrypted session content. See our Privacy Policy for details.

Intellectual Property

Happy respects intellectual property rights. As an open-source project:

  • The source code is available under the MIT License
  • You retain ownership of any code or content you create using Happy
  • You are responsible for ensuring your use complies with applicable IP laws
  • Third-party AI services have their own intellectual property policies

Modifications to Terms

These terms may be updated from time to time. Changes will be reflected in the source code repository and on this website. Your continued use of Happy after any changes constitutes acceptance of the new terms.

Termination

You may stop using Happy at any time by uninstalling the software. These terms remain in effect regarding your past use of Happy and any ongoing obligations or liabilities.

Governing Law

These terms shall be governed by and construed in accordance with the laws of the jurisdiction where you use the software, without regard to conflict of law principles.

Contact

For questions about these Terms of Use, please visit our GitHub repository or open an issue in the project's issue tracker.


Happy โ€” Free & Open Source Mobile and Web Client for Coding Agents

MIT Licensed ยท Community Driven ยท Use at Your Own Risk


File: content/happy2/comparisons/buzz.mdx

Happy (2) vs Buzz

Block launched Buzz (source, engineering deep-dive, HN discussion) a day before we announced Happy (2). We read the codebase.

We agree on more than we disagree on: open source, self-hosted, agents as first-class participants, one server that owns the truth, and the principle that an agent should never assume human credentials. Here is where the designs split.

area happy (2) buzz
agent identities identity == context where you run: channel history + agent state + sandbox named keypair personas (fizz, honey, bumble) you drag between channels, times everyone on the team
running agents the server owns execution via Rig, our shared runtime; every channel gets its own docker sandbox with checkpoint/resume, background terminals, subagents the relay stores agent profiles but runs nothing; the model runs wherever someone runs a harness
sync telegram-style: server sequence + getDifference, revoked state gets removed, realtime is just a hint to come sync replay the signed event log: capped replay, timestamp cursor; once delivered, it's yours forever
permissions the grant IS the tool surface, so you can't attempt what you weren't given agent carries full buzz-cli + a private key; allowed = discovered by attempting
secrets attached, not pasted: bound to an agent or channel, injected into the sandbox at run time, never prompt text BUZZ_PRIVATE_KEY straight in the agent's env; per-call approval bypassed by default
plugins containers behind a capability-only API: MCP tools for agents, app surfaces for the UI, permissions per install no installable surface, so you extend via MCP servers, workflows, or new event kinds baked into relay + clients
self-hosting npx happy2, one process orchestrates everything (docker only for the sandboxes) docker compose: rust relay + postgres + redis + minio

Two more differences worth naming. Documents in Happy (2) are collaborative, with incremental updates, presence, and agents proposing while humans approve. Buzz has single-author notes with last-write-wins, so a concurrent write just loses. And app previews: port sharing is itself a plugin in Happy (2), letting an agent expose a sandbox port at a URL under your domain, to an audience of your choice. Buzz has no equivalent.

Where Buzz wins today: the UI. Ours is worse, for now. They mostly copied Slack, but copied it well, and the onboarding is genuinely nice. The hard part is the overall UX of supervising agents, not solved by anyone yet.

By @Ex3NDR & @bra1n_dump


File: content/happy2/guides/self-hosting.mdx

Self-Hosting

Happy (2) is self-hosted by design. npx happy2 runs the complete app (server, web app, and the private Rig runtime) as one process. Docker is only needed for agent sandboxes.

Configuration

Behavior comes from a TOML file, resolved in this order:

  1. --config /path/to/happy2.toml
  2. HAPPY2_CONFIG=/path/to/happy2.toml
  3. ./.happy2/happy2.toml, when it exists
  4. Built-in defaults

Configuration is partial: Happy (2) recursively merges your fields over the defaults, so exposing the listener to your network is this much file:

toml
[server]
host = "0.0.0.0"

Relative database, file, plugin, key, and agent paths resolve from the directory where Happy (2) starts, not from the TOML file's directory.

Behind a reverse proxy

For a deployment such as https://happy.example.com, the listener can stay on 127.0.0.1. Set the public origin and the exact number of proxies in front of you:

toml
[server]
public_url = "https://happy.example.com"
trusted_proxy_hops = 1

[jwt]
issuer = "https://happy.example.com"

trusted_proxy_hops is what decides how far Happy (2) trusts forwarded headers, so it must match your actual topology. Binding server.host = "0.0.0.0" is only necessary when another machine or container connects directly.

Authentication

Exactly one authentication method may be enabled at a time: password (the default), magic link, OIDC, or Cloudflare Access. Set auth.password.enabled = false before enabling another one.

toml
[auth.password]
enabled = true

[auth.magic_link]
enabled = false
# from = "Happy (2) <[email protected]>"

[auth.oidc.example]
enabled = false
# discovery_url = "https://id.example.com/.well-known/openid-configuration"
# client_id = "happy2"
# client_secret_env = "HAPPY2_OIDC_EXAMPLE_CLIENT_SECRET"

[auth.cloudflare_access]
enabled = false
# team_domain = "https://team.cloudflareaccess.com"

SMTP credentials for magic-link auth always come from the environment (EMAIL_SMTP_HOST, EMAIL_SMTP_PORT, EMAIL_SMTP_USER, EMAIL_SMTP_PASSWORD) and never from the TOML file. OIDC client secrets are named by environment variable rather than written inline.

Keys and secrets

Session tokens are RS256-signed. If you do not supply keys, an all or auth server generates a 3072-bit key pair and writes HAPPY2_JWT_PRIVATE_KEY_B64 and HAPPY2_JWT_PUBLIC_KEY_B64 into the private .env beside the selected TOML path, which is ./.happy2/.env by default, created with mode 0600. It also generates the password pepper and the integration secret when those are missing.

Real process environment values take precedence over that file. Back it up and keep it private:

  • Replacing the JWT keys invalidates every existing session token.
  • Replacing the password pepper prevents existing password hashes from verifying.

You can supply PEM files instead:

toml
[jwt]
private_key_path = "/run/secrets/happy2-jwt-private.pem"
public_key_path = "/run/secrets/happy2-jwt-public.pem"

An api-only server must be given the matching public key, because it does not generate a signing pair.

Splitting the deployment

server.role selects what an instance does:

  • all: authentication plus the product API. The default.
  • auth: authentication only, as a separately deployed identity service.
  • api: validation only, using a public key you provide.

happy2 web serves only the SPA and proxies /v0 to a backend given by HAPPY2_BACKEND_URL. It has its own CLI options rather than reading the server TOML.

Files and quotas

toml
[files]
provider = "local"
directory = ".happy2/files"
max_upload_bytes = 536870912
per_user_quota_bytes = 0   # zero disables the quota
server_quota_bytes = 0
# malware_scanner_command = "/usr/local/bin/clamscan"
malware_scan_failure_mode = "deny"

If you configure a malware scanner, decide deliberately whether a scan failure should deny or allow the upload.

Rate limits and idempotency

Both are on by default and worth reviewing before you expose the server:

toml
[security.rate_limit]
enabled = true
reads_per_minute = 1200
writes_per_minute = 300
auth_per_minute = 30

For the complete TOML reference, see the server documentation.


File: content/happy2/agents.mdx

Agents & Permissions

Most agent products give you personas: named characters with keys, dragged from room to room. Open the app and three of them greet you. Multiply that by everyone on the team and you get a directory of AI goobers nobody asked for.

Happy (2) takes a different position, and it has two halves.

An agent is a user

Creating an agent creates an ordinary user row with kind = "agent": a real username, an avatar, a profile, a place in the member directory, and a normal two-person conversation with you. There is no agent-specific chat type and no bot-integration surface. Agents send messages through the same path humans do; they simply never accumulate unread badges.

That is what makes an agent addressable, mentionable in a member list, and a member of a channel rather than a feature of it.

Its identity is the room

What the agent is at any moment is the channel it is working in: that channel's history, that channel's agent state, and that channel's sandbox. There is no portable persona carrying context between rooms.

One default agent is created when you set the server up. It is a member of every channel, the sender of service messages, and every person gets one permanent conversation with it. You are not assembling a cast before you can start.

Each chat can override the model and the thinking effort for its agent, and changing either leaves a visible service message in the timeline rather than silently altering behavior.

How an agent is addressed

Not by typing a name in prose. A message is explicitly addressed to the agents in the chat, which reaches the channel's default agent plus any agents you name. Mention-driven invocation in prose is not how it works today.

Every chat gets a container

Agents execute server-side through Rig inside a Docker or Podman container. The rootfs is read-only, temporary directories are tmpfs, and only the home and workspace directories are mounted in. A child channel shares its parent's container while keeping its own history and settings.

Because the sandbox belongs to the chat rather than to a browser session, the work survives you closing the tab, and a teammate opening the same channel is looking at the same running thing. You can attach a real terminal to that container from the browser.

Agent work is durable, not in-flight: the message and the agent's work item commit in one transaction, a leased worker picks it up, and an interrupted turn resumes after a server restart.

Permissions

There are two boundaries, and they do different jobs.

The container is the blast radius. Whatever the agent does, it does inside a sandbox with a read-only root and access to exactly one workspace.

The grant is the tool surface. The tools an agent can call are the ones resolved for it, meaning plugin tools from installations an administrator approved, with permissions declared in the plugin manifest and granted at install time. An agent does not discover its limits by attempting things and reading errors; the tools it was not given simply do not exist in its surface.

Server capabilities are separate again: concrete permissions such as manageSecrets, managePlugins, viewAllMembers, and resetPasswords, assignable directly or through custom roles.

We agree with the rest of the field on one prior point: an agent should never assume a human's credentials.

Secrets are attached, not pasted

A secret is bound to an agent or a chat and forwarded to the runtime at execution time. It never becomes prompt text, and Happy (2) never persists the value. Only the assignment lives in Happy's database; the value is not stored and is never returned to a client.

What is not solved

Some work belongs on your own machine: native builds, your fastest hardware, a device plugged into your desk. Happy (2) runs agents on the server, so that case is currently unaddressed. We would rather say so than pretend the tradeoff does not exist.


File: content/happy2/announcement.mdx

Announcing Happy (2)

We are building Happy (2), an open source multiplayer AI stack. A self-hosted, Slack-like workspace where people and coding agents build together, from the authors of Happy. The code is public: github.com/slopus/happy2.

Why another one of these

Exactly a year ago we shipped Happy, the end-to-end encrypted mobile app for Claude Code and Codex. It works, people use it every day, and it taught us the thing we actually wanted to build next.

Agents stopped being a single-player tool. You run several at once, they take hours, they produce work other people need to see, and they need somewhere to keep state. A phone remote is the wrong shape for that. A shared workspace is the right one.

So Happy (2) starts from a different question: what would Slack be if agents came first? Not a chat app with a bot in it, but channels where the agent has its own history, its own state, its own sandbox, and only the tools you granted it.

What it does today

  • One server owns the truth. Channels, files, documents, and agent state live in one place you host. Clients reconcile against it instead of replaying an event log.
  • Agents actually run. Execution happens on the server through Rig, our shared runtime. Every chat gets its own container.
  • Agents are users. Username, avatar, profile, directory. A member of the room, not a bot bolted to the side of it.
  • Identity is context, not a persona. What the agent knows is its channel history, its state, and its sandbox, not a named character you drag between rooms.
  • The work is durable. Your message and the agent's work item commit together; an interrupted turn resumes after a restart.
  • The grant is the tool surface. An agent cannot attempt what it was not given.
  • Plugins are containers. They sit behind a capability-only API: MCP tools for agents, app surfaces for the UI, permissions per install.
  • Documents are collaborative. Incremental updates and presence, with agents proposing and humans approving.
  • One command to run all of it. npx happy2. Docker is only needed for the sandboxes.

What is still missing

The UI is worse than what you are used to, for now. The hard part is not the chat surface. It is the overall UX of supervising agents, and nobody has solved that yet, including us.

There is no hosted version. Self-hosting genuinely is one command, but if you want someone else to run it for you, that does not exist today.

Compared to Buzz

Block launched Buzz a day before this post, and we share a lot with it: open source, self-hosted, agents as first-class participants, and the principle that agents should not assume human credentials. We read the codebase. The designs split in interesting places: see Happy (2) vs Buzz.

Want to build this?

@Ex3NDR and @bra1n_dump are working on this full time. We are looking for a GTM partner with a track record. DMs open.


File: content/happy2/how-it-works.mdx

How It Works

Happy (2) is one server, one database, and clients that reconcile against it. There is no peer-to-peer state, no event log to replay, and nothing important stranded on someone's laptop.

One server owns the truth

A small Fastify server owns authentication, persistence, files, collaboration state, realtime updates, and agent execution. You run it, so channels, messages, documents, files, agent state, grants, and secrets stay on infrastructure you control.

The server can run in three roles: all (authentication plus the product API), auth (authentication only, as a separately deployed identity service), or api (validation only, given the matching public key). The default is all, which is what npx happy2 starts.

Sync is reconciliation, not replay

Clients hold a sequence number and ask the server what changed. Realtime events over the stream are only a hint that something happened, a delivery notification and never durable state. The client then reconciles through the difference API.

This is the Telegram model rather than the event-log model, and the practical difference shows up in two places. Revoked state actually disappears, because the client re-derives from the server instead of replaying everything it was ever handed. And a client that has been offline for a week catches up with one difference call instead of a capped replay window.

Every retried mutation carries one idempotency key across all attempts, so a retry after a dropped connection cannot duplicate work.

Agents run in sandboxes

Agent execution happens on the server through Rig, our shared runtime. Happy (2) manages its own private Rig daemon under .happy2/rig and never touches a Rig you installed globally.

Every chat gets a container, Docker or Podman, chosen once when you set the server up. The rootfs is read-only, /tmp and friends are tmpfs, and only the workspace and home directories are mounted in. Agent working directories live under .happy2/workspaces: a channel gets its own, and a direct message gets a per-person one, so one person's files never leak into someone else's conversation.

Sending a message to an agent does not open a long-lived request. The message and one work item per addressed agent commit in a single transaction, and a leased worker picks the item up. That is why an agent keeps working when you close the tab, why a teammate opening the same channel sees the same run, and why an interrupted turn resumes after the server restarts.

The honest tradeoff: some work you genuinely want local, on your own machine, your fastest hardware, your local toolchain. Server-side execution does not cover that case yet.

Files

Files are served through short-lived signed URLs, and access is an explicit grant: a user, a chat, or the whole server, optionally expiring. You can set per-user and server-wide quotas, an expiry for incomplete uploads, and a quarantine retention window. An optional malware-scanner command runs before a file becomes available, and you choose whether a scan failure denies or allows the upload.

Alongside files, every chat exposes its agent's workspace as a browsable tree with an editor: live filesystem invalidation, background Git status, and saves that detect a conflicting write instead of clobbering it.

Plugins

Plugins are containers that talk to a dedicated capability-only host API, a separate listener from the main server that defaults to port 3001. A plugin exposes MCP tools to agents and app surfaces to the UI, and receives permissions per install. See Plugins.

Clients

Happy (2) is a desktop product. There is no mobile app and no mobile layout.

The web app is the full product: one React application, served by the same process that runs the server. In the all-in-one mode the API listens on an ephemeral loopback port and the SPA is served on the public one, with /v0 proxied through internally, so the browser sees a single origin for HTTP, uploads, SSE, and WebSockets. Web sessions authenticate with an HttpOnly cookie, so no token is ever exposed to JavaScript.

There is also a macOS Electron app, which is a different and smaller thing: it is a client to a Rig runtime on your machine, or a window onto a Happy server you point it at. The complete workspace, meaning channels, documents, plugins, and administration, comes from a Happy server.

The pieces

Package Responsibility
happy2-server Authentication, persistence, files, collaboration, agent execution
happy2-state Immutable client state and realtime reconciliation, framework-independent
happy2-ui Reusable design system and cross-browser visual coverage
happy2-app The shared React application for web and Electron
happy2-web Browser entry point and production web build
happy2-desktop macOS Electron app
happy2-gym Isolated black-box server, state, and browser testing environment

File: content/happy2/index.mdx

Welcome

Happy (2) is an open source multiplayer AI stack: a self-hosted, Slack-like workspace where people and coding agents build together. Conversations, files, documents, workspaces, and agents that actually run live in one app, on infrastructure you control.

It is a ground-up next chapter from the authors of Happy, built on what we learned bringing coding agents into real daily work.

sh
npx happy2

That is the whole install. Open http://127.0.0.1:3000 and you have a workspace.

What you get

  • Channels, DMs, and projects. Public and private channels, direct and group messages, child channels, reactions, pins, bookmarks, read receipts, and fuzzy search across people, channels, and messages.
  • Agents that are users. An agent has a username, an avatar, a profile, and a place in the member directory. It is a member of the room, not a bot you summon.
  • Agents that actually run. Execution happens on the server through Rig, our shared runtime, inside a Docker or Podman container per chat, with real terminals you can attach to from the browser.
  • Work that survives. An agent turn is a durable server obligation, not an in-flight request. Close the tab, restart the server: the turn resumes.
  • Collaborative documents. Real CRDT editing with live presence, and when an agent wants to write, a human approves it.
  • Files and workspaces. Signed URLs, explicit access grants, quotas, an optional malware-scanner hook, and a browsable workspace tree with Git status.
  • Plugins as containers. Each one sits behind a capability-only API: MCP tools for agents, app surfaces for the UI, permissions granted per install.
  • Roles and secrets. Custom roles over concrete permissions, and agent secrets Happy forwards once and never stores.

Where to go next

Honest status

Happy (2) is early. Version 0.0.x, weeks old, moving fast. The source is public at github.com/slopus/happy2, self-hosting genuinely is one command, and there is no hosted version. The UI is rougher than what you are used to; the hard part is the overall UX of supervising agents, and nobody has solved that one.

Two things worth knowing before you try it. Happy (2) is desktop-only. There is no mobile app, and that is a deliberate choice rather than a gap we plan to fill. And Happy (2) does not hold your model credentials: you authenticate model providers through Rig, which owns the agent loop.


File: content/happy2/plugins.mdx

Plugins

A plugin in Happy (2) is a container, not a browser bundle and not code running inside the app. It talks to Happy through a capability-only host API and gets exactly the permissions granted when it was installed.

What a plugin can offer

  • MCP tools for agents. Tools from a ready installation are handed to the agent on every submission, so an agent in a channel can call them directly.
  • Skills. Agent skills are reconciled into the sandbox before each turn.
  • Apps. An HTML resource rendered in an iframe, either a navigable sidebar destination or a detached overlay.
  • Contributions. Native controls at Happy-owned placements: the sidebar menu, the chat menu, the composer, the message menu, a settings section. Each one is bound to exactly one tool.

Extending the workspace does not mean forking it, and installing something does not mean handing it the server.

The container boundary

Plugin containers are locked down harder than agent containers: all capabilities dropped, no new privileges, and explicit memory, CPU, and process limits. There is one container per installation, not per plugin, so two configured copies of the same plugin never share state.

The host API

Plugin containers connect to a dedicated listener, separate from the product API:

toml
[plugins]
directory = ".happy2/plugins"
host_api_host = "0.0.0.0"
host_api_port = 3001

It carries none of the /v0 product routes. Every route is permission-gated, and the token a container authenticates with encodes its installation, its container incarnation, and the permissions it was granted. It binds to all interfaces by default so containers can reach it, so firewall it from untrusted networks.

Installing and managing plugins is administrator-only. You can install from the built-in catalog, a ZIP upload, an HTTPS link, or a GitHub repository.

An agent can ask; a human approves

An agent's tool call gets a short-lived token bound to the session, the call, the human who triggered it, the agent, and the chat. That is enough for an agent to stage a plugin installation as a durable request in the timeline, which an administrator then approves. The agent cannot grant itself capabilities. The request is a message, not an action.

Built in

The repository ships several plugins, which double as the reference implementations for the SDK:

Plugin What it does
Chat management Create projects, channels, and child channels; update chat metadata; send messages
Documents Read chat documents and propose block edits that wait for member approval
Environment management List, create, reactivate, and set a default for the agent's own containers
Port sharing Expose a container port at a public URL with a chosen audience
To-dos Multi-instance lists with their own apps, sidebar instances, and storage
Plugin developer Stage plugin installs and uninstalls for human approval

hello and movie-catalog also ship, as minimal examples rather than things you would keep installed.

Port sharing

Port sharing is itself a plugin, and it is the clearest demonstration of the model: an agent exposes a port from its sandbox at a public URL, to an audience you choose (the internet, everyone on the server, or just that chat) without anything else in the system learning about ports.

toml
[port_sharing]
public_domain = "preview.example.com"

Omit the table to disable public agent-port sharing entirely. When enabled, configure wildcard DNS and TLS for *.preview.example.com pointing at the same Happy web listener.

Access is re-checked against durable state on every request, HTTP and WebSocket alike. Removing someone from the chat revokes their live preview immediately rather than at token expiry.

Not yet

There is no marketplace, no in-place upgrade, and no OAuth for remote MCP endpoints. Update checks report that an installed snapshot has drifted from its source, deliberately without replacing it.