You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(source-control): remotes like github.com:owner/repo reach their host - #29457
Git reads github.com:owner/repo.git as an SSH remote and takes the user from ssh config, so this is a working remote for anyone whose ~/.ssh/config sets User git. T3 Code keyed the repository correctly, but only user@host:path counted as naming a host, so the remote got no source control provider.
Call path: parseGitRemoteHost (packages/source-control-core/src/shared/definition.ts) falls through to new URL("github.com:owner/repo.git"), which parses as a custom scheme with an empty host, and returns null. recognizeRemote then returns null, which has two effects:
RepositoryIdentityResolver.buildRepositoryIdentity leaves provider off the identity, and PullRequestService skips projects with no provider, so their pull requests never list.
SourceControlProviderRegistry.selectProviderContext finds no candidate, so resolveHandle returns the unknown provider and every call fails with "No unknown source control provider is registered."
The same repository on git@github.com:owner/repo.git works. The GitLab provider already had a local workaround with the comment "Remote host parsing does not recognize userless SCP remotes", and normalizeGitRemoteUrl and parseForgejoRemote already have tests for this form.
Change
packages/shared/src/sourceControl.ts gains userlessScpRemoteHost, and the places that needed user@ now also accept host:path:
parseGitRemoteHost, so recognizeRemote finds the host.
isSshRemoteUrl, so these remotes keep preferring SSH and SSH-only host handling applies, the same as their git@ spelling.
repositoryPathFromRemoteUrl, so the display name keeps its case and head-owner lookups find an owner.
parseGitCafeRemote, because GitCafe reads the repository from the remote itself.
The GitLab workaround is gone, since parseGitRemoteHost now does that job.
A remote on a host no forge claims, such as an ssh alias gh:owner/repo, now reads as unknown with its server's address, exactly as git@gh:owner/repo already did. It does not resolve the alias; that is #17805.
These still find no host: Windows drives (C:/repos/x), local paths (/srv/git/x, ./team:group/repo), file://, and remote helpers (hg::owner/repo, codecommit::us-east-1://repo).
Scope and approval
A small, focused fix of an obvious bug, with no prior issue. One underlying problem: one form of remote that git accepts was not recognized as naming a host. The code already acknowledged the gap in a comment, and nothing here adds behavior beyond making this form match its git@ spelling. No contract or client changes.
Searched open issues and PRs for this. Nearest are #17805 and #14919 (ssh aliases resolved with ssh -G), which address a different problem and touch RepositoryIdentityResolver rather than parseGitRemoteHost, and #22620 / #22625 (forge SSH hosts such as ssh.bitbucket.org).
Verification
Each focused test ran against the unfixed code first, then with the fix.
Before:
× reads the host of an SSH remote that leaves its user to ssh config: github.com:team/project.git
AssertionError: expected 'unknown' to equal 'github'
× reads the host of an SSH remote that leaves its user to ssh config: gitlab.com:team/project.git
AssertionError: expected 'unknown' to equal 'gitlab'
× reads the host of an SSH remote that leaves its user to ssh config: bitbucket.org:team/project.git
AssertionError: expected 'unknown' to equal 'bitbucket'
× reads the host of an SSH remote that leaves its user to ssh config: code.example.test:team/project.git
AssertionError: expected undefined to equal 'code.example.test:team/project.git'
× identifies the host of an SSH remote that leaves its user to ssh config
AssertionError: expected undefined to be 'github'
× reads github.com:owner/repo.git as SSH
× reads github-work:owner/repo.git as SSH
× reads the repository path of github.com:T3Tools/t3code.git
× reads the repository path of gitlab.com:T3Tools/platform/t3code
× reads the host and repository of git.cafe:team/project.git
The RepositoryIdentityResolver test uses a real git init and git remote add origin github.com:T3Tools/t3code.git. The cases that must stay hostless were already passing and still pass, so they guard against over-matching.
Neighbouring suites also pass: GitLab provider and discovery (15), GitHub provider and discovery (42), GitCafe provider (8), Forgejo provider (37), packages/sharedgit.test.ts (30). Targeted vp fmt, vp lint and tsc --noEmit are clean in every changed package, and the commit hook's knip check passed.
Not checked: a live forge. The real gh, glab and Bitbucket calls were not run against a remote of this form; the tests stop at the provider chosen for it, and the providers downstream read the host and path through helpers that already handle this form. No visible UI strings or layout changed, though projects on these remotes will now show pull requests where they showed none.
Git reads `host:path` as SSH and takes the user from ssh config, but only
`user@host:path` was read as naming a host. A checkout on such a remote got
no provider, so pull request sync skipped it and every provider call failed
as an unknown host.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Macroscope's review found this PR approvable — Userless SSH remotes such as github.com:owner/repo now reach the existing provider and retain SSH transport. The change is limited to remote recognition and routing, with existing host validation retained.
You can add or adjust custom eligibility rules. Learn more.
The changes add recognition for supported SCP-style Git remotes without a username. Shared parsing and provider handling use this recognition, and tests cover remote classification, repository paths, provider resolution, and repository identity.
A shared helper recognizes supported userless host:path remotes. SSH classification and host parsing use this helper. Tests cover supported and rejected remote formats.
Repository path parsing accepts userless SCP-style remotes. GitLab remote detection passes the original URL to host parsing instead of converting it first.
Provider and identity integration packages/source-control-gitcafe/src/server/*, apps/server/src/project/RepositoryIdentityResolver.test.ts, apps/server/src/sourceControl/*
GitCafe host parsing accepts remotes without a username, and its SSH detection uses the shared helper. Application tests cover provider resolution, remote retention, rejected formats, and repository identity.
Userless host:path remotes now get a provider and fork checkouts for them use the GitCafe ssh@ URL. That could matter for someone whose SSH config selects an identity by user, but this is unconfirmed and limited to GitCafe fork checkouts. The change is mergeable with that caveat in mind.
Pre-merge checks: 4
Check name
Status
Explanation
Title check
The title names the main change: remotes written as host:path, such as github.com:owner/repo, are now resolved to their host. It follows the conventional commit format. The changeset adds userlessScpR…
Description check
The description follows the template. It has Problem, Change, Scope and approval, and Verification sections. The problem, the call path, and the affected behavior are explained. The change lists the m…
Linked Issues check
Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check
Check skipped because no linked issues were found for this pull request.
Full details: Title check
Explanation
The title names the main change: remotes written as host:path, such as github.com:owner/repo, are now resolved to their host. It follows the conventional commit format. The changeset adds userlessScpRemoteHost and uses it in host parsing, SSH detection, repository path parsing, and GitCafe parsing, which matches the title.
Full details: Description check
Explanation
The description follows the template. It has Problem, Change, Scope and approval, and Verification sections. The problem, the call path, and the affected behavior are explained. The change lists the modified functions and the forms that still stay hostless. Scope names the small-fix exemption, cites related open issues and PRs, and gives reasons. Verification shows before and after test output, the neighboring suites that ran, and states what was not checked, which is the live forge calls. The description does not include a template-required note about the CONTRIBUTING.md read, but this is a minor, non-critical item. It also does not state a maintainer-approval link. The author explains why the small-fix exemption applies, which the template allows.
Finishing Touches
Generate unit tests (beta)
Create a new PR
Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
481-481: Major · Functional Correctness · Quick win
Unverified finding
Verification ran but could not confirm this finding. It is shown for review, not as a verified issue.
Preserve the configured SSH user for fork checkouts.
For a userless git.cafe:team/project remote, the new SSH check selects this ssh@ URL when checkout needs a fork remote. That overrides the configured user. If SSH config selects the identity with Match user, the fork fetch can fail even though the original remote works. Preserve the userless form for userless remotes. (man.openbsd.org)
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.
Declining the unverified CodeRabbit note on GitCafeSourceControlProvider.ts:481 (preserve the userless form for fork checkouts). GitCafe fork remotes hard-code ssh@, the same user cloneUrls advertises, and every other SSH spelling of the remote already takes this path. A userless remote that works must already resolve to that user through ssh config, so ssh@ selects the same user and a Match user rule still applies. Keeping a separate userless form would add a special case for a failure that does not arise.
verified as-is at 73a81531d1b018c5f553b713e29f4dc5a3186b18 on a linux boat vm. installed both revisions with vp i and ran one background dev server at a time. used repo playwright with /usr/bin/google-chrome, isolated app state, app-created projects and a real codex gpt-6.1-sol turn. no mocks or demo data.
reproduced on github/main (30b9c4a956): a real repository with only origin=github.com:pingdotgg/t3code.git had an empty project-filtered pull-request list. authenticated git.resolvePullRequest failed with No unknown source control provider is registered.
neighboring server checks passed for the explicit-user github ssh remote, https://github.com/pingdotgg/t3code.git, and userless git.cafe:pingdotgg/t3code.git, each resolving this pr through its real forge provider.
the real codex turn completed and reported the userless origin and clean working tree.
blacksmith vp run check:changed c8a601c0dfa5c7626e51e06d727076f6b840a005 passed: 82 tests across 10 files, format, lint, knip, graphql and affected-package typechecks. existing ci reports 30/30 successful. no source changes needed.
ssh network fetch/push and git.cafe fork checkout: this vm has no ssh private key. live gitlab and bitbucket calls: no credentials. native desktop, ios/android, macos/windows, and relay/tunnel connections were not exercised. the web client and local running-server paths above were exercised.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
size:S10-29 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.
2 participants
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Git reads
github.com:owner/repo.gitas an SSH remote and takes the user from ssh config, so this is a working remote for anyone whose~/.ssh/configsetsUser git. T3 Code keyed the repository correctly, but onlyuser@host:pathcounted as naming a host, so the remote got no source control provider.Call path:
parseGitRemoteHost(packages/source-control-core/src/shared/definition.ts) falls through tonew URL("github.com:owner/repo.git"), which parses as a custom scheme with an empty host, and returns null.recognizeRemotethen returns null, which has two effects:RepositoryIdentityResolver.buildRepositoryIdentityleavesprovideroff the identity, andPullRequestServiceskips projects with no provider, so their pull requests never list.SourceControlProviderRegistry.selectProviderContextfinds no candidate, soresolveHandlereturns theunknownprovider and every call fails with "No unknown source control provider is registered."The same repository on
git@github.com:owner/repo.gitworks. The GitLab provider already had a local workaround with the comment "Remote host parsing does not recognize userless SCP remotes", andnormalizeGitRemoteUrlandparseForgejoRemotealready have tests for this form.Change
packages/shared/src/sourceControl.tsgainsuserlessScpRemoteHost, and the places that neededuser@now also accepthost:path:parseGitRemoteHost, sorecognizeRemotefinds the host.isSshRemoteUrl, so these remotes keep preferring SSH and SSH-only host handling applies, the same as theirgit@spelling.repositoryPathFromRemoteUrl, so the display name keeps its case and head-owner lookups find an owner.parseGitCafeRemote, because GitCafe reads the repository from the remote itself.The GitLab workaround is gone, since
parseGitRemoteHostnow does that job.A remote on a host no forge claims, such as an ssh alias
gh:owner/repo, now reads asunknownwith its server's address, exactly asgit@gh:owner/repoalready did. It does not resolve the alias; that is #17805.These still find no host: Windows drives (
C:/repos/x), local paths (/srv/git/x,./team:group/repo),file://, and remote helpers (hg::owner/repo,codecommit::us-east-1://repo).Scope and approval
A small, focused fix of an obvious bug, with no prior issue. One underlying problem: one form of remote that git accepts was not recognized as naming a host. The code already acknowledged the gap in a comment, and nothing here adds behavior beyond making this form match its
git@spelling. No contract or client changes.Searched open issues and PRs for this. Nearest are #17805 and #14919 (ssh aliases resolved with
ssh -G), which address a different problem and touchRepositoryIdentityResolverrather thanparseGitRemoteHost, and #22620 / #22625 (forge SSH hosts such asssh.bitbucket.org).Verification
Each focused test ran against the unfixed code first, then with the fix.
Before:
After:
The
RepositoryIdentityResolvertest uses a realgit initandgit remote add origin github.com:T3Tools/t3code.git. The cases that must stay hostless were already passing and still pass, so they guard against over-matching.Neighbouring suites also pass: GitLab provider and discovery (15), GitHub provider and discovery (42), GitCafe provider (8), Forgejo provider (37),
packages/sharedgit.test.ts(30). Targetedvp fmt,vp lintandtsc --noEmitare clean in every changed package, and the commit hook's knip check passed.Not checked: a live forge. The real
gh,glaband Bitbucket calls were not run against a remote of this form; the tests stop at the provider chosen for it, and the providers downstream read the host and path through helpers that already handle this form. No visible UI strings or layout changed, though projects on these remotes will now show pull requests where they showed none.Claude Opus 5.5 (Claude Code desktop app)
🤖 Generated with Claude Code