buddylist
Download
All guides

The contact list

The contact list works like a status board:

Status Meaning
🟢 Online Ready.
Also while what it left in the background runs: "A command running in the background".
🔴 Busy Working. The status line says on what, such as "Running npm test".
Also while its subagents work on: "2 subagents at work".
🟠 Away Waiting for you to approve something.
⚪ Offline Its folder is gone.

A contact with something you have not seen yet is in bold, and its buddy wears the count: replies, requests and errors from a conversation you weren't looking at. Open that conversation, or click into it, and it is read.

Every conversation window has the list too, on its left: see Your contacts beside the conversation.

A contact's ⋯. Point at a contact and a ⋯ comes up at the end of its row. It opens the same menu as a right-click, which also copies the contact's folder path (Copy path) and the name of the branch it is on (Copy branch name).

Command palette

Press ⌘K on Mac or Ctrl+K on Windows and Linux in the contact list or a conversation window. Type a contact's name, project, conversation preview, file name or menu action. The best matches appear under Contacts, Conversations, Files and Actions. Use ↑, ↓ and Enter to choose, or Esc to close it.

With nothing typed, the palette lists contacts with the most recently active first, then the window's available menu actions. Typing also searches conversation previews, contact names, projects and branches, with up to eight matching conversations. A past conversation opens in message history; Continue there resumes it. Archived contacts' conversations can appear in these results even though their contacts are left out of the contact shortcuts.

In a conversation window, typing also searches the files of the contact's folder that Git doesn't ignore, with up to eight matching files. A file is found by its name and by its folders, so palette test finds test/palette.test.js. Enter opens it in a tab beside the conversation, as clicking it in All files does. The contact list has no folder, so it lists no files.

Organizing contacts

Groups. Sort your contacts into groups, such as "Work" and "Side projects":

  • Contacts > Create a group... makes one.
  • Right-click a contact and choose Move to group, or pick the group in Edit contact....
  • Right-click a group to rename or delete it. Deleting a group keeps its contacts.

Group, filter and sort. The ... button next to the search box lays the list out another way:

  • Group by lists your contacts under their Project, which is how the list starts out, or under your Groups, their Status or their Service. Grouped by project, point at a project and click the + at the end of its line for another contact on it. By status, the contacts that are working come after the ones waiting for you.
  • Filter by project shows the contacts of one project only. A line above the list says which one; click Show all there to see everyone again.
  • Sort by orders the contacts in each section by Date added, Name, Status or Last active.
  • New group... makes a group, and puts the list back on your groups so you see it.

Waiting for you is always on top, however the list is grouped: every contact that needs you to approve something, a favorite too. Its rows say which project each one works on, where the list has more than one. Once you answer, the contact goes back to its project or group. Favorites come next, then pinned projects (see Pinning below), and offline and archived contacts stay at the bottom. Your choices are kept when you quit. A project is the repository a contact's worktree is a copy of, or else the folder it works in.

Right-click a project in a list grouped by project for what can be done with all of it:

  • New contact in this project is what the + next to its name does.
  • New contact from an issue or pull request... opens the same dialog in its GitHub field: type a number or paste a link.
  • Project settings... opens the project's Settings: its scripts, variables, branches, instructions and files to copy.
  • Pin project lists it before the other projects. See Pinning below.
  • Hide project leaves its contacts out of the list. They keep working, and still tell you when they are done. Hidden projects in the list's ... menu brings one back.
  • Archive all contacts puts away every contact listed under the project, after asking: see Archiving a contact below. One that is working is stopped. Its favorites, and the ones waiting for you, are listed elsewhere and stay.
  • Delete all contacts... deletes the contacts listed under the project, after asking, and keeps what the project is set up with in Settings, and its favorites and archived contacts. Untick the ones you want to keep. Tick Also remove their worktrees to take those along: a worktree with uncommitted changes is kept, and you are told which.
  • Remove project... deletes every contact that works on it, after asking, and forgets what the project was set up with in Settings. The project's folder is not touched. Untick the contacts you want to keep: the project then stays, with them and its settings, and only the ones still ticked are deleted. Tick Also remove their worktrees to take those along: a worktree with uncommitted changes is kept, and you are told which.

