Skip to content

feat(sources): support well-known HTTP skill sources#77

Merged
gricha merged 9 commits intomainfrom
feat/wellknown-skill-sources
Mar 20, 2026
Merged

feat(sources): support well-known HTTP skill sources#77
gricha merged 9 commits intomainfrom
feat/wellknown-skill-sources

Conversation

@gricha
Copy link
Member

@gricha gricha commented Mar 20, 2026

Summary

Adds support for bare HTTPS URLs as skill sources, resolving via the .well-known/skills/ convention (Issue #74).

  • dotagents add https://cli.sentry.dev now works — fetches {url}/.well-known/skills/index.json, downloads skill files into a TTL-based local cache
  • Bare HTTPS URLs not matching GitHub/GitLab are treated as well-known candidates; failure suggests the git: prefix
  • Trust validation uses git_domains with prefix-matching (e.g. trust add cli.sentry.dev)
  • Same offline behavior as git: stale cache used on fetch failure
  • Full add/install/resolve/wildcard/lockfile support

Changes

File What
src/sources/wellknown.ts New HTTP fetcher and cache (fetchWellKnownIndex, ensureWellKnownCached)
src/skills/resolver.ts parseSource returns "well-known" for bare HTTPS; resolveSkill/resolveWildcardSkills handle it; normalizeSource lowercases hostname
src/config/schema.ts Schema accepts bare http:///https:// URLs
src/trust/validator.ts "well-known" shares domain-matching logic with "git"
src/lockfile/schema.ts lockedWellKnownSkillSchema (source + resolved_url)
src/cli/commands/add.ts Well-known branch: fetch/cache → discover → picker (same UX as git)
src/cli/commands/install.ts Lock entry creation for well-known sources
specs/SPEC.md, docs/public/llms.txt Document https://<domain> source type

Closes #74

Test plan

  • pnpm check passes (lint + typecheck + 585 tests)
  • New tests in wellknown.test.ts: index fetch (valid/invalid/404/network error), caching (fresh/stale/offline)
  • New tests in resolver.test.ts: parseSource with well-known URLs, normalizeSource, sourcesMatch
  • New tests in validator.test.ts: well-known sources against git_domains
  • Updated test in schema.test.ts: bare HTTPS URLs now accepted
  • Manual smoke test: npx @sentry/dotagents add https://cli.sentry.dev (requires network + live endpoint)

Agent transcript: https://claudescope.sentry.dev/share/IWLZm9eChduh84Sfd0hyukgm_3Y8F0fp82DqNZzNZ6Q

Add support for bare HTTPS URLs (e.g. `https://cli.sentry.dev`) as skill
sources. These are resolved via the `.well-known/skills/` convention: dotagents
fetches `{url}/.well-known/skills/index.json` to discover available skills,
then downloads each skill's files into a TTL-based cache.

Bare HTTPS URLs that don't match GitHub/GitLab patterns are treated as
well-known source candidates. If the endpoint doesn't exist, the error
message suggests using the `git:` prefix.

Closes #74

Agent transcript: https://claudescope.sentry.dev/share/zG7Tq2nDrDatJjftMjoLN2b_zvtpADH05RTyp_Zka3c
@vercel
Copy link

vercel bot commented Mar 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
dotagents Ready Ready Preview, Comment Mar 20, 2026 6:54pm

Request Review


// Bare HTTP(S) URL not matching GitHub/GitLab — candidate for well-known
if (/^https?:\/\//i.test(source)) {
return { type: "well-known", url: source.replace(/\/+$/, "") };

Check failure

Code scanning / CodeQL

Polynomial regular expression used on uncontrolled data High

This regular expression that depends on library input may run slow on strings with many repetitions of '/'.
This regular expression that depends on library input may run slow on strings with many repetitions of '/'.
This regular expression that depends on library input may run slow on strings with many repetitions of '/'.
Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed — replaced /\/+$/ regex with an iterative stripTrailingSlashes() helper that uses a simple while loop. No regex involved.

— Claude Code

export async function fetchWellKnownIndex(
baseUrl: string,
): Promise<WellKnownIndex | null> {
const indexUrl = `${baseUrl.replace(/\/+$/, "")}/.well-known/skills/index.json`;

Check failure

Code scanning / CodeQL

Polynomial regular expression used on uncontrolled data High

This regular expression that depends on library input may run slow on strings with many repetitions of '/'.
Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed — same stripTrailingSlashes() helper approach, no regex.

— Claude Code

return { cacheDir };
}

const baseUrl = opts.url.replace(/\/+$/, "");

Check failure

Code scanning / CodeQL

Polynomial regular expression used on uncontrolled data High

This regular expression that depends on library input may run slow on strings with many repetitions of '/'.
Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed — same stripTrailingSlashes() helper approach, no regex.

— Claude Code

Replace /\/+$/ regex (flagged by CodeQL as polynomial on uncontrolled
data) with a simple while-loop helper in wellknown.ts and resolver.ts,
and an inline slice in add.ts.
- Validate skill.name and file names from remote index.json against
  safe name pattern to prevent path traversal attacks
- Restrict well-known sources to HTTPS only (reject http://) to
  prevent MITM attacks on skill content
- Use URL.host instead of URL.hostname to preserve port numbers in
  normalization and cache keys
- Remove unused WellKnownError class
- Move stripTrailingSlashes to shared utils/fs.ts (deduplicate)
parseSource now only classifies https:// URLs as well-known (not http://).
The add command explicitly rejects bare http:// URLs with a clear error
message, preventing MITM attacks via plain HTTP skill fetching.
extractDomain and extractDomainPath now use URL.host instead of
URL.hostname, consistent with the resolver changes. This ensures
git_domains entries with ports (e.g. "localhost:3000") match correctly.
- File paths in well-known index can now contain subdirectories
  (e.g. "prompts/base.md") while still preventing path traversal
- Schema rejects bare "https://" without a hostname
- Create parent directories for nested file paths during download
Move the http:// rejection check before parseSource and check against
the raw URL with GitHub/GitLab regex exclusions, so http://cli.sentry.dev
gets the "Insecure source" error instead of a confusing git clone failure.
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

`Specify skill names as arguments, use --skill to specify which ones, or --all for all skills.`,
);
}
}
Copy link

Choose a reason for hiding this comment

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

Well-known and git add branches heavily duplicated

Low Severity

The well-known branch (lines 200–343) is nearly a verbatim copy of the git branch (lines 344–487). The interactive selection flow — clack.select for all-vs-pick, clack.multiselect, multi-name override handling, duplicate-skip logic, and addWildcard — is identical across both branches except for the cache source (cached.cacheDir vs cached.repoDir). A shared helper accepting the cache directory would eliminate ~140 lines of duplication and reduce the risk of fixing a bug in one branch but not the other.

Fix in Cursor Fix in Web

@gricha gricha merged commit 0fa5b70 into main Mar 20, 2026
18 checks passed
@gricha gricha deleted the feat/wellknown-skill-sources branch March 20, 2026 19:05
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.

Support Sentry CLI agent skill installation.

1 participant