Skip to content

fix: support custom Git hosts in getOwnerRepo for lockfile tracking#223

Merged
quuu merged 2 commits intovercel-labs:mainfrom
renehernandez:fix/support-custom-git-hosts
Feb 5, 2026
Merged

fix: support custom Git hosts in getOwnerRepo for lockfile tracking#223
quuu merged 2 commits intovercel-labs:mainfrom
renehernandez:fix/support-custom-git-hosts

Conversation

@renehernandez
Copy link
Contributor

@renehernandez renehernandez commented Jan 30, 2026

Summary

  • Updated getOwnerRepo() to support any HTTPS Git host with an owner/repo URL structure
  • Skills installed from self-hosted Git servers (e.g., GitLab CE, Gitea, Forgejo) are now tracked in the lockfile
  • Handle query strings, URL fragments, and GitLab subgroups

Problem

The getOwnerRepo() function only recognized github.com and gitlab.com URLs:

const match = parsed.url.match(/(?:github|gitlab)\.com\/([^/]+)\/([^/]+?)(?:\.git)?$/);

This caused skills installed from self-hosted Git servers to return null, which skipped the lockfile update in add.ts:1827:

if (successful.length > 0 && installGlobally && normalizedSource) {

Solution

Replaced the regex with URL parsing for cleaner handling:

const url = new URL(parsed.url);
let path = url.pathname.slice(1);
path = path.replace(/\.git$/, '');
if (path.includes('/')) {
  return path;
}

This approach:

  • Uses native URL parsing to automatically handle query strings and fragments
  • Supports GitLab nested paths (e.g., group/subgroup/repo)
  • Validates that path has at least owner/repo structure

Test plan

  • Updated existing tests for custom Git hosts to expect owner/repo instead of null
  • Added test cases for URLs with query strings (?ref=main)
  • Added test cases for URLs with fragments (#readme)
  • Added test cases for GitLab subgroups (2-3 levels deep)
  • All 261 tests pass

🤖 Generated with Claude Code

The getOwnerRepo() function previously only recognized github.com and
gitlab.com URLs, causing skills installed from self-hosted Git servers
to not be tracked in the lockfile.

Updated the regex to match any HTTPS Git URL with an owner/repo structure,
enabling lockfile tracking for skills installed from any Git host.
@renehernandez
Copy link
Contributor Author

@quuu Ran into this issue when using npx skills update against an our own internal skills repo in our self-hosted GitLab instance

@renehernandez
Copy link
Contributor Author

Local Testing

Tested the fix locally against a self-hosted GitLab instance:

# Build from source
pnpm build

# Install skills from self-hosted GitLab
node dist/cli.mjs add https://git.example.io/team/skills.git --agent claude-code -y -g

Before fix: Lockfile remained empty ("skills": {})

After fix: Lockfile correctly tracks all installed skills:

{
  "version": 3,
  "skills": {
    "skill-1": {
      "source": "team/skills",
      "sourceType": "git",
      "sourceUrl": "https://git.example.io/team/skills.git",
      "skillPath": "skill-1/SKILL.md",
      "skillFolderHash": "",
      "installedAt": "2026-01-30T17:29:08.822Z",
      "updatedAt": "2026-01-30T17:29:08.822Z"
    },
    ...
  }
}

The source field now correctly extracts team/skills from the custom Git host URL, enabling lockfile tracking.

Note: skillFolderHash remains empty for non-GitHub hosts since fetchSkillFolderHash() uses GitHub's Trees API. This is expected behavior and a separate limitation.

…rRepo

- Replace regex with URL parsing for cleaner handling of edge cases
- Strip query strings (?ref=main) and fragments (#readme) from URLs
- Support GitLab nested paths (group/subgroup/repo)
- Add 7 new test cases covering these scenarios

Addresses review feedback from Devin.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@renehernandez
Copy link
Contributor Author

Addressed Review Feedback

Thanks for the review! I've pushed changes to address the feedback:

Fixed: Query strings and URL fragments (Issue #1)

URLs like https://git.example.com/owner/repo?ref=main or https://git.example.com/owner/repo#readme are now handled correctly by using native URL parsing instead of regex.

Added: GitLab subgroups support (Issue #2)

The function now supports nested GitLab paths:

  • https://gitlab.com/group/subgroup/repogroup/subgroup/repo
  • https://gitlab.com/org/team/project/repo.gitorg/team/project/repo

Implementation

Replaced the regex approach with URL parsing which cleanly handles all edge cases:

  • Query strings are automatically stripped by URL.pathname
  • Fragments are automatically stripped
  • Arbitrary path depth is supported
  • .git suffix is stripped with a simple replace

Added 7 new test cases covering these scenarios.

Copy link
Collaborator

@quuu quuu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks! works well

@quuu quuu merged commit b43577b into vercel-labs:main Feb 5, 2026
2 checks passed
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.

2 participants