Add a project. ... > Add project, also in the Contacts menu, has three ways to a project for a new contact:

  • Open project... picks a folder that is on your computer.
  • Open GitHub project... clones a repository. Type its address or owner/name, or pick one of your own: your repositories on GitHub are listed, the one pushed to last on top, and the search box narrows them down by name and description. It is cloned into a folder of its own in Location.
  • Quick start... starts a new project: a folder named after it, with a git repository and a first commit. Leave Create a private GitHub repository ticked to get one on GitHub too, as the project's origin.

Each ends in Add a Contact with the folder filled in, so you pick the service and press Enter. The next project is offered the folder the last one went in.

Your repositories are listed, and a new one is made, with the GitHub CLI: install gh and connect it once (see Connecting to GitHub below). Without it you can still clone by address, and start a project without a repository on GitHub. Listing only reads. Nothing is made on GitHub unless the box is ticked, and a project that could not be made there leaves no folder behind.

Favorites. Right-click a contact and choose Add to favorites. Your favorites are listed in a Favorites section at the top of the list.

  • A favorite keeps its group. Remove from favorites puts it back there.
  • A favorite whose folder is gone is listed under Offline, like any other contact.

Pinning. A pin keeps something where you look first, without moving it anywhere else:

  • A contact. Right-click it and choose Pin to top. It stays in its project or group, first in it, with a pin before its name. Several pinned in one section keep the order the list is sorted by. Unpin puts it back in its place. A pinned favorite is first among the favorites, and pinned and favorite are kept apart: one says nothing about the other.
  • A project. Grouped by project, right-click the project and choose Pin project. It is listed before the other projects, with a pin before its name, under Waiting for you and the favorites. Pinned projects are by name among themselves. Unpin project puts it back.
  • The list beside a conversation has the same pins, and the same right-click choices: see Your contacts beside the conversation. The pins are kept when you quit.
  • A message can be pinned too, and a window kept on top of others with the pin by its buttons.

Conversations a contact started. A Claude contact can start another conversation for a side task. It is listed right under the one that started it, joined to it by a line, and that one shows how many are under it.

Chat tabs. The chats opened with the + over a conversation, in tabs of the same window, are listed under the first of them the same way. They are not counted with the conversations it started.

Archiving a contact. Done with a project for now? Right-click its contact and choose Archive contact. The contact is put away, not deleted:

  • It stops, and its conversation window closes. If it is working or waiting for you, you are asked first.
  • It moves to the Archived section at the bottom of the list. That section stays folded until you click it.
  • Its message history, its folder and its worktree are kept.
  • It leaves the conversations it was a guest in. Its own guests stay invited.
  • While it is archived, you can't message or invite it, and it is left out of the menu-bar menu and its counts.

Double-click an archived contact to read its message history. Its right-click menu has Restore contact, View message history, Open folder and Delete contact.

Restore contact brings it back as it was, with its group, its model and its mode. Its conversation picks up where it left off. It is not invited back into the conversations it left.

Search in all conversations. The search box at the top of the list filters your contacts by name and folder. From two characters on, it also looks through every contact's conversations: the current one and the past ones, in any letter case.

  • The contacts whose conversations contain your text are listed under Conversations, each with a line from its newest match and the text marked.
  • Point at one to see how many of its conversations contain the text.
  • Double-click one, or press Enter on it, to open its message history with the search already filled in.
  • Archived contacts are searched too.
  • Contacts > View all message history... lists every contact's conversations in one window, newest first, with its own search: see Message history.

A worktree for every contact. A contact added in a git repository always gets its own worktree of it, on a new branch. The folder you picked is never the one its agent changes, and two contacts never change each other's files:

  • Contacts > Add a contact..., the + next to the search box and ⌘N in the contact list ask for the project's folder. It is already the project of the contact you added last, with that contact's service, picture, group, model and mode, so pressing Enter adds another contact there; Browse... picks another project. With the list showing one project only, it is that project's last contact. The branch field can be left empty, so pressing Enter is enough: the branch then starts out named after the project and a number, such as shop-2, and is renamed after the first thing you ask the contact to do: "Fix the login redirect" makes it fix-the-login-redirect. The nickname made up from the branch follows it: Claude (shop-2) is Claude (fix-the-login-redirect) from then on. A nickname you typed yourself, or one that came from an issue, is kept. The worktree's folder stays where it is, and a branch you named yourself, switched away from or already pushed keeps its name, and the contact its nickname. Type a name in the field for one of your own. The branch starts from the remote's main line, fetched while you fill in the dialog, or from where the folder is. A project can name another branch to start from in its Settings. Making the worktree takes a few seconds in a big project: the dialog says what it is doing.
  • A team to start with. Team in the dialog picks agents that join the new contact's conversation with it, such as a reviewer that looks over every change. It starts out as the team of the contact the dialog starts from. Edit teams... beside it opens Settings at Teams. See Roles and teams.
  • Tools > Branch prefix... puts something of yours in front of every branch the app names, such as safa/feature: the branch is then safa/feature/shop-2, and safa/feature/fix-the-login-redirect once it is named after the work. A name you type yourself is taken as it is. Names the app makes hold plain letters, numbers and dashes only: Mağaza Önü is written magaza-onu.
  • Another contact on the same project. Point at the project in the list and click the + at the end of its line, or right-click one of its contacts and choose New contact in this project.... The dialog opens with the same service, picture, group, model and mode, so there is no folder to browse for.
  • A contact like the ones in a section. When the list is grouped by groups, status or service, every section but Waiting for you, Offline and Archived has a + at the end of its line too. The dialog starts out like the contact added last in that section, on its project, and Browse... still picks another project. A group's + puts the new contact in that group. An empty group's + starts like the contact you added last.
  • A folder that is not a git repository, or has no commit yet, has nothing to make a worktree of. The contact works in the folder itself, and a contact added from it shares the folder.
  • A contact added to your list from a conversation's Invite dialog is there to join that conversation, so it gets no worktree: it works in its host's folder. See Group conversations.

Worktrees go in ~/.buddylist/worktrees/<project>/<branch>, whichever service the contact uses. The ones made while the app was called Agent Messenger stay in ~/.agent-messenger/worktrees/, since an agent finds its session by its folder, and work as before. Files git doesn't track, such as node_modules and .env, are not copied into a worktree unless the project says so: its Settings can name files to copy, and a setup script to run in each new worktree.

A worktree's Claude Code settings come from the main checkout. A worktree's branch can be anyone's, a pull request from a fork too, and Claude Code runs here without asking whether to trust a folder. So a Claude contact in a worktree reads the project's settings from the same folder in the main checkout: .claude/settings.json with its hooks and allow rules, .claude/settings.local.json, .mcp.json, and the commands, agents, skills and output styles in .claude. What the branch has in them never runs. A change you make to them on a branch holds once it is in the main checkout. Always allow in a worktree is kept in the main checkout's .claude/settings.local.json, so every contact on the project has it. A contact working in the main checkout itself, or in a folder outside a repository, reads them where it works, as before. The conversation is still kept by the worktree's folder, so it is picked up as before.

Start from a GitHub issue or pull request. A contact added in a git repository can start from one. Both ways of adding it show a Start from a GitHub issue or PR field. Click it for the project's open pull requests and issues, yours first, and type words from a title to narrow them down; words that match none of them are searched for on GitHub. Or type a number, such as 123 or #123, or paste a link. The app looks it up with the GitHub CLI in the project's folder and fills in the rest:

  • An issue names the contact after its title, and the branch after its number and title, such as 123-fix-login-redirect. You can still change both.
  • A pull request names the contact after its title too. Its worktree checks out the pull request's own branch instead of a new one, so what the contact pushes goes to the pull request. That works for a pull request from a fork as well. A branch that is already checked out in another folder is refused, and you are told where. Hooks, allow rules and MCP servers the pull request adds to the project's Claude Code settings don't run: a Claude contact reads them from the main checkout (see above).
  • A pull request's worktree is not set up by itself. The project's setup script would run the pull request's code on your computer: installing runs a package's own scripts. Its conversation says the script waits, and Run setup in the Setup tab runs it once you have looked the changes over.

