Skip to content

feat: attach repositories to messages and clone them into .context - #89

Merged
adampeterhiggins merged 6 commits into
mainfrom
ah/attach-context-repositories
Sep 30, 2026
Merged

adampeterhiggins merged 6 commits into
mainfrom
ah/attach-context-repositories

Conversation

@adampeterhiggins

Copy link
Copy Markdown
Owner

Starting a thread that needs other repositories as context meant clicking Create worktree first, then running ctxclone in that worktree's .context/ by hand before writing the first message.

Now you can attach repositories to a message. T3 Code clones whatever is missing into the workspace's .context/ folder before the agent starts.

How it works

  • Picker. Attach → Repository in the composer (or Attach repository in the command palette) lists the default owner's GitHub repositories via gh repo list, with recently attached repositories first, like ctxclone's completion ranking. Typing org/ lists another owner, and a pasted owner/repo or clone URL also works. Repositories already in the thread's workspace are marked with their branch, ahead/behind, and changed-file count.
  • Chip. A picked repository becomes a repository context record, a new kind in composerContext.ts.
  • Clone on send (apps/server/src/contextRepositories/ContextRepositories.ts). Full clones, as ctxclone does, with up to 4 in parallel.
    • Missing → cloned.
    • Already a clone of the same remote → left alone and not pulled. It is fetched so ahead/behind are current.
    • A folder that belongs to something else → reported and never overwritten.
    • Failed, timed-out, or cancelled clones remove their partial .git.
    • .context/ is added to the repository's info/exclude, so checkpoints and diffs ignore the clones.
  • Where it runs (ws.ts). On a new worktree it's a new Clone context repositories stage on the setup card, after checkout and before the setup script. Other sends (local first send, follow-ups) clone before the turn is recorded.
  • The agent knows what happened. Each record's outcome (cloned / present / conflict / failed, the detail, and git status) is written back onto the message. The prompt projection spells it out, for example: status: already cloned; left as it was, not pulled / git: on main, 0 ahead and 3 behind origin/main, clean working tree. The bootstrap path persists the message before the worktree exists, so the decider now restates a persisted message when the turn start carries changed context (decider.ts). Failures are warnings, and the agent still starts.
  • Settings. Settings → General → Repository owner (default owner) and Repository folder (default .context). Both are server settings.

Surfaces

  • Web and desktop: picker, chips, setup stage, and settings.
  • Mobile: renders the chips and details, and the setup stage with its warning lines. There's no picker on mobile yet.
  • Providers: nothing provider-specific. The clones are files in the workspace, and the prompt text works for all providers.
  • Remote: clones run on the server host with its git/gh credentials.

Testing

  • New tests: ContextRepositories.test.ts (real git: clone, present with ahead/behind after a remote push, conflict, failed, outside-workspace folder refused, inspect, porcelain parsing), two server.test.ts integration tests (bootstrap order ensure → setup script → turn, and the follow-up path), a decider restatement test, the projection text, contract round-trips, and client input parsing.
  • Typecheck is clean for contracts, shared, client-runtime, server, web, and mobile.
  • server.test.ts > flushes more than one tool chunk before the synchronization marker fails on this branch. It's about the tool-call preview field, which this PR doesn't touch.
  • No before/after screenshots yet: I didn't run the app in a browser.

🤖 Generated with Claude Code (Claude Opus 5.5 in T3 Code)

adampeterhiggins and others added 6 commits September 30, 2026 16:27
Picking a repository from the composer's attach menu (or the command
palette) adds a `repository` chip. On send, the server clones anything
missing into the workspace's `.context/` folder before the agent starts,
like ctxclone: a new worktree gets it as a setup-card step before the setup
script, other sends clone before the turn is recorded. Existing clones of
the same remote are left alone and only fetched; folders that belong to
something else are never overwritten; failures warn and the agent still
starts. Each record's outcome and git status are written back onto the
message, so the chip and the agent's prompt both say what happened.

The picker lists the default owner's GitHub repositories (`gh repo list`),
ranks recent picks first, accepts `org/` and pasted URLs, and marks
repositories already in the workspace with their branch and ahead/behind.
Default owner and folder are server settings under Settings > General.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…-ups

A send into an existing workspace has no setup card, so the clone now
records a work log row (one per message, upserted) that reports progress
and each repository's outcome before the turn starts.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant