Claude's cooking. Chat with your squad. Friends online, right beside your Claude Code session. Zero tokens, zero leaks to Claude.
JavaScript
1
29 commits
updated Oct 7, 2026
Claude's cooking. Chat with your squad.
Friends online, right beside your Claude Code session. Zero tokens, zero leaks to Claude.
Explore the commands »
View Demo
·
Report Bug
·
Request Feature
Signing in, joining a room, chatting while a friend is typing, switching rooms when a new message comes in, and picking a new name with /chat-name.
squad-chat puts a group chat next to your Claude Code conversation. You keep working with Claude on the left while your friends' messages come in on the right.
/chat command opens a pane: no browser tab, no extra app.It is a Claude Code mod: a plugin of function hooks, plus a small Node process that holds the connection to Supabase. docs/ARCHITECTURE.md explains how the pieces fit.
PATH:
node --version
/tui fullscreen) and a terminal at least 110 columns wide.[!NOTE] Claude Code decides where the pane goes, not the mod. Below 110 columns the pane opens above the prompt in a compact layout. While it's closed, a one-line summary sits above the prompt with an Open button.
The repository is its own plugin marketplace.
claude plugin marketplace add chrisluo5311/squad-chat
claude plugin install squad-chat@squad-chat
Or, from inside Claude Code:
/plugin install squad-chat --marketplace chrisluo5311/squad-chat
/reload-plugins./chat.To update later:
claude plugin marketplace update squad-chat && claude plugin update squad-chat@squad-chat
If you host your group's server, also run supabase db push again from an updated clone, so the server has what the new version needs. For example, typing indicators need 0.5.0's database change.
To uninstall:
claude plugin uninstall squad-chat@squad-chat && claude plugin marketplace remove squad-chat
To try it without installing:
git clone https://github.com/chrisluo5311/squad-chat.git
claude --plugin-dir ./squad-chat/plugins/squad-chat
squad-chat has no central server. Each group of friends shares one Supabase project, its server: one person hosts it on Supabase's free plan, and everyone else connects with two values from them:
https://abcd1234.supabase.cosb_publishable_… (safe to share, unlike the secret key, which you never share)Set them when you install:
claude plugin install squad-chat@squad-chat \
--config supabase_url=https://abcd1234.supabase.co \
--config supabase_key=sb_publishable_...
or later, from /config in Claude Code (squad-chat's options), or from a shell:
echo '{"supabase_url":"https://abcd1234.supabase.co","supabase_key":"sb_publishable_..."}' \
| claude plugin configure squad-chat@squad-chat --values-stdin
Until a server is set, the pane says so and shows these steps.
/chat opens the pane./room our-team some-passcode
Your friends join with the same line.[!IMPORTANT] An account made with just a name can't be recovered. It has no email, so once you sign out, delete
~/.config/squad-chator switch computers, you can't sign back into it. Signing in again makes a new account: rejoin your rooms with their passcodes and you'll see their history again. Messages from the old account stay in the rooms until they expire after 30 days. Signing in by email doesn't have this problem.
| Command | What it does |
|---|---|
/chat | Open the pane |
/say <message> | Send a message to the current room from the prompt |
/room | List your rooms |
/room <name> | Switch to a room you're in (or click its tab) |
/room <name> <passcode> | Create a room, or join a friend's |
/room leave <name> | Leave a room. Rejoin any time with its passcode. |
/room delete <name> | Delete a room you created, with all its messages, for everyone. Run it twice to confirm. |
/who | Who's online, across all your rooms |
/chat-login <email>, then /chat-login <code> | Sign in by email from the prompt instead of the pane |
/chat-login <name> | Sign in with just a name, where the server allows it |
/chat-name <new name> | Change your display name. Your friends see the new one right away. |
/chat-logout | Sign out on this computer |
/chat notify on / off | Toast when someone writes @yourname (off by default) |
The pane's input box takes /room, /who, /name, /logout and /help too. Type passcodes there: it never touches the conversation.
| Where | What you see |
|---|---|
| Docked (fullscreen, ≥ 110 columns) | Room tabs, a FRIENDS card, and the room's messages as bubbles: yours on the right, theirs on the left, grouped by sender, with date labels and a new line where you stopped reading |
| Above the prompt (narrower) | The room, who's online, the last five messages and the input box |
| Pane closed | One line: the room, who's online, unread count, the latest message and Open |
| Status line | Unread counts per room, such as 💬 #team 3 |
Each account needs its own config folder. Start the second Claude Code with:
SQUAD_CONFIG_DIR=~/.config/squad-chat-b claude
Gmail delivers you+b@gmail.com to you@gmail.com, which makes a handy second account for trying it out.
/say, /room and /chat-login are replaced with a placeholder before Claude Code stores the command, and command answers are notices the model never reads. Claude Code still keeps a slash command's raw text in one bookkeeping line of the local transcript on your own disk, so type passcodes in the pane if that matters to you.@) and whether you're online. Never your email.~/.config/squad-chat/session.json, readable only by you, and /chat-logout removes it. An account made with just a name can't be signed back into once you sign out, so /chat-logout asks twice.Found a security problem? Please report it privately, as described in SECURITY.md.
Want to help? CONTRIBUTING.md covers setting up, the tests and how to send a pull request.
# The mod
claude plugin validate ./plugins/squad-chat # check the manifest and hooks
claude plugin test ./plugins/squad-chat # mod tests, against a fake bridge
claude --plugin-dir ./plugins/squad-chat # run Claude Code with this checkout
# The bridge
cd plugins/squad-chat/bridge
npm install && npm run build # rebuild dist/bridge.mjs after editing src/
npm test # two users, two bridges, local Supabase
# The database
supabase start # local stack on ports 56420-56429
supabase test db # pgTAP access-control tests
supabase db advisors --local --type all
To run the mod against the local stack, start Claude Code with:
SQUAD_SUPABASE_URL=http://127.0.0.1:56421 \
SQUAD_SUPABASE_KEY=<local publishable key from `supabase status`> \
SQUAD_CONFIG_DIR=$(mktemp -d) \
claude --plugin-dir ./plugins/squad-chat
Sign-in emails land in the local mail UI at http://127.0.0.1:56424.
| Path | Contents |
|---|---|
plugins/squad-chat/hooks/squad-chat.mjs | Hooks: commands, pane, band, status line, the bridge client, keeping chat out of the conversation |
plugins/squad-chat/hooks/state.mjs | State built from the bridge's events |
plugins/squad-chat/hooks/commands.mjs | Slash commands and the pane's input box |
plugins/squad-chat/hooks/views.mjs | The docked pane, the compact pane and the band |
plugins/squad-chat/hooks/theme.mjs | Colors and glyphs |
plugins/squad-chat/bridge/src/ | The Node bridge (bundled into bridge/dist/bridge.mjs) |
plugins/squad-chat/tests/ | Mod tests |
bridge-tests/ | Bridge tests against a local Supabase |
supabase/migrations/, supabase/tests/ | Schema, RLS and pgTAP tests |
docs/ARCHITECTURE.md | How it fits together, and why |
One person per group does this, once. It fits in Supabase's free plan.
supabase link --project-ref <your-project-ref>
supabase db push
In Resend, add and verify a domain you own, such as mail.example.com.
Create an API key with Sending access, restricted to that domain.
In Supabase, open Authentication → Emails → SMTP Settings, turn on Enable custom SMTP, and fill in:
| Field | Value |
|---|---|
| Sender email | an address on your domain, such as login@mail.example.com |
| Sender name | squad-chat |
| Host | smtp.resend.com |
| Port | 465 |
| Username | resend |
| Password | the Resend API key |
Under Authentication → Emails → Templates, edit Confirm signup and Magic Link so they show the code. For example, subject Your squad-chat code and body:
<h2>squad-chat</h2>
<p>Your sign-in code:</p>
<p style="font-size:28px;font-weight:bold;letter-spacing:4px">{{ .Token }}</p>
<p>Type it into Claude Code. It expires in one hour.</p>
Try it: sign in with your own email. Each code shows up under Emails in Resend's dashboard, with its delivery status.
/chat-name to change your display nameSee the open issues for proposed features and known issues.
Distributed under the MIT License. See LICENSE for more information.
Claude's cooking. Chat with your squad. Friends online, right beside your Claude Code session. Zero tokens, zero leaks to Claude.
JavaScript
1
29 commits
updated Oct 7, 2026
Claude's cooking. Chat with your squad.
Friends online, right beside your Claude Code session. Zero tokens, zero leaks to Claude.
Explore the commands »
View Demo
·
Report Bug
·
Request Feature
Signing in, joining a room, chatting while a friend is typing, switching rooms when a new message comes in, and picking a new name with /chat-name.
squad-chat puts a group chat next to your Claude Code conversation. You keep working with Claude on the left while your friends' messages come in on the right.
/chat command opens a pane: no browser tab, no extra app.It is a Claude Code mod: a plugin of function hooks, plus a small Node process that holds the connection to Supabase. docs/ARCHITECTURE.md explains how the pieces fit.
PATH:
node --version
/tui fullscreen) and a terminal at least 110 columns wide.[!NOTE] Claude Code decides where the pane goes, not the mod. Below 110 columns the pane opens above the prompt in a compact layout. While it's closed, a one-line summary sits above the prompt with an Open button.
The repository is its own plugin marketplace.
claude plugin marketplace add chrisluo5311/squad-chat
claude plugin install squad-chat@squad-chat
Or, from inside Claude Code:
/plugin install squad-chat --marketplace chrisluo5311/squad-chat
/reload-plugins./chat.To update later:
claude plugin marketplace update squad-chat && claude plugin update squad-chat@squad-chat
If you host your group's server, also run supabase db push again from an updated clone, so the server has what the new version needs. For example, typing indicators need 0.5.0's database change.
To uninstall:
claude plugin uninstall squad-chat@squad-chat && claude plugin marketplace remove squad-chat
To try it without installing:
git clone https://github.com/chrisluo5311/squad-chat.git
claude --plugin-dir ./squad-chat/plugins/squad-chat
squad-chat has no central server. Each group of friends shares one Supabase project, its server: one person hosts it on Supabase's free plan, and everyone else connects with two values from them:
https://abcd1234.supabase.cosb_publishable_… (safe to share, unlike the secret key, which you never share)Set them when you install:
claude plugin install squad-chat@squad-chat \
--config supabase_url=https://abcd1234.supabase.co \
--config supabase_key=sb_publishable_...
or later, from /config in Claude Code (squad-chat's options), or from a shell:
echo '{"supabase_url":"https://abcd1234.supabase.co","supabase_key":"sb_publishable_..."}' \
| claude plugin configure squad-chat@squad-chat --values-stdin
Until a server is set, the pane says so and shows these steps.
/chat opens the pane./room our-team some-passcode
Your friends join with the same line.[!IMPORTANT] An account made with just a name can't be recovered. It has no email, so once you sign out, delete
~/.config/squad-chator switch computers, you can't sign back into it. Signing in again makes a new account: rejoin your rooms with their passcodes and you'll see their history again. Messages from the old account stay in the rooms until they expire after 30 days. Signing in by email doesn't have this problem.
| Command | What it does |
|---|---|
/chat | Open the pane |
/say <message> | Send a message to the current room from the prompt |
/room | List your rooms |
/room <name> | Switch to a room you're in (or click its tab) |
/room <name> <passcode> | Create a room, or join a friend's |
/room leave <name> | Leave a room. Rejoin any time with its passcode. |
/room delete <name> | Delete a room you created, with all its messages, for everyone. Run it twice to confirm. |
/who | Who's online, across all your rooms |
/chat-login <email>, then /chat-login <code> | Sign in by email from the prompt instead of the pane |
/chat-login <name> | Sign in with just a name, where the server allows it |
/chat-name <new name> | Change your display name. Your friends see the new one right away. |
/chat-logout | Sign out on this computer |
/chat notify on / off | Toast when someone writes @yourname (off by default) |
The pane's input box takes /room, /who, /name, /logout and /help too. Type passcodes there: it never touches the conversation.
| Where | What you see |
|---|---|
| Docked (fullscreen, ≥ 110 columns) | Room tabs, a FRIENDS card, and the room's messages as bubbles: yours on the right, theirs on the left, grouped by sender, with date labels and a new line where you stopped reading |
| Above the prompt (narrower) | The room, who's online, the last five messages and the input box |
| Pane closed | One line: the room, who's online, unread count, the latest message and Open |
| Status line | Unread counts per room, such as 💬 #team 3 |
Each account needs its own config folder. Start the second Claude Code with:
SQUAD_CONFIG_DIR=~/.config/squad-chat-b claude
Gmail delivers you+b@gmail.com to you@gmail.com, which makes a handy second account for trying it out.
/say, /room and /chat-login are replaced with a placeholder before Claude Code stores the command, and command answers are notices the model never reads. Claude Code still keeps a slash command's raw text in one bookkeeping line of the local transcript on your own disk, so type passcodes in the pane if that matters to you.@) and whether you're online. Never your email.~/.config/squad-chat/session.json, readable only by you, and /chat-logout removes it. An account made with just a name can't be signed back into once you sign out, so /chat-logout asks twice.Found a security problem? Please report it privately, as described in SECURITY.md.
Want to help? CONTRIBUTING.md covers setting up, the tests and how to send a pull request.
# The mod
claude plugin validate ./plugins/squad-chat # check the manifest and hooks
claude plugin test ./plugins/squad-chat # mod tests, against a fake bridge
claude --plugin-dir ./plugins/squad-chat # run Claude Code with this checkout
# The bridge
cd plugins/squad-chat/bridge
npm install && npm run build # rebuild dist/bridge.mjs after editing src/
npm test # two users, two bridges, local Supabase
# The database
supabase start # local stack on ports 56420-56429
supabase test db # pgTAP access-control tests
supabase db advisors --local --type all
To run the mod against the local stack, start Claude Code with:
SQUAD_SUPABASE_URL=http://127.0.0.1:56421 \
SQUAD_SUPABASE_KEY=<local publishable key from `supabase status`> \
SQUAD_CONFIG_DIR=$(mktemp -d) \
claude --plugin-dir ./plugins/squad-chat
Sign-in emails land in the local mail UI at http://127.0.0.1:56424.
| Path | Contents |
|---|---|
plugins/squad-chat/hooks/squad-chat.mjs | Hooks: commands, pane, band, status line, the bridge client, keeping chat out of the conversation |
plugins/squad-chat/hooks/state.mjs | State built from the bridge's events |
plugins/squad-chat/hooks/commands.mjs | Slash commands and the pane's input box |
plugins/squad-chat/hooks/views.mjs | The docked pane, the compact pane and the band |
plugins/squad-chat/hooks/theme.mjs | Colors and glyphs |
plugins/squad-chat/bridge/src/ | The Node bridge (bundled into bridge/dist/bridge.mjs) |
plugins/squad-chat/tests/ | Mod tests |
bridge-tests/ | Bridge tests against a local Supabase |
supabase/migrations/, supabase/tests/ | Schema, RLS and pgTAP tests |
docs/ARCHITECTURE.md | How it fits together, and why |
One person per group does this, once. It fits in Supabase's free plan.
supabase link --project-ref <your-project-ref>
supabase db push
In Resend, add and verify a domain you own, such as mail.example.com.
Create an API key with Sending access, restricted to that domain.
In Supabase, open Authentication → Emails → SMTP Settings, turn on Enable custom SMTP, and fill in:
| Field | Value |
|---|---|
| Sender email | an address on your domain, such as login@mail.example.com |
| Sender name | squad-chat |
| Host | smtp.resend.com |
| Port | 465 |
| Username | resend |
| Password | the Resend API key |
Under Authentication → Emails → Templates, edit Confirm signup and Magic Link so they show the code. For example, subject Your squad-chat code and body:
<h2>squad-chat</h2>
<p>Your sign-in code:</p>
<p style="font-size:28px;font-weight:bold;letter-spacing:4px">{{ .Token }}</p>
<p>Type it into Claude Code. It expires in one hour.</p>
Try it: sign in with your own email. Each code shows up under Emails in Resend's dashboard, with its delivery status.
/chat-name to change your display nameSee the open issues for proposed features and known issues.
Distributed under the MIT License. See LICENSE for more information.