The title, the text and the link wait in the new conversation's message box as a draft. Nothing is sent: add what you want done and press Enter. The draft is still there after you close the window or restart the app. It goes away with your first message, or when you start a new conversation.

A closed or merged issue or pull request works too, and the dialog says that it is. The link has to be for the project's own repository. Looking it up only reads from GitHub. It needs gh installed and connected.

Deleting a contact never touches the folder it was added from. Its worktree stays too, unless you tick Also remove its worktree in the question it asks. Tools > Remove worktrees with contacts makes that box start ticked. The branch and its commits stay, unless Delete the branch with its worktree is on in Settings; uncommitted changes go with the worktree, and you are told how many first. A project's cleanup script runs in the worktree before it goes. A worktree another contact works in is not offered. The contact leaves your list at once and its worktree is removed right after, which takes a few seconds in a big project; if it can't be removed, it stays where it is and the list tells you. Guests in the contact's conversation work in its worktree too, and are stopped before it goes.

Models. The Model list in Add a Contact and Edit contact... starts with a few models for the service, and Default, which leaves the choice to the service's own settings:

  • Type in the list to find any model the service has, or to use one by its exact name.
  • Add models... at the bottom opens the service's own list. Tick the models you want to choose from; the list keeps them for every contact of that service.

Claude and Codex are asked for their lists as you open the dialog, so new models show up by themselves. No message is sent for that. Gemini, OpenCode and Hermes can't be asked this way: Gemini offers its usual models, an OpenCode model is typed as provider/model, and a Hermes one as provider:model.

Contact card. Rest the mouse on a contact for half a second to see where its project stands:

  • the git branch, or the short commit if no branch is checked out
  • the branch's pull request, whether it has a merge conflict and how its checks stand, as a link such as "Pull request #12 · merge conflict, 2 checks failing": move the mouse onto the card and click it to open the pull request on GitHub
  • how many files have uncommitted changes. The conversation's Changes tab lists them, with what the branch committed
  • what its conversation cost today, guests included
  • when it was last active

A line the app can't fill in is left out. A folder that isn't a git repository shows no branch or changes, and Codex and Gemini contacts show no cost of their own. The pull request is the one for the branch checked out in the contact's folder, found with the GitHub CLI; it arrives a moment after the card.

Pull request tags. A contact whose branch has a pull request wears coloured tags at the end of its row, so you can see how every pull request stands without pointing at each contact:

Tag Meaning
Merged Merged. Purple.
Conflict Can't be merged until its conflicts with the base branch are resolved. Orange.
2 failing That many checks failed, even if others still run. Red.
Running Checks are still running, and none has failed. Yellow.
Passed Every check passed. Green.
Closed Closed without being merged. Grey.
Open, Draft Nothing more to say yet: no checks, and no conflict.
  • A pull request with a conflict wears its checks' tag too, such as Conflict and 2 failing.
  • A row with tags shows only the contact's name and its tags, whether it is working, waiting for you or idle. Its buddy still shows its status, and what it is doing is in its conversation window and the menu-bar menu.
  • The tags are never cut short: in a narrow list the name gives way instead.
  • Click the tags to open the pull request on GitHub. Point at them for how it stands and its title, such as "Pull request #12 · merge conflict, 2 checks failing" and "Back off when the API says to slow down".
  • Merged or Closed stays for as long as the contact's folder is on that branch. To go on with the same contact, click Continue next to the tag, or right-click it and choose Start new branch: its folder moves to a new branch, started from the project's main branch as the remote has it now, and the tags go, since the new branch has no pull request yet. The conversation is kept, and so is the branch it leaves. The new branch gets a name such as shop-3, and the next thing you ask the contact to do names it, as with a new contact. A nickname that was made up from the branch follows it both times. A folder with uncommitted changes is left as it is, and so is one whose contact is working or waiting for you: commit or finish first. Continue is greyed out meanwhile. Point at it for what it does.
  • Archive, next to Continue, is for a contact you are done with: it does what Archive contact in its right-click menu does. See Archiving a contact above for what is kept. Archive contacts once their pull request is merged in Settings does it for you.
  • Delete, after Archive, does what Delete contact in its right-click menu does: it asks first, and can take the contact's worktree along. Deleting a contact, above, says what goes and what stays.
  • In a narrow contact list, Archive and Delete are a box and a bin. Point at them for what they do.

