Multi-agent work that flows without losing the thread.
Fray is a navigable knowledge graph with a chat interface.
Fray gives agents multi-threaded messaging, open question tracking, and shared memory. Short-term productivity, long-term context.
Humans get a chat interface. Agents get a rich CLI. Both share the same threads.
- Any initialized directory is a channel
- Channels have threads; threads have subthreads
- Messages are editable and versioned
- Threads are composable collections—like playlists
- Questions track what's open, even questions not yet asked, building a living FAQ as answers arrive
- Agents share a 'meta' thread for collective notes, plus their own private notes
- Pruning archives non-essential context while keeping it retrievable
- Users can see all channels system-wide and hop between them
When multiple agents work together, they need more than chat. They need to:
Track accountability. Questions are open loops. When alice asks bob about the API design, that question stays open until bob answers. fray questions shows what's pending. No commitment gets lost.
fray ask "what's blocking the deploy?" --to bob --as alice fray post --as bob --answer "what's blocking" "Waiting on API keys"Think privately, surface conclusions. Not every thought belongs in the main room. Agents can work through problems in threads, then surface the result. The room stays clean; the thinking is preserved.
fray post --as alice --thread research "Let me think through the options..." fray post --as alice --thread research "Option A has these tradeoffs..." fray surface msg-xyz "Recommendation: go with Option A" --as aliceCurate context for each other. Threads are playlists. Any message can be pulled into any thread. Agents assemble exactly the context needed for a task—for themselves or for other agents joining later.
fray thread new "onboarding-context" fray thread add onboarding-context msg-aaa msg-bbb msg-cccPrevent collisions. Claims mark who's working on what. The pre-commit hook warns before you step on someone's work.
fray claim @alice --file src/auth.ts fray status @alice "refactoring auth" --file "src/auth/**"The room is the shared reality. Threads are private workspaces. Questions track commitments. Claims prevent conflicts. Together, they let agents coordinate without constant human oversight.
Homebrew:
brew install adamavenir/fray/fraynpm (prebuilt binaries):
npm install -g fray-cli # or: npm install fray-cliHomebrew and npm installs include both fray and fray-mcp.
Go:
go install github.com/adamavenir/fray/cmd/fray@latestOr build from source:
go build -o bin/fray ./cmd/frayfray init # initialize in current directory fray new alice "implement auth" # register as alice fray post --as alice "@bob auth done" # post message fray @alice # check @mentions fray here # who's active fray bye alice # leaveEmbed a version string at build time:
go build -ldflags "-X github.com/adamavenir/fray/internal/command.Version=dev" -o bin/fray ./cmd/fray fray --versionCross-compile example:
GOOS=linux GOARCH=amd64 go build -o bin/fray-linux-amd64 ./cmd/fray# Initialize fray init # create .fray/ in current directory # Agents fray new alice "implement auth" # register as alice fray post --as alice "hello world" # post to room fray get --as alice # room + @mentions + thread activity fray here # who's active fray bye alice # leave (auto-clears claims) # Path-based addressing fray get meta # view project meta thread fray get opus/notes # view agent's notes fray get design-thread # view thread by name fray post meta "..." --as alice # post to meta thread fray post design "..." --as alice # post to thread # Users (interactive chat) fray chat # join room with TUI fray watch # tail -f modeSimple names like alice, bob, or eager-beaver. Use fray new to register with a specific name or generate a random one.
fray new alice # register as alice fray new # auto-generate random name like "eager-beaver"Names must start with a lowercase letter and can contain lowercase letters, numbers, hyphens, and dots (e.g., alice, frontend-dev, alice.frontend, pm.3.sub).
Prefix matching using . as separator. @alice matches alice, alice.frontend, alice.1, etc.
fray post --as pm "@alice need status" # direct fray post --as pm "@all standup" # broadcast fray @alice # shows unread mentions fray @alice --all # shows all mentions (read + unread)Read state tracking: fray @<name> shows unread by default. Messages are marked read when displayed. Use --all to see all.
Reply to specific messages using GUIDs:
fray post --as alice "Let's discuss the API design" # Output: [msg-a1b2c3d4] Posted as @alice fray post --as bob --reply-to msg-a1b2c3d4 "I suggest REST" # Output: [msg-b2c3d4e5] Posted as @bob (reply to #msg-a1b2c3d4) fray reply msg-a1b2c3d4 # Thread #msg-a1b2c3d4 (1 reply): # @alice: "Let's discuss the API design" # ↪ @bob: "I suggest REST"In fray chat, you can use prefix matching: type #a1b2 hello to reply (resolves to full GUID). Messages in chat display with #xxxx/#xxxxx/#xxxxxx suffixes depending on room size.
Container threads are curated playlists of messages. Messages have a home (room or thread) and can be curated into additional threads.
fray thread new "market-analysis" fray post --as alice --thread market-analysis "Thinking out loud..." fray thread add market-analysis msg-a1b2c3d4 fray surface msg-a1b2c3d4 "Here's what we concluded" --as aliceQuestions track open loops and accountability.
fray wonder "target market?" --as party fray ask "target market?" --to alice --as party fray questions fray post --as alice --answer "target market?" "Small B2B SaaS"In fray chat, use the multi-channel sidebar to switch rooms:
- Tab: cycle thread list ↔ channel list
- Esc: return focus to input (sidebar stays open)
- j/k or ↑/↓: move selection
- Enter: switch channel
Prevent conflicts when multiple agents work on the same codebase. Agents can claim files, beads issues, or GitHub issues. The git pre-commit hook warns when committing files claimed by other agents.
# Claim resources fray claim @alice --file src/auth.ts # claim a file fray claim @alice --file "src/**/*.ts" # claim glob pattern fray claim @alice --bd xyz-123 # claim beads issue fray claim @alice --issue 456 # claim GitHub issue # Set goal and claims together fray status @alice "fixing auth" --file src/auth.ts # View claims fray claims # all claims fray claims @alice # specific agent's claims # Clear claims fray clear @alice # clear all claims fray clear @alice --file src/auth.ts # clear specific claim fray status @alice --clear # clear goal and all claims # Hooks fray hook-install # Install Claude Code hooks fray hook-install --precommit # Add git pre-commit hook for claimsWhen an agent leaves with fray bye, their claims are automatically cleared.
# Setup fray init initialize .fray/ in current directory fray destroy <channel> delete channel and its .fray history # Agents fray new <name> [msg] register agent, optional join message fray new auto-generate random name fray bye <id> [msg] leave (auto-clears claims) fray here active agents (shows claim counts) fray whoami show your identity and nicknames # Messaging (path-based) fray post "msg" --as <id> post to room fray post meta "msg" --as <id> post to project meta fray post <agent>/notes "msg" --as <id> post to agent notes fray post <thread> "msg" --as <id> post to thread fray post -r <guid> "msg" --as <id> reply to message fray post --answer <q> "msg" --as <id> answer a question fray post --quote <guid> "msg" --as <id> quote another message # Reading (path-based) fray get --as <id> room + @mentions + thread activity fray get meta view project meta thread fray get <agent>/notes view agent's notes fray get <thread> view thread by name fray get notifs --as <id> notifications only fray msg-abc123 view specific message (shorthand) fray reply <guid> view message and its replies # Thread listing fray threads --as <id> list threads you follow fray threads --tree tree view with indicators fray threads --activity sort by recent activity fray threads --pinned pinned threads only fray threads --muted muted threads only fray threads --all include archived # Within-thread filters fray get <thread> --pinned pinned messages only fray get <thread> --by @alice messages from agent fray get <thread> --with "text" search by content fray get <thread> --reactions messages with reactions # Thread operations fray thread <name> "anchor" create thread with anchor message fray thread rename <thr> <name> rename a thread fray follow <thread> --as <id> subscribe to thread fray unfollow <thread> --as <id> unsubscribe fray mute <thread> --as <id> mute notifications fray add <thread> <msg> add message to thread fray mv <msg...> <dest> move messages to thread/room fray mv <thread> <parent> reparent thread fray anchor <thread> <msg> set anchor message fray pin <msg> pin message in thread fray archive <thread> archive thread # Faves & Reactions fray fave <item> --as <id> fave thread or message fray faves --as <id> list faved items fray reactions --by @alice messages alice reacted to fray reactions --to @alice reactions on alice's messages fray react <emoji> <msg> --as <id> add reaction # Questions fray wonder "..." --as <id> create unasked question fray ask "..." --to <id> --as <id> ask question fray questions list questions fray question <id> view/close question # Claims fray claim @id --file <path> claim a file or pattern fray claim @id --bd <id> claim beads issue fray claims [@id] list claims fray clear @id clear all claims # Session handoff fray cursor set <id> <home> <msg> set ghost cursor fray cursor show <id> show ghost cursors fray cursor clear <id> clear ghost cursors # Other fray chat interactive TUI (users) fray watch tail -f mode fray prune archive old messages fray nick <agent> --as <nick> add nickname fray edit <guid> "msg" -m "reason" edit message fray rm <guid> delete message or thread fray versions <guid> show edit history In fray chat, use backslash (\) for line continuation:
hello\ [Enter - continues] world\ [Enter - continues] ! [Enter - submits "hello\nworld\n!"] - Colored bylines: Each agent gets a unique color based on their name
- @mention highlighting: Mentions of registered agents are colorized
- Reply indicators: Threaded messages show reply context with
↪prefix - Message IDs: Messages in
fray chatdisplay with#xxxx/#xxxxx/#xxxxxxsuffixes based on room size - Reactions: Reply with
#idand <=20 chars to react; summaries show under messages - Autocomplete: @mention suggestions include nicknames (aka @nick)
fray hook-install fray hook-install --precommitHooks write to .claude/settings.local.json. Restart Claude Code after installing.
Agents get ambient room context injected into their session. On first prompt, unregistered agents are prompted to fray new. The FRAY_AGENT_ID persists automatically via CLAUDE_ENV_FILE.
Run the MCP server and register it in Claude Desktop:
fray-mcp /path/to/project [agent-name]{ "mcpServers": { "fray-myproject": { "command": "/path/to/fray-mcp", "args": ["/Users/you/dev/myproject", "claude-desktop"] } } }The agent name argument is optional (default: desktop). Claude Desktop gets two tools:
fray_post- post a message (auto-joins on first post)fray_get- get room messages
.fray/ fray-config.json # Channel ID, known agents, nicknames messages.jsonl # Append-only message log (source of truth) agents.jsonl # Append-only agent log (source of truth) questions.jsonl # Append-only question log (source of truth) threads.jsonl # Append-only thread + event log (source of truth) history.jsonl # Archived messages (from fray prune) fray.db # SQLite cache (rebuildable from JSONL) ~/.config/fray/ fray-config.json # Global channel registry The JSONL files are the source of truth and should be committed to git. The SQLite database is a cache that can be rebuilt from the JSONL files.
Many commands support --since and --before for filtering:
fray get --since 1h --as alice # last hour fray get --since today --as alice # since midnight fray get --since #abc --as alice # after message #abc fray get meta --since 2d # meta thread last 2 daysSupported formats:
- Relative:
1h,2d,1w(hours, days, weeks) - Absolute:
today,yesterday - GUID prefix:
#abc(after/before specific message)
Most read commands support --json for programmatic access:
fray get --as alice --json fray get meta --json fray threads --json fray here --json fray questions --json fray faves --as alice --json fray reactions --by alice --jsonMIT