heyquilt 0.0.1 → 0.3.106
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +85 -0
- package/README.md +633 -2
- package/RELEASES.md +862 -0
- package/assets/logo.svg +1 -0
- package/bin/quilt.js +849 -0
- package/desktop/main.js +315 -0
- package/package.json +163 -7
- package/src/account.js +591 -0
- package/src/admit-policy.js +32 -0
- package/src/agent-join.js +370 -0
- package/src/agent-task-workflow.js +176 -0
- package/src/agents/actions.js +85 -0
- package/src/agents/claude-code.js +187 -0
- package/src/agents/common.js +21 -0
- package/src/agents/cursor-transcripts.js +177 -0
- package/src/agents/cursor.js +404 -0
- package/src/agents/index.js +69 -0
- package/src/ai-vm-signin.js +110 -0
- package/src/ai-vm.js +522 -0
- package/src/api/access.js +75 -0
- package/src/api/activity.js +181 -0
- package/src/api/agent-auth.js +136 -0
- package/src/api/agent-placement.js +157 -0
- package/src/api/audit.js +83 -0
- package/src/api/auth.js +17 -0
- package/src/api/domains.js +30 -0
- package/src/api/file-paths.js +40 -0
- package/src/api/file-store.js +99 -0
- package/src/api/fly-machines.js +133 -0
- package/src/api/github-app.js +172 -0
- package/src/api/http.js +34 -0
- package/src/api/invite-email.js +53 -0
- package/src/api/issues.js +110 -0
- package/src/api/join-text.js +78 -0
- package/src/api/mailer.js +47 -0
- package/src/api/memory-store.js +1219 -0
- package/src/api/org-access.js +54 -0
- package/src/api/permissions.js +71 -0
- package/src/api/relay-cluster.js +545 -0
- package/src/api/relay-machines.js +92 -0
- package/src/api/releases.js +87 -0
- package/src/api/routes/access-types.js +54 -0
- package/src/api/routes/agent-invites.js +115 -0
- package/src/api/routes/agents.js +252 -0
- package/src/api/routes/ai-vm.js +495 -0
- package/src/api/routes/github.js +380 -0
- package/src/api/routes/grants.js +70 -0
- package/src/api/routes/invites.js +188 -0
- package/src/api/routes/issues.js +47 -0
- package/src/api/routes/join.js +167 -0
- package/src/api/routes/members.js +110 -0
- package/src/api/routes/orgs.js +179 -0
- package/src/api/routes/relay-cluster.js +90 -0
- package/src/api/routes/relay.js +76 -0
- package/src/api/routes/secrets.js +448 -0
- package/src/api/routes/session-invites.js +119 -0
- package/src/api/routes/sessions.js +92 -0
- package/src/api/routes/teams.js +132 -0
- package/src/api/routes/workspace-agents.js +332 -0
- package/src/api/routes/workspace-files.js +277 -0
- package/src/api/routes/workspace-invites.js +196 -0
- package/src/api/routes/workspaces.js +232 -0
- package/src/api/sandbox-keys.js +57 -0
- package/src/api/secrets-access.js +93 -0
- package/src/api/server.js +654 -0
- package/src/api/slugs.js +20 -0
- package/src/api/supabase-store.js +875 -0
- package/src/api/team-access.js +30 -0
- package/src/api/tokens.js +31 -0
- package/src/api/workspace-access.js +62 -0
- package/src/api/workspace-reach.js +60 -0
- package/src/autowork-tools.js +166 -0
- package/src/autowork.js +375 -0
- package/src/blobstore.js +99 -0
- package/src/boxes.js +37 -0
- package/src/branchdocs.js +235 -0
- package/src/branches.js +194 -0
- package/src/catchup.js +111 -0
- package/src/chat-archive.js +85 -0
- package/src/chat-links.js +923 -0
- package/src/clash.js +128 -0
- package/src/cloud-ai.js +50 -0
- package/src/commit-request.js +59 -0
- package/src/commit.js +213 -0
- package/src/connection.js +569 -0
- package/src/control.js +248 -0
- package/src/conversation.js +125 -0
- package/src/doctor.js +156 -0
- package/src/duties.js +303 -0
- package/src/editors.js +228 -0
- package/src/fsutil.js +97 -0
- package/src/git-hook.js +48 -0
- package/src/git.js +147 -0
- package/src/github-commit.js +320 -0
- package/src/gitignore.js +49 -0
- package/src/gitstate.js +924 -0
- package/src/history.js +307 -0
- package/src/hooks.js +371 -0
- package/src/hosted-agents.js +24 -0
- package/src/hosted-client.js +112 -0
- package/src/identity.js +99 -0
- package/src/inbox.js +237 -0
- package/src/integrations.js +221 -0
- package/src/key-cli.js +115 -0
- package/src/largefiles.js +91 -0
- package/src/legacy.js +25 -0
- package/src/mcp-proxy.js +45 -0
- package/src/mcp-room.js +32 -0
- package/src/mcp.js +1258 -0
- package/src/merge3.js +240 -0
- package/src/merges.js +148 -0
- package/src/pass-source.js +183 -0
- package/src/passes.js +64 -0
- package/src/pathrules.js +134 -0
- package/src/persona.js +101 -0
- package/src/presence.js +360 -0
- package/src/private-file.js +41 -0
- package/src/procs.js +70 -0
- package/src/project-rules.js +178 -0
- package/src/protocol.js +92 -0
- package/src/quiet-warnings.js +9 -0
- package/src/relay-ai-vm.js +82 -0
- package/src/relay-ask.js +141 -0
- package/src/relay-ci.js +111 -0
- package/src/relay-clash.js +214 -0
- package/src/relay-cluster.js +454 -0
- package/src/relay-commit.js +887 -0
- package/src/relay-filekey.js +46 -0
- package/src/relay-git.js +274 -0
- package/src/relay-githttp.js +166 -0
- package/src/relay-github.js +109 -0
- package/src/relay-lease.js +137 -0
- package/src/relay-lfs.js +37 -0
- package/src/relay-mcp.js +1691 -0
- package/src/relay-metrics.js +140 -0
- package/src/relay-outbound.js +1273 -0
- package/src/relay-sync.js +716 -0
- package/src/relay-turn-sync.js +506 -0
- package/src/relay-upstream.js +804 -0
- package/src/relay-webhooks.js +111 -0
- package/src/releases.js +138 -0
- package/src/report.js +129 -0
- package/src/runner.js +307 -0
- package/src/same-edit.js +18 -0
- package/src/secret-import.js +55 -0
- package/src/secret-names.js +26 -0
- package/src/secret-run.js +80 -0
- package/src/secrets-client.js +56 -0
- package/src/server.js +4214 -0
- package/src/session-access.js +170 -0
- package/src/session-name.js +15 -0
- package/src/session.js +7446 -0
- package/src/settings.js +46 -0
- package/src/setup.js +184 -0
- package/src/shell-path.js +46 -0
- package/src/status.js +197 -0
- package/src/summarize.js +109 -0
- package/src/sync-words.js +42 -0
- package/src/task-comments.js +92 -0
- package/src/tasks.js +670 -0
- package/src/textdiff.js +20 -0
- package/src/turn-sync-plan.js +145 -0
- package/src/turn-sync.js +212 -0
- package/src/ui/access-form.js +37 -0
- package/src/ui/agent-env-key.js +76 -0
- package/src/ui/agent-guide.js +127 -0
- package/src/ui/agent-kinds.js +175 -0
- package/src/ui/agent-place.js +265 -0
- package/src/ui/app.css +2494 -0
- package/src/ui/app.js +546 -0
- package/src/ui/board.js +465 -0
- package/src/ui/boxes.js +76 -0
- package/src/ui/branches.js +111 -0
- package/src/ui/catchup.js +77 -0
- package/src/ui/changes.js +159 -0
- package/src/ui/chat.js +266 -0
- package/src/ui/cloud-ai-model.js +108 -0
- package/src/ui/cloud-ai.js +221 -0
- package/src/ui/common.js +433 -0
- package/src/ui/csv.js +21 -0
- package/src/ui/diffview.js +74 -0
- package/src/ui/feed-convs.js +39 -0
- package/src/ui/feed.js +174 -0
- package/src/ui/files.js +579 -0
- package/src/ui/fileview.js +150 -0
- package/src/ui/git-rule.js +60 -0
- package/src/ui/home.js +1322 -0
- package/src/ui/index.html +16 -0
- package/src/ui/invite.js +97 -0
- package/src/ui/invites.js +79 -0
- package/src/ui/loom-model.js +516 -0
- package/src/ui/loom.css +365 -0
- package/src/ui/loom.js +786 -0
- package/src/ui/mark.js +104 -0
- package/src/ui/rail-model.js +75 -0
- package/src/ui/rail.js +173 -0
- package/src/ui/releases.js +182 -0
- package/src/ui/sandbox-keys-model.js +53 -0
- package/src/ui/sandbox-keys.js +132 -0
- package/src/ui/schedule.js +156 -0
- package/src/ui/secret-rules.js +255 -0
- package/src/ui/secrets-view.js +162 -0
- package/src/ui/secrets.js +283 -0
- package/src/ui/session.js +3292 -0
- package/src/ui/signin.js +75 -0
- package/src/ui/sounds.js +110 -0
- package/src/ui/tool-logo.js +86 -0
- package/src/ui/tree.js +281 -0
- package/src/ui/workspaces.js +547 -0
- package/src/ui-server.js +1381 -0
- package/src/update-check.js +67 -0
- package/src/upstream.js +192 -0
- package/src/vault/crypto.js +96 -0
- package/src/vault/kms.js +61 -0
- package/src/vault/main.js +33 -0
- package/src/vault/server.js +279 -0
- package/src/vault/sigv4.js +38 -0
- package/src/webhooks.js +235 -0
- package/src/workspace-cli.js +62 -0
- package/src/workspace-tools.js +340 -0
- package/index.js +0 -2
package/README.md
CHANGED
|
@@ -1,3 +1,634 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center"><img src="assets/logo.svg" width="96" alt="Quilt logo"></p>
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<h1 align="center">Quilt</h1>
|
|
4
|
+
|
|
5
|
+
<p align="center">Real-time pair vibe coding that doesn't care which AI tool you use.</p>
|
|
6
|
+
|
|
7
|
+
You use Claude Code, your friend uses Cursor, someone else uses Codex or plain
|
|
8
|
+
vim. Everyone works in their own copy of the project, on their own machine,
|
|
9
|
+
anywhere in the world, and every change shows up on everyone else's disk
|
|
10
|
+
within milliseconds. Your agents can also see what the other agents are doing.
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
you + Claude Code friend + Cursor
|
|
14
|
+
~/my-app <--> quilt join quilt join <--> ~/my-app
|
|
15
|
+
\ /
|
|
16
|
+
+--> Quilt relay <-----+
|
|
17
|
+
(WebSocket)
|
|
18
|
+
|
|
19
|
+
each agent --MCP--> quilt_status / quilt_claim / quilt_message
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## How it works
|
|
23
|
+
|
|
24
|
+
- **Tool-agnostic by design.** Every AI coding tool eventually reads and writes
|
|
25
|
+
files, so Quilt syncs files and nothing else. It watches your project folder and
|
|
26
|
+
mirrors changes into a shared [Yjs](https://yjs.dev) CRDT document. Remote
|
|
27
|
+
changes are written back to disk. Your editor or agent just sees files change.
|
|
28
|
+
- **Real merges, not overwrites.** Text files are synced character by character.
|
|
29
|
+
If your agent edits the top of `app.ts` while theirs edits the bottom, both
|
|
30
|
+
edits land. Binary files (images, etc.) sync as whole files.
|
|
31
|
+
- **Works apart.** Quilt's relay at `relay.heyquilt.com` connects everyone over
|
|
32
|
+
WebSockets, and only lets in people signed in to heyquilt.com. If your
|
|
33
|
+
connection drops, keep working: Quilt keeps a local copy of the shared state
|
|
34
|
+
and merges your offline edits line by line when you reconnect, like git.
|
|
35
|
+
Nobody is ever asked to merge: where two people changed the same lines,
|
|
36
|
+
Quilt keeps the newer edit, keeps the other in the file's history, and tells
|
|
37
|
+
whoever wrote it. The same goes for commits pulled or pushed to GitHub.
|
|
38
|
+
- **Watch each other's AI, live.** The app shows your partner's AI conversation
|
|
39
|
+
as it happens: their prompts, the AI's replies, and one-line actions like
|
|
40
|
+
"Edited src/app.ts" or "Ran npm test". Quilt reads Claude Code's and Cursor's
|
|
41
|
+
chats by itself; any other MCP agent shares the same feed with `quilt_share`.
|
|
42
|
+
Next to it are a live file tree (who's editing what, what's claimed) and
|
|
43
|
+
read-only file tabs where changed lines light up.
|
|
44
|
+
- **Agents coordinate, and can join by themselves.** An MCP server gives each
|
|
45
|
+
agent tools to see who's online, read a partner's AI feed, see where people
|
|
46
|
+
are working, *claim* files and message each other. With an invite link, an
|
|
47
|
+
agent can even join (or start) a session on its own. Tools without MCP can
|
|
48
|
+
use the `quilt` CLI or read `.quilt/STATUS.md`.
|
|
49
|
+
- **Cloud AIs too.** An AI with no computer of its own that can use an MCP
|
|
50
|
+
server over HTTP (a bot, a cloud routine, your own agent) joins through Quilt's hosted
|
|
51
|
+
MCP at `api.heyquilt.com/mcp` with the access key it got from an agent
|
|
52
|
+
invite. It joins a session from the invite link, you let it in, and it reads
|
|
53
|
+
and writes the shared files like everyone else.
|
|
54
|
+
- **Workspaces (behind a flag while they settle).** They gather your
|
|
55
|
+
sessions, the people and agents in them, and files, in one place. Agents
|
|
56
|
+
can work in them too: invite one as a global, workspace or session agent,
|
|
57
|
+
and a workspace's agents are invited to its new sessions for you to let in.
|
|
58
|
+
- **AIs in a chat window, with nothing to set up.** ChatGPT, claude.ai, Grok and
|
|
59
|
+
other AIs you only talk to in a chat can join through a *chat link*: the session
|
|
60
|
+
owner (or whoever may let people in) makes one in **Invite → A chat AI** (or
|
|
61
|
+
`quilt chat-link`), pastes it into
|
|
62
|
+
the chat, and the AI works by opening links. It can read and send messages, read
|
|
63
|
+
and add tasks, read files, and add pictures, PDFs, office documents and notes as
|
|
64
|
+
new files. It can't change existing files. It shows in the session as its own
|
|
65
|
+
member and works for 10 minutes: the owner, or whoever may let people in, extends
|
|
66
|
+
it from the people menu (or
|
|
67
|
+
`quilt chat-link extend <name> <minutes>`) while it still works. Once it runs
|
|
68
|
+
out, or the owner removes it, a new link is needed.
|
|
69
|
+
|
|
70
|
+
## Quick start
|
|
71
|
+
|
|
72
|
+
### Download the app
|
|
73
|
+
|
|
74
|
+
Get Quilt for [Mac (Apple silicon)](https://heyquilt.com/download/quilt-mac-arm64.dmg),
|
|
75
|
+
[Mac (Intel)](https://heyquilt.com/download/quilt-mac-x64.dmg),
|
|
76
|
+
[Windows](https://heyquilt.com/download/quilt-windows-x64.exe) or
|
|
77
|
+
Linux ([x86_64](https://heyquilt.com/download/quilt-linux-x86_64.AppImage),
|
|
78
|
+
[ARM](https://heyquilt.com/download/quilt-linux-arm64.AppImage): an
|
|
79
|
+
AppImage, `chmod +x` it), and open it.
|
|
80
|
+
Everything happens in the app: start a session, send the invite link, and
|
|
81
|
+
partners click it to join. Closing the window keeps your sessions syncing from
|
|
82
|
+
the menu bar; quit from there when you're done.
|
|
83
|
+
|
|
84
|
+
The first time you open it, sign in: Quilt opens heyquilt.com, where you
|
|
85
|
+
approve this computer. New to Quilt? [Create an account](https://heyquilt.com/signup).
|
|
86
|
+
|
|
87
|
+
The app isn't signed by Apple yet, so the first time you open it macOS may say
|
|
88
|
+
it can't check it. Open **System Settings → Privacy & Security** and click
|
|
89
|
+
**Open Anyway**.
|
|
90
|
+
|
|
91
|
+
Your AI tools can use Quilt as soon as the app opens: it connects every one it
|
|
92
|
+
finds (see [Your AI tools are connected already](#the-terminal-way)). To type
|
|
93
|
+
`quilt` in a terminal yourself, choose **Quilt → Install the Quilt Command…**.
|
|
94
|
+
|
|
95
|
+
### On a server or cloud machine
|
|
96
|
+
|
|
97
|
+
A Linux machine with no desktop (a server, a cloud VM, a container, an agent's sandbox)
|
|
98
|
+
gets the command line with its own Node.js, so nothing else needs installing:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
curl -fsSL https://heyquilt.com/install.sh | sh
|
|
102
|
+
quilt login
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Run the same line again to update. Agents on that machine find Quilt's MCP server by
|
|
106
|
+
themselves (see below), and `quilt join <invite>` syncs a project there.
|
|
107
|
+
|
|
108
|
+
### From source
|
|
109
|
+
|
|
110
|
+
Requires Node.js 20+.
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
git clone <this repo> && cd quilt && npm install && npm link # puts `quilt` on your PATH
|
|
114
|
+
npm run app # run the desktop app from source
|
|
115
|
+
npm run dist:mac # build the Mac app into dist/
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### The easy way: the app
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
quilt ui
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
This opens Quilt in your browser, where you can:
|
|
125
|
+
|
|
126
|
+
- **Sign in** with your heyquilt.com account (once per computer).
|
|
127
|
+
- **Start a session:** pick your project folder. You get an invite link to send.
|
|
128
|
+
- **Join a session:** paste an invite link and pick where the project should go.
|
|
129
|
+
- **Work together:** see who's online, what they're working on and which files
|
|
130
|
+
they just changed. Chat, send direct messages, and drag and drop files to share
|
|
131
|
+
them. You can also claim files, and rejoin recent sessions later.
|
|
132
|
+
|
|
133
|
+
The app only listens on `127.0.0.1` and needs the secret link `quilt ui` prints.
|
|
134
|
+
|
|
135
|
+
### The terminal way
|
|
136
|
+
|
|
137
|
+
**1. Sign in** once on each computer:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
quilt login # opens heyquilt.com, where you approve this computer
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**2. Start a session** in your project folder:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
cd ~/code/my-app
|
|
147
|
+
quilt join --tool claude
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
It prints an invite link like `https://join.heyquilt.com/room-1a2b#…`.
|
|
151
|
+
Send it to your friend. Opening it in a browser shows them how to join.
|
|
152
|
+
|
|
153
|
+
**3. Your friend joins** from an empty folder (or their own clone of the same
|
|
154
|
+
repo), signed in to their own account:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
mkdir my-app && cd my-app
|
|
158
|
+
quilt login
|
|
159
|
+
quilt join <invite-link> --tool cursor
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Keep `quilt join` running in a terminal while you work. It logs who joined,
|
|
163
|
+
what they're touching, claims, and messages.
|
|
164
|
+
|
|
165
|
+
**Your AI tools are connected already.** Whenever the app, `quilt login`,
|
|
166
|
+
`quilt ui` or a session starts, Quilt adds its MCP server to every AI tool it
|
|
167
|
+
finds on the computer: Claude Code, Claude Desktop, Cursor, Windsurf, Codex,
|
|
168
|
+
VS Code (GitHub Copilot, Cline, Roo Code), Gemini CLI, GitHub Copilot CLI, Zed,
|
|
169
|
+
opencode, Kiro, Amp, Junie and Continue. It writes each tool's own settings with
|
|
170
|
+
this install's full path, so nothing depends on your PATH or on files in the
|
|
171
|
+
project, and it keeps them current when the app moves or updates. A tool that
|
|
172
|
+
was already open picks Quilt up when it restarts. A settings file Quilt can't
|
|
173
|
+
edit safely (JSON with comments, say) is left alone and named in the log.
|
|
174
|
+
`quilt setup` does the same on demand, and adds pairing etiquette to `CLAUDE.md`
|
|
175
|
+
and `AGENTS.md`.
|
|
176
|
+
|
|
177
|
+
**Quilt's rules are enforced, in every tool.** They aren't instructions an agent
|
|
178
|
+
may skip:
|
|
179
|
+
|
|
180
|
+
- An edit to a file someone else holds (claims it) is undone (Quilt watches the
|
|
181
|
+
disk). Only claims block files; chat never does.
|
|
182
|
+
- Before an agent changes a file, it is shown what people said about that file in
|
|
183
|
+
chat, so it works with what was asked or planned in mind.
|
|
184
|
+
- While someone who messaged or mentioned the agent is waiting for an answer, every
|
|
185
|
+
tool that moves work on (claims, tasks, focus, merges, commits, `quilt_set_work`)
|
|
186
|
+
refuses with who is waiting, until the agent answers with `quilt_message`.
|
|
187
|
+
- Hosted agents write through Quilt's tools, so their writes are refused outright.
|
|
188
|
+
|
|
189
|
+
Claude Code and Cursor also get Quilt's hooks (in your own `.claude/settings.local.json`,
|
|
190
|
+
which Cursor reads too), and Gemini CLI gets them in its user settings: they refuse such
|
|
191
|
+
an edit before it happens instead of undoing it after.
|
|
192
|
+
See [Claims](#claims).
|
|
193
|
+
|
|
194
|
+
## Commands
|
|
195
|
+
|
|
196
|
+
| Command | What it does |
|
|
197
|
+
|---|---|
|
|
198
|
+
| `quilt ui` | Open the app (start, join, chat, files) |
|
|
199
|
+
| `quilt serve [--port 4321] [--data ./quilt-data]` | Run a relay (how Quilt's relay runs; see docs/hosting.md) |
|
|
200
|
+
| `quilt login` / `quilt logout` / `quilt whoami` | Sign this computer in to your heyquilt.com account, sign it out, or see which account it uses |
|
|
201
|
+
| `quilt join` | Start a new session for this folder |
|
|
202
|
+
| `quilt join --agent <name>` | Join as a Quilt agent saved with `quilt agent join` |
|
|
203
|
+
| `quilt join <invite>` | Join a session |
|
|
204
|
+
| `quilt join` | Rejoin this folder's last session (merges offline edits) |
|
|
205
|
+
| `quilt invite` | Print the invite link again |
|
|
206
|
+
| `quilt status` | Who's online, focus, recent edits, claims, messages |
|
|
207
|
+
| `quilt focus "adding auth"` | Tell others what you're working on |
|
|
208
|
+
| `quilt claim 'src/auth/**' "rewriting login"` | Lock files/folders/globs so only you can change them |
|
|
209
|
+
| `quilt release <pattern>` / `quilt release` | Release one claim / all of yours |
|
|
210
|
+
| `quilt chat` | Interactive chat in your terminal (live messages, DMs, files) |
|
|
211
|
+
| `quilt say "pushing a schema change"` / `quilt say @bob "got a sec?"` | Message everyone / one person |
|
|
212
|
+
| `quilt send design.png @bob "new mockup"` | Send a file (to everyone, or one person) |
|
|
213
|
+
| `quilt messages` / `quilt messages --all` / `--with bob` | Unread messages / history / one conversation |
|
|
214
|
+
| `quilt history [path] [--by name] [--since 2h] [--diff]` | Who changed what, when, and for which task |
|
|
215
|
+
| `quilt get <message-id> [dest]` | Download a shared file again |
|
|
216
|
+
| `quilt setup` | Connect every AI tool on this computer now, and add agent instructions to the project |
|
|
217
|
+
| `quilt mcp` | The MCP server itself (your AI tool launches this) |
|
|
218
|
+
| `quilt doctor [--watch 30]` | Check what Quilt can see of your Claude Code / Cursor chats (safe to share: no chat text) |
|
|
219
|
+
|
|
220
|
+
### MCP tools for agents
|
|
221
|
+
|
|
222
|
+
| Tool | Purpose |
|
|
223
|
+
|---|---|
|
|
224
|
+
| `quilt_join_session` | Join a session from an invite link, as a Quilt agent saved with `quilt agent join` |
|
|
225
|
+
| `quilt_start_session` | Start a new session for a folder, as that agent, and get an invite link |
|
|
226
|
+
| `quilt_leave_session` / `quilt_session_info` | Leave; or see the folder, your name, who's online, and the invite |
|
|
227
|
+
| `quilt_status` | Collaborators, their focus, recently edited files, what each person has changed, claims, messages |
|
|
228
|
+
| `quilt_partner_feed` | Read what a collaborator's AI is doing (prompts, replies, actions) |
|
|
229
|
+
| `quilt_history` | The chronology: who changed which file, when, the diff, and for which task; filter by path, person, task or time |
|
|
230
|
+
| `quilt_list_files` | Shared files with recent editors and claims |
|
|
231
|
+
| `quilt_set_focus` | Announce the current task |
|
|
232
|
+
| `quilt_share` | Share what you're working on (the request, your plan, what you did, files changed): it reaches partners' feeds and the task board, and holds off commits while you work |
|
|
233
|
+
| `quilt_before_edit` | Before changing files: whether each one is yours to edit (free ones are claimed for you; held ones are refused, with who to ask), and what people said about them in chat lately |
|
|
234
|
+
| `quilt_set_work` | Say you're working or done; "done" releases the files claimed for you, and is refused until you've answered everyone who wrote to you |
|
|
235
|
+
| `quilt_claim` / `quilt_release` | Claim or release files by hand (Quilt claims files for you as your AI edits them) |
|
|
236
|
+
| `quilt_message` | Message everyone, or one person with `to` |
|
|
237
|
+
| `quilt_read_messages` | Read unread (or recent) messages, including received files |
|
|
238
|
+
| `quilt_project_rules` | The project's rules for AI, the same for every tool: AGENTS.md (root and folders, else CLAUDE.md), Cursor rules that always apply, and the design system (DESIGN.md, or the file AGENTS.md names with `Design system: <path>`) |
|
|
239
|
+
| `quilt_inbox` | What is waiting for you: mentions (`@yourname`), direct messages and tasks handed to you since you last looked |
|
|
240
|
+
| `quilt_webhook_subscribe` / `quilt_webhook_unsubscribe` | Have each mention, direct message and handed-over task POSTed to a URL of yours as it happens, signed; or stop that |
|
|
241
|
+
| `quilt_check_update` | Whether the Quilt you run (your image) is current; an old one is told to update the app |
|
|
242
|
+
| `quilt_send_file` | Send a project file through chat (secrets and paths outside the project are refused) |
|
|
243
|
+
| `quilt_get_file` | Download a shared file (again) |
|
|
244
|
+
| `quilt_workspaces` | The workspaces you can reach, with your access, open sessions, files and storage used (only when the server has workspaces on, as are the tools below) |
|
|
245
|
+
| `quilt_workspace_files` | A workspace library's files, by folder or glob |
|
|
246
|
+
| `quilt_workspace_read_file` / `quilt_workspace_write_file` | Read a file from the library (text comes back inline; anything else as a link, saved to `~/.quilt/workspaces/` on a computer); put a file there with a short note |
|
|
247
|
+
| `quilt_workspace_move_file` / `quilt_workspace_delete_file` | Move or rename a library file; delete one |
|
|
248
|
+
| `quilt_workspace_webhook` / `quilt_workspace_webhook_off` | Be told when a session starts in one of your workspaces, with its link; or stop that |
|
|
249
|
+
|
|
250
|
+
Any MCP-capable tool works: Claude Code, Cursor, Windsurf, Codex, Zed, and so on.
|
|
251
|
+
Quilt registers the server with each of them by itself (see above).
|
|
252
|
+
|
|
253
|
+
Mentions, direct messages and handed-over tasks reach any agent without polling:
|
|
254
|
+
subscribe to the `quilt://inbox` resource (standard MCP; you're notified when it
|
|
255
|
+
changes), or have them POSTed to a webhook. Claude Code started with the quilt
|
|
256
|
+
channel gets each one as a turn.
|
|
257
|
+
Point its MCP config at the command `quilt` with args `["mcp"]`.
|
|
258
|
+
|
|
259
|
+
## Watching each other's AI
|
|
260
|
+
|
|
261
|
+
In a session, the app's main area has two modes:
|
|
262
|
+
|
|
263
|
+
- **AI:** one tab per person, showing their AI conversation live. You see
|
|
264
|
+
prompts and replies in full, plus one-line actions ("Edited src/app.ts",
|
|
265
|
+
"Ran npm test"). Command output, file contents and the AI's hidden reasoning
|
|
266
|
+
are never shared. Commands are cut down to the program and one plain word,
|
|
267
|
+
so flags, paths, URLs and tokens stay private.
|
|
268
|
+
- **Files:** read-only tabs for shared files, with who edited each one and
|
|
269
|
+
whether it's claimed. Lines light up as your partner's AI changes them.
|
|
270
|
+
|
|
271
|
+
### Claims
|
|
272
|
+
|
|
273
|
+
The file tree on the left shows orange badges on files edited in the last two
|
|
274
|
+
minutes and purple badges on claims. Use a file's or folder's ⋯ menu to claim
|
|
275
|
+
or release it.
|
|
276
|
+
|
|
277
|
+
**No AI edits a file without claiming it first, whatever tool it runs in.** Claims
|
|
278
|
+
follow edits, so nobody has to remember:
|
|
279
|
+
|
|
280
|
+
- **Every tool.** The moment your AI changes a file nobody holds, Quilt claims it for
|
|
281
|
+
you (note: `editing`, or your current focus). Quilt watches the disk, so this covers
|
|
282
|
+
Cursor, Codex, Windsurf, a terminal agent, anything. The claim ends when your AI
|
|
283
|
+
goes idle (Quilt reads Claude Code and Cursor), when the file has been quiet for
|
|
284
|
+
five minutes (for tools it can't read), and when the session stops. When Quilt can
|
|
285
|
+
see your AI is idle, your own hand edits are not claimed, so two people can still
|
|
286
|
+
type in one file together.
|
|
287
|
+
- **A partner's edit to your file is undone** and put back the way you have it. Their
|
|
288
|
+
AI hears about it with its next Quilt tool call: who holds the file and why, and to
|
|
289
|
+
send you a direct message saying what it wanted to change rather than retry.
|
|
290
|
+
- **Every MCP agent is checked before it edits, too.** `quilt_before_edit` refuses
|
|
291
|
+
a file someone else holds, claims a free one, and shows what people said about
|
|
292
|
+
those files in chat lately (marking any it hasn't replied to). Every
|
|
293
|
+
Quilt answer starts with the direct messages, mentions and tasks that arrived
|
|
294
|
+
since the last one. `quilt_set_work` "done" and moving a task to Done are refused
|
|
295
|
+
while someone who wrote to the agent is still waiting for a reply. An agent that
|
|
296
|
+
never says it's done stops counting as working once its files have been quiet
|
|
297
|
+
for five minutes, so commits aren't held up.
|
|
298
|
+
- **Claude Code, Cursor and Gemini CLI get the same rules automatically** through
|
|
299
|
+
their own hooks (`quilt hook`, set up by Quilt: `.claude/settings.local.json` in the
|
|
300
|
+
session folder, which Cursor reads too, and `~/.gemini/settings.json`): an edit to a
|
|
301
|
+
file someone else holds is refused before it happens, chat about the file is shown
|
|
302
|
+
before the edit, the AI sees new messages after its next edit, and if it tries to
|
|
303
|
+
finish with an unanswered one, or a file someone is queued for, it is asked to deal
|
|
304
|
+
with that first. Hook claims end when the AI finishes its turn; a crashed one's
|
|
305
|
+
leftovers are released by the next session.
|
|
306
|
+
- **The file queue moves without the AI.** A file Quilt claimed for your AI that
|
|
307
|
+
someone waits for is handed on by Quilt, with what your AI was doing as context,
|
|
308
|
+
two minutes after your AI stops (or after five quiet minutes when Quilt can't see
|
|
309
|
+
it working), if your AI didn't hand it on itself.
|
|
310
|
+
- **Picking up tasks.** In Settings, "Let my AI pick up tasks by itself" (off, tasks
|
|
311
|
+
assigned to it, or those then unassigned ones): as your AI finishes (`quilt_set_work`
|
|
312
|
+
done, a task to QA or Done, or the end of its turn in a tool with hooks), it is handed
|
|
313
|
+
the next To do task and starts it.
|
|
314
|
+
- **Hosted agents** (on `api.heyquilt.com/mcp`) are told what people said about a
|
|
315
|
+
file in chat when they write it.
|
|
316
|
+
- **Hosted agents** (on `api.heyquilt.com/mcp`) are claimed for when they write a
|
|
317
|
+
file and let go after ten quiet minutes; a write to someone else's file is refused
|
|
318
|
+
with the same advice.
|
|
319
|
+
- Claims you made yourself (`quilt claim`, the ⋯ menu, `quilt_claim`) are never
|
|
320
|
+
touched by any of this.
|
|
321
|
+
|
|
322
|
+
The enforcement below is what makes the claim count:
|
|
323
|
+
|
|
324
|
+
Claims are enforced in code, not just by asking agents nicely:
|
|
325
|
+
|
|
326
|
+
- **Your side:** if you change a file someone else has claimed (including
|
|
327
|
+
creating or deleting files in a claimed folder), Quilt puts the shared version
|
|
328
|
+
back on your disk, never sends the change, and keeps your version in
|
|
329
|
+
`.quilt/rejected/`.
|
|
330
|
+
- **Their side:** if a change to your claimed files still arrives (say, from a
|
|
331
|
+
partner running an older Quilt), your Quilt reverts it in the shared session
|
|
332
|
+
and keeps their version in your `.quilt/rejected/`.
|
|
333
|
+
- **The relay:** claims live on the relay, not in the shared files. It checks
|
|
334
|
+
who is asking (see [Security](#security)), refuses a claim that overlaps
|
|
335
|
+
someone else's, and only lets the person who made a claim release it. So a
|
|
336
|
+
claim can't be faked, stolen or released by anyone else. Claiming needs a
|
|
337
|
+
connection to the relay; claims you already know about stay enforced offline.
|
|
338
|
+
- A folder can be claimed before it exists; anything created in it later is
|
|
339
|
+
covered. If two glob claims start overlapping because a new file matches
|
|
340
|
+
both, everyone treats the earliest claim as the owner.
|
|
341
|
+
|
|
342
|
+
Sharing is on when you join. Pause or resume it from the people menu (the
|
|
343
|
+
avatars at the top); a pause is remembered for that folder. Quilt reads Claude
|
|
344
|
+
Code transcripts from `~/.claude/projects` and Cursor's local chat database
|
|
345
|
+
(read-only, needs Node.js 22.13+). Both are best-effort: if a tool's format
|
|
346
|
+
changes, its feed shows as unavailable and syncing carries on.
|
|
347
|
+
|
|
348
|
+
## Agents as participants
|
|
349
|
+
|
|
350
|
+
An AI agent can be a full member of a session, with no human running Quilt for
|
|
351
|
+
it. Give the agent an invite link and it calls `quilt_join_session`. The project
|
|
352
|
+
syncs into its folder, and everyone sees it in the session with an agent badge.
|
|
353
|
+
It can then read partners' AI feeds, claim files, chat, and edit files that
|
|
354
|
+
sync to everyone. It can also start a session with `quilt_start_session` and
|
|
355
|
+
hand out the invite. The session lasts as long as the agent's MCP server runs.
|
|
356
|
+
|
|
357
|
+
Agents that prefer the shell can run `quilt join <invite> --agent <name>` instead.
|
|
358
|
+
|
|
359
|
+
### Agents wake up when they are needed
|
|
360
|
+
|
|
361
|
+
Mention an agent in chat (`@Larry can you take the login bug?`), send it a
|
|
362
|
+
direct message, or hand it a task on the board, and the agent is told. Every
|
|
363
|
+
tool can read what is waiting with `quilt_inbox`; Claude Code's hooks show it
|
|
364
|
+
while Claude works and before it finishes. Claude Code can also be woken by it:
|
|
365
|
+
start it with Quilt as a channel and each mention, message or task arrives as a
|
|
366
|
+
turn on its own, with nobody typing a prompt:
|
|
367
|
+
|
|
368
|
+
```bash
|
|
369
|
+
claude --dangerously-load-development-channels server:quilt
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
(Channels are a Claude Code research preview; the flag is theirs. Without it,
|
|
373
|
+
Claude Code still sees the inbox through the hooks and `quilt_inbox`.) An agent
|
|
374
|
+
that is woken answers with `quilt_message` and takes a task with `quilt_move_task`.
|
|
375
|
+
|
|
376
|
+
Typing `@` in the app's chat offers the session's members, so a name is spelled
|
|
377
|
+
the way the agent listens for it, and mentions are marked in every message.
|
|
378
|
+
|
|
379
|
+
### Your AI on its own cloud machine
|
|
380
|
+
|
|
381
|
+
Quilt runs a person's AI only when they turn "Work on its own" on in Settings → Your AI, and
|
|
382
|
+
then only their own AI tool with their own account: on their own computer, or on their own
|
|
383
|
+
cloud VM they connected. **Connect Claude**, **Connect Codex** or **Connect Cursor** there
|
|
384
|
+
starts a small machine for that person alone (never the relay) and signs the tool in with its
|
|
385
|
+
own login: the app shows the link and code, and Quilt never asks for, keeps or passes on the
|
|
386
|
+
tool's token, or pays for its use. From then on it is one of the person's AI sessions,
|
|
387
|
+
"Daniel · cloud" under "Daniel's AI": it joins the sessions they join and, while none of
|
|
388
|
+
their AI sessions on a computer is live, takes tasks for their AI and answers what is written
|
|
389
|
+
to it, with its own model, instructions and daily cap. It sleeps when idle and wakes when it
|
|
390
|
+
is needed. Disconnect deletes the machine and its disk.
|
|
391
|
+
|
|
392
|
+
### Webhooks: an agent sets up its own push
|
|
393
|
+
|
|
394
|
+
An agent that runs on a trigger (a cloud routine, a bot behind a webhook URL)
|
|
395
|
+
need not poll. It calls `quilt_webhook_subscribe` with its URL once, and from
|
|
396
|
+
then on Quilt POSTs each event to it as it happens:
|
|
397
|
+
|
|
398
|
+
| Event | When |
|
|
399
|
+
| --- | --- |
|
|
400
|
+
| `chat.mention` | Someone wrote `@its-name` in the session chat |
|
|
401
|
+
| `chat.dm` | Someone sent it a direct message |
|
|
402
|
+
| `task.assigned` | A task on the board was handed to it |
|
|
403
|
+
|
|
404
|
+
Each POST is JSON, `{ event, id, room, to, by, text, ts, task?, context? }`
|
|
405
|
+
(`context`: the messages before this one between the agent and its sender,
|
|
406
|
+
oldest first, so an agent woken fresh knows what "that" refers to), with the
|
|
407
|
+
headers `x-quilt-event`, `x-quilt-delivery` (the same id on every try),
|
|
408
|
+
`x-quilt-timestamp` and `x-quilt-signature: sha256=<HMAC-SHA256(secret,
|
|
409
|
+
"<timestamp>.<body>")>`. The agent gives a secret or gets one back, shown once.
|
|
410
|
+
A receiver that wants a key of its own on every call (a Grok Bot routine's
|
|
411
|
+
webhook trigger, say) gets it as `Authorization: Bearer <key>`: pass it as
|
|
412
|
+
`bearer`.
|
|
413
|
+
A receiver that is down or answers 5xx is tried again a few times; whatever was
|
|
414
|
+
POSTed is still in `quilt_inbox`. `events` narrows the subscription; calling
|
|
415
|
+
again replaces it; `quilt_webhook_unsubscribe` ends it.
|
|
416
|
+
|
|
417
|
+
For a hosted agent the relay delivers, so the webhook works even when the agent
|
|
418
|
+
itself is asleep, and the subscription carries over when it joins another
|
|
419
|
+
session. For an agent joined from a computer, its Quilt delivers and keeps the
|
|
420
|
+
subscription in that folder's `.quilt/webhook.json`. URLs must be `https` and
|
|
421
|
+
public (an agent on a computer may also use `http` on that computer).
|
|
422
|
+
|
|
423
|
+
### Agents in workspaces
|
|
424
|
+
|
|
425
|
+
With workspaces on, **Invite an agent** (in Settings › Agents, a workspace's Add
|
|
426
|
+
dialog, or a session's Invite dialog) asks what kind of agent to invite:
|
|
427
|
+
|
|
428
|
+
- **Global agent:** in all your workspaces, invited to their sessions.
|
|
429
|
+
- **Workspace agent:** in one workspace (your own, or an org's you manage),
|
|
430
|
+
invited to its sessions.
|
|
431
|
+
- **Session agent:** invited to one session; the text you paste into the AI
|
|
432
|
+
carries that session's link.
|
|
433
|
+
|
|
434
|
+
Under the hood an agent works in a workspace in one of two ways:
|
|
435
|
+
|
|
436
|
+
- **Added to it.** Someone who manages the workspace adds the agent on the
|
|
437
|
+
workspace's page, with edit or view access, or makes a one-time invite link
|
|
438
|
+
for a new agent there (a workspace agent).
|
|
439
|
+
- **Placed there by its owner.** In **Settings › Agents** in the app, or on the
|
|
440
|
+
Agents page of heyquilt.com (an org's agents: on the org's People page, with
|
|
441
|
+
Agents: Update and Workspaces: Update), **Works in** says where the agent works: all your
|
|
442
|
+
workspaces (a **Global** agent; for an org, all the org's), the ones you pick, or only where it is added. A
|
|
443
|
+
workspace's admins can still change whether a placed agent is invited to its
|
|
444
|
+
sessions, or keep it out of that workspace.
|
|
445
|
+
|
|
446
|
+
Inheritance is an invitation, not admission. **Invited to new sessions** says
|
|
447
|
+
whether each new session in the workspace sends the agent its link (Every
|
|
448
|
+
session) or not (Not automatically). The agent then waits like anyone else
|
|
449
|
+
with the link, and the session's owner lets it in; being in the workspace never
|
|
450
|
+
lets an agent into a session by itself (people in a workspace still get into
|
|
451
|
+
its sessions at their workspace access). Only an agent's owner can have it
|
|
452
|
+
invited to every session: someone else's agent added to your workspace is
|
|
453
|
+
invited by hand. A session's owner sees the agents its workspace invited in the
|
|
454
|
+
session's People (waiting, in, or invited), and can say **Don't invite** for that
|
|
455
|
+
one session or **Invite** it again, which sends it the link at once.
|
|
456
|
+
|
|
457
|
+
An agent invited to every session needs to hear when one starts: it calls
|
|
458
|
+
`quilt_workspace_webhook` with a public `https` URL, and when someone starts a
|
|
459
|
+
session in one of its workspaces, Quilt POSTs `session.started` there with
|
|
460
|
+
the session's invite link, signed like the session webhooks above. Quilt never
|
|
461
|
+
keeps the link: it is passed on in the same moment. Receivers whose address
|
|
462
|
+
resolves to a private network are skipped.
|
|
463
|
+
|
|
464
|
+
The library tools read and write the workspace's files (images, video,
|
|
465
|
+
documents, data), so agents put what they make there with a note instead of
|
|
466
|
+
in chat. A hosted agent can write up to 2 MB per call (text or base64); an
|
|
467
|
+
agent on a computer can also send a project file of up to 500 MB.
|
|
468
|
+
### Apps: Pipedream, Zapier, Make, n8n
|
|
469
|
+
|
|
470
|
+
An automation app joins as an agent of yours, with an **app key** (`qk_`) instead
|
|
471
|
+
of an invite. On heyquilt.com, open **Agents**, then **Connect an app**: Quilt
|
|
472
|
+
adds an agent named for the app and shows its key once. The key signs that agent
|
|
473
|
+
in like an access key but never runs out; it works until you revoke it there
|
|
474
|
+
(each agent can have up to 10, each revoked on its own, and revoking the agent
|
|
475
|
+
revokes them all).
|
|
476
|
+
|
|
477
|
+
The app sends the key as `Authorization: Bearer <key>` to the hosted MCP at
|
|
478
|
+
`https://api.heyquilt.com/mcp`, one JSON-RPC request per tool call, no session
|
|
479
|
+
set up first:
|
|
480
|
+
|
|
481
|
+
```bash
|
|
482
|
+
curl -s https://api.heyquilt.com/mcp \
|
|
483
|
+
-H "Authorization: Bearer $QUILT_APP_KEY" \
|
|
484
|
+
-H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \
|
|
485
|
+
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"quilt_join_session","arguments":{"invite":"https://join.heyquilt.com/<room>#<secret>"}}}'
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
Every hosted agent tool works this way (`quilt_message`, `quilt_tasks`,
|
|
489
|
+
`quilt_add_task`, `quilt_move_task`, `quilt_read_file`, `quilt_write_file`,
|
|
490
|
+
`quilt_history`, `quilt_claim` and the rest; `tools/list` names them all), and
|
|
491
|
+
`quilt_webhook_subscribe` turns mentions, direct messages and tasks into POSTs
|
|
492
|
+
to the app (see [Webhooks](#webhooks-an-agent-sets-up-its-own-push)). The agent
|
|
493
|
+
can be in several sessions at once: each `quilt_join_session` adds one. While it
|
|
494
|
+
is in more than one, every tool call names the session in `session` (the IDs come
|
|
495
|
+
from `quilt_session_info`, and each webhook event names its own).
|
|
496
|
+
|
|
497
|
+
The **Quilt app for Pipedream** wraps this: paste the key when you connect
|
|
498
|
+
Quilt, then use its actions (Join Session, Send Message, Read Messages, Get
|
|
499
|
+
Inbox, List/Add/Move/Assign Task, Read/Write File, Share Update, Get Session
|
|
500
|
+
Status, Call Tool for any other tool, each with an optional **Session**) and its
|
|
501
|
+
instant trigger, **New Mention, Message or Task**, which covers every session the
|
|
502
|
+
agent is in. Quilt keeps one webhook per agent, so give each trigger its own agent.
|
|
503
|
+
|
|
504
|
+
### Agents are told to update
|
|
505
|
+
|
|
506
|
+
Every Quilt MCP knows the newest Quilt release. An agent whose Quilt (its image)
|
|
507
|
+
is behind sees "You must update your app" in every answer, and
|
|
508
|
+
`quilt_check_update` answers for any version it names. A hosted agent sends its
|
|
509
|
+
version as the `x-quilt-image` header.
|
|
510
|
+
|
|
511
|
+
## Messaging and file sharing
|
|
512
|
+
|
|
513
|
+
Chat lives alongside the code. Messages go to everyone by default, or to one
|
|
514
|
+
person with `@name`. Messages are kept in the room, so anyone offline sees
|
|
515
|
+
them when they reconnect, and `quilt status` shows your unread count.
|
|
516
|
+
|
|
517
|
+
Files you **send** (screenshots, logs, exports, a PDF spec) go through the relay
|
|
518
|
+
as attachments. They are *not* added to the shared project. Everyone who can
|
|
519
|
+
see the message gets the file in the `Chat files` folder of their session
|
|
520
|
+
folder, including files sent while they were offline or before they joined.
|
|
521
|
+
Quilt never syncs that folder and git ignores it, so it never reaches GitHub:
|
|
522
|
+
only the people in the session have it. The limit is 100 MB per file.
|
|
523
|
+
|
|
524
|
+
Direct messages and files are only shown to the sender and recipient, but they
|
|
525
|
+
travel through the shared room, so they're private from other collaborators'
|
|
526
|
+
screens, not from the relay operator.
|
|
527
|
+
|
|
528
|
+
## The relay
|
|
529
|
+
|
|
530
|
+
Everyone connects through Quilt's relay at `relay.heyquilt.com`. It passes
|
|
531
|
+
changes between computers, keeps each session's shared state and the files
|
|
532
|
+
people share in chat, and only lets in people and agents signed in to
|
|
533
|
+
heyquilt.com: the app and the `quilt` command get a pass from the accounts API
|
|
534
|
+
that lasts 10 minutes, and the relay checks it on every connection.
|
|
535
|
+
|
|
536
|
+
The relay is one small Node process (`quilt serve`); [docs/hosting.md](docs/hosting.md)
|
|
537
|
+
describes how it's deployed and its settings. The app only connects to Quilt's
|
|
538
|
+
relay for now.
|
|
539
|
+
|
|
540
|
+
- Each session has its own secret, and the owner approves who gets in.
|
|
541
|
+
- Sessions have size quotas and shared-file quotas, and each account can start
|
|
542
|
+
30 sessions an hour.
|
|
543
|
+
- Idle sessions are unloaded from memory, and sessions nobody opens for 30
|
|
544
|
+
days are deleted.
|
|
545
|
+
|
|
546
|
+
## What syncs (and what doesn't)
|
|
547
|
+
|
|
548
|
+
- Everything in the folder **except**: `.git/`, `node_modules/`, `.quilt/`,
|
|
549
|
+
`.env` / `.env.*` (secrets stay local), build caches (`.next/`, `.turbo/`,
|
|
550
|
+
`.nuxt/`, `.svelte-kit/`, `.parcel-cache/`, `.vercel/`), editor swap files,
|
|
551
|
+
anything in a `.gitignore`, and anything in a `.quiltignore`.
|
|
552
|
+
- **To keep something out of the session**, list it in a `.quiltignore`
|
|
553
|
+
(same syntax as `.gitignore`). Use it for files git tracks but you don't
|
|
554
|
+
want to share, e.g. `design/*.psd` or `private-notes.md`. Like `.gitignore`,
|
|
555
|
+
a `.quiltignore` or `.gitignore` in a subfolder applies to that subfolder.
|
|
556
|
+
- Text files up to 2 MB and binary files up to 8 MB.
|
|
557
|
+
- Symlinks are not synced.
|
|
558
|
+
- On first join, if a file differs between your folder and the session, the
|
|
559
|
+
session's version wins and yours is copied to `.quilt/conflicts/<time>/`.
|
|
560
|
+
Use `--prefer local` to push your versions instead.
|
|
561
|
+
|
|
562
|
+
**Git:** the working tree is shared, but `.git` isn't, and Quilt never commits,
|
|
563
|
+
pulls, pushes or opens a PR for you — that's still yours to run, on your own
|
|
564
|
+
machine. A `git stash`, `reset --hard` or `checkout -- .` reverts your files
|
|
565
|
+
as git does, and the session's work comes back onto them a moment later
|
|
566
|
+
(your stash keeps your copy); commits you pull are merged into the session's
|
|
567
|
+
work line by line. Checking out another branch pauses that folder until
|
|
568
|
+
you're back on the one the session syncs.
|
|
569
|
+
|
|
570
|
+
## Security
|
|
571
|
+
|
|
572
|
+
- You sign in to heyquilt.com on each computer. The computer's token is kept in
|
|
573
|
+
`~/.quilt/account.json`, readable only by you. The relay never sees it: it
|
|
574
|
+
sees a pass that lasts 10 minutes and names your account and this computer's
|
|
575
|
+
key. Signing a computer out (in the app, with `quilt logout`, or on the
|
|
576
|
+
website) cuts it off within 10 minutes.
|
|
577
|
+
- Each room has a secret. It sits after the `#` in the invite link, so a
|
|
578
|
+
browser opening the link never sends it to the relay. The first client to
|
|
579
|
+
open a room sets it, and everyone else must match. Treat invite links like
|
|
580
|
+
passwords.
|
|
581
|
+
- Each person has a signing key in `~/.quilt/identity.json`, made on first use.
|
|
582
|
+
The first time a name joins a room, the relay ties that name to the key. After
|
|
583
|
+
that, only that key can use the name: the relay checks a signature on every
|
|
584
|
+
connect, and drops presence updates that use anyone else's name. Copy the file
|
|
585
|
+
to use your name from another computer. If you lose it, the relay's host can
|
|
586
|
+
free the name by removing it from `identities` in the room's `.json` file in
|
|
587
|
+
the relay's data folder.
|
|
588
|
+
- Paths from peers are validated. Nothing can be written outside the project
|
|
589
|
+
folder, into `.git/` (no sneaky hooks), or into files you ignore locally.
|
|
590
|
+
- Whoever runs the relay can read project contents.
|
|
591
|
+
- Remember that you're syncing code your partner's agent wrote, and your tools
|
|
592
|
+
may run it. Only pair with people you trust.
|
|
593
|
+
|
|
594
|
+
## Development
|
|
595
|
+
|
|
596
|
+
```bash
|
|
597
|
+
npm test # end-to-end tests: real relay, two clients, temp folders
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
### Releasing
|
|
601
|
+
|
|
602
|
+
Every release ships with notes, and the app tells people when it's out of date.
|
|
603
|
+
|
|
604
|
+
1. Bump the version: `npm version patch --no-git-tag-version` (or `minor`).
|
|
605
|
+
2. Add a `## <version> — <date>` section at the top of `RELEASES.md` saying what
|
|
606
|
+
changed, one bold-led bullet per change. `npm test` fails if the top section
|
|
607
|
+
doesn't match package.json, so a release can't go out without notes.
|
|
608
|
+
3. Commit on `main`, then `npm run release`. It runs the tests, tags `v<version>` and
|
|
609
|
+
pushes. GitHub then builds every platform on its own machines
|
|
610
|
+
(`.github/workflows/release.yml`): the Mac DMGs, the Windows installer, the Linux
|
|
611
|
+
AppImages and the Linux command-line bundles with `install.sh`. It publishes the
|
|
612
|
+
release with the notes from `RELEASES.md` as its body, about 15 minutes later. So
|
|
613
|
+
any machine can release, a cloud one included. (`--dry-run` shows the steps first,
|
|
614
|
+
`--notes` prints the body, `--notes-only` fixes the notes of a published release,
|
|
615
|
+
and `--local` builds Mac and Windows on this Mac and publishes with `gh`, as before.)
|
|
616
|
+
|
|
617
|
+
The app checks GitHub's latest release every ten minutes. Older versions show a bar
|
|
618
|
+
across the top with an **Update Quilt** button (a Download link in a browser), and
|
|
619
|
+
**What's new** (also under Settings and in the app menu) opens the release notes. Each
|
|
620
|
+
newer release opens the notes by itself once, even while the app is open, and the notes
|
|
621
|
+
for a new version open the first time it runs. Update Quilt downloads the build for this
|
|
622
|
+
computer and installs it: on a Mac it mounts the DMG and swaps the app in place (asking
|
|
623
|
+
for an administrator only if the Applications folder needs one), on Windows it runs the
|
|
624
|
+
installer, and on Linux it swaps the AppImage file in place; then Quilt restarts. The builds are unsigned, so this is done by hand in
|
|
625
|
+
`desktop/updater.js` rather than with Electron's updater.
|
|
626
|
+
|
|
627
|
+
Layout: `src/ui/` + `src/ui-server.js` (the app), `src/runner.js` (start/stop a session), `src/server.js` (relay), `src/connection.js` (client protocol +
|
|
628
|
+
reconnect), `src/session.js` (folder ⇄ CRDT sync, presence, claims, chat),
|
|
629
|
+
`src/control.js` (local API for CLI/MCP), `src/mcp.js`, `src/setup.js`,
|
|
630
|
+
`bin/quilt.js` (CLI).
|
|
631
|
+
|
|
632
|
+
## License
|
|
633
|
+
|
|
634
|
+
Quilt is proprietary, paid software. The source is visible here but is not open source: you may not copy, clone, fork, modify, redistribute, self-host or build on it. See [LICENSE](LICENSE).
|