The menu-bar menu has no tags, so there an idle contact says it in words, what stands out first: "Merge conflict on pull request #12", "2 checks failing on pull request #12", "Checks running on…" or "Checks passed on…". A merged or closed one says so.

When checks start failing, and when they have all passed, you get a toast; click it to open that contact's conversation. Your own status decides about that toast as it does about any other. The app asks gh in the background and only reads: every minute while a pull request is still to be merged or a turn has just ended, and every fifteen without one or once it is merged or closed. Coming back to the app asks at once, so a pull request you just merged on GitHub shows as merged. GitHub can take a moment to work out whether a pull request has conflicts, so a new conflict shows on the next look. Without gh, or when you are signed out, there are no tags and the line stays the folder, until you connect to GitHub.

Pull requests to review. Where MSN counted your new e-mail, the line under your picture counts the pull requests waiting for your review: "You have (3) pull requests to review". Click it to open them on GitHub.

The count comes from the GitHub CLI. The app asks every two minutes and only reads. With nothing to review it says (0). When GitHub can't be reached the line is hidden until it can.

Connecting to GitHub. Without gh, or when it is signed out, that line says Connect to GitHub to see your pull requests instead. Point at it for which of the two it is. Click it for the Connect to GitHub dialog, which signs gh in without a terminal:

  1. The dialog shows a one-time code, such as 1A2B-3C4D.
  2. Open GitHub copies the code and opens GitHub's page for it in your browser. Paste the code there and approve.
  3. The dialog closes by itself. The line turns into the count, and your contacts get their pull request tags, without waiting for the next look.

It is GitHub's own sign-in for its command-line tool, gh auth login --web: the app never sees your password, and gh keeps the sign-in, so gh in a terminal is signed in by it too. As gh auth login offers to in a terminal, git is set up to use the same sign-in for github.com (gh auth setup-git), so that cloning and pushing over https work.

Cancel, or Esc, calls the sign-in off. A sign-in that did not go through says why, and Try again starts over with a new code: a code is good for fifteen minutes. When gh is not installed the dialog says so, with a link to where to get it; Try again once it is there.

Signing in with gh auth login in a terminal works as well: the line notices within two minutes. The welcome wizard has the same sign-in on its GitHub line.

Notifications. When a window isn't focused, you get a toast in the corner and a dock bounce. When Claude needs you, it also sends a nudge. It asks once: more requests that come in while the conversation is still waiting for you join the first one quietly. Always allow on one of them also accepts the others the same rule covers. Click a toast and the conversation window you were in last shows that conversation, as when you click a contact beside it. A new window opens only when none is open, and a conversation that has a window of its own comes to the front there.

Menu bar. buddylist also sits in the menu bar, so you can check on your agents without finding its windows:

  • The number next to the icon is how much is unread: replies, requests and errors from a conversation you weren't looking at. Open or click into that conversation and it is read.
  • Click the icon to see every contact with its status and what it is doing. Click a contact to open its conversation.
  • Hover over the icon for a summary, such as "buddylist: 2 unread, 1 waiting for you".
  • ⌃⌥M (Control+Option+M, or Ctrl+Alt+M on Linux) brings the contact list to the front from any app. On Windows it is Ctrl+Alt+Shift+M: there Ctrl+Alt is AltGr on many keyboards, and AltGr+M types a letter. If another app already uses that shortcut, Open contact list in the menu still works.

The dock badge still counts the conversations waiting for you to approve something. On Windows and Linux the icon lives in the system tray, and the unread count is in its tooltip and menu.

Quick send

⌃⌥S (Control+Option+S, or Ctrl+Alt+S on Linux; Ctrl+Alt+Shift+S on Windows) opens a floating message box for the conversation you last viewed, including its selected chat tab. That contact is remembered after restarting. The box names everyone in the conversation and shows its folder before you send. Enter sends, Shift+Enter adds a line, and Esc, clicking elsewhere, or pressing the shortcut again dismisses it. Unsent text stays with that contact; a failed send keeps it for retrying. Open conversation brings up the full chat. Messages sent here appear in the full conversation too, and a busy agent handles them as it would messages sent there.

If no conversation has been viewed, or the last contact is deleted, archived, or offline, the shortcut opens the contact list. Quick send to last contact in the menu-bar icon’s menu also works if another app has taken the shortcut.

Your status and updates

Your own status. Click your name at the top of the contact list to change it. It decides how far the app goes to get your attention:

Your status Toast, sound, nudge and dock bounce Dock badge and menu-bar count Catch-up when you're back
Online yes yes –
Away, Be Right Back, Out To Lunch yes yes yes
Busy, On The Phone no yes yes
Appear Offline no no yes
  • Catch-up. When you go back to Online, every contact still waiting for you to approve something tells you again, with its toast and nudge. A conversation you are already looking at is skipped, and nothing else is repeated.
  • The counts. The dock badge and the number in the menu bar are hidden together. What you missed is still counted, and the menu-bar icon's menu and hover text still say it.
  • Your contacts never know. They aren't told your status, and nothing is accepted or declined for you. A contact that needs you keeps waiting, as it always does.

Auto-away. After five minutes without touching your computer, Online turns into Away. When you are back it turns into Online again, and you get the catch-up. A status you picked yourself is never changed. It is on by default: Tools > Show me as Away when I'm inactive in the contact list turns it off. The browser preview doesn't have it.

Quitting. Quitting ends every conversation. While a contact is working or waiting for you, buddylist asks first, as MSN did when you signed out: "Signing out will end 3 conversations.", naming the contacts, with Quit and Cancel. Cancel leaves every conversation, command and terminal running. With everyone idle it quits at once. ⌘Q and Quit in the app menu, Quit in the menu-bar icon's menu and File > Exit all ask. When macOS shuts down, restarts or logs you out, buddylist quits without asking, as the computer is waiting for it.

Updates. When a new version is out, buddylist downloads it in the background without a word. Once it is ready, a card at the bottom of the contact list says New update available: See changes opens what is new in it on the changelog, Restart installs it and opens buddylist again, and × hides the card. Restart asks first while contacts are busy, as quitting does. A copy that can't update itself, such as a Debian installation or one opened from a Mac disk image, shows Version x.y.z is available with What's new and Update... instead: Update... says how to get a copy that can, and links to the download page. Help > What's new opens the changelog too.

Music in your personal message

On Mac, click your name at the top of the contact list and turn on Show what I'm listening to. While Spotify or Apple Music plays, its song title and artist appear in place of your personal message. Pausing or stopping the music, or turning the option off, brings your saved message back. Clicking that line still edits your saved message, not the song.

macOS may ask to let buddylist control the player when it reads the song already playing. If you decline, later track changes can still appear. This option is off until you enable it and is available only on Mac.

Spending

Contacts > View spending... opens one window with the reported cost across all contacts for Today, This week and This month, in US dollars. The week starts on Monday and the month on the 1st, in your computer’s time zone. Each total says when its period began.

Below the totals, each contact has a week and month amount, with the largest month total first. Archived contacts are included. Guest agents count under the conversation they took part in; copied results in a fork count once. The window refreshes as contacts finish working, when history changes, when you return to it, and at midnight. File > Refresh or ⌘R (Ctrl+R elsewhere) asks again.

These are estimates from the costs agents report in the message history. Agents such as Codex do not report dollar costs; the status bar notes when contacts have replies without a reported cost. This is not a bill or a subscription balance. Deleted history and deleted contacts no longer count, and history retention (the newest 600 entries per conversation and 50 past conversations per contact) can limit the totals. The browser demo does not offer this window.