Skip to content

feat(skills): run a skill from a URL, pin it with --skill-sha256, and share packs - #105

Open
AdithKB wants to merge 2 commits into
secfoo-com:mainfrom
AdithKB:feat/93-skill-packs-and-skill-file-urls
Open

AdithKB wants to merge 2 commits into
secfoo-com:mainfrom
AdithKB:feat/93-skill-packs-and-skill-file-urls

Conversation

@AdithKB

@AdithKB AdithKB commented Nov 13, 2026

Copy link
Copy Markdown
Contributor

Summary

#79's --skill-file covers one machine. This closes the two gaps #93 calls out — a teammate sending a link, and a team keeping its skills pinned in a git repo:

  • --skill-file over HTTPS: secfoo run --skill-file https://.../review.md fetches over HTTPS only (no http://, and no redirect to one), capped at 256 KB, and validated exactly like a local skill (Custom skills: add your own skills without changing code #79's rules). --skill-sha256 <hex> pins the content; a mismatch is an error before the file is even parsed, let alone run.
  • Skill packs: secfoo skills install <git-url> [--ref v3] [--name NAME] clones a repo of *.md skills (optionally under a skills/ subfolder) into ~/.secfoo/skills/packs/<name> and pins it in ~/.secfoo/skills/packs.lock. secfoo skills update [NAME], secfoo skills remove NAME, and secfoo skills install --from-lock (reproduces every pinned pack — for CI) round it out. secfoo skills list now shows each skill's pack and resolved commit. A pack skill that clashes with another pack or a built-in is skipped with a warning naming both, same as any other custom skill.
  • Trust prompt: the first time a run would use a skill from anywhere other than a built-in or a file under ~/.secfoo/skills/*.md — a configured path, a one-off file or URL, or a pack — secfoo run prints its id, name, source and sha256 and asks for confirmation, since that text becomes agent instructions. --yes skips it, and it's always skipped on a non-interactive run (CI, --json).
  • Traceability: runs.skill_source now carries the actual URL or pack:<name>@<commit> instead of collapsing every non-builtin source to "user". The run detail page shows it (a URL renders as a link; a pack source is shown as-is) and flags definition changed when a run's sha256 differs from the previous run of the same skill id.
  • Docs: docs/SKILLS.md gets a "Sharing skills with your team" section (plain checkout vs. a pinned pack, packs.lock, CI) and a "Trust model" section.

Scope note

The dashboard change is deliberately the minimal, testable slice from the issue's point 4 (the run detail page). The activities page already groups runs purely by skill_id with no source-based filtering, so there was nothing there to fix for "group runs of the same skill id across sources" — that part needs no code change.

Test plan

  • pytest tests passes (1295 passed; the one pre-existing failure, test_sensor_dying_mid_run_drops_events_without_blocking, is a flaky socket-timing test that fails identically on main without this branch)
  • ruff check . — no new findings introduced by this branch (verified by diffing findings against main for every touched file)
  • New coverage: --skill-file with an HTTPS URL (fetch, sha256 recorded); rejection of http://; the no-redirect-to-http handler; the 256 KB cap; a sha256 match and mismatch (mismatch never reaches the frontmatter parser); --skill-sha256 without a URL errors; the CLI wiring for both
  • New coverage: install from a local git repo at a tag; update moving to a new commit; update with no name updating every pack; remove; an id clash between a pack and a built-in being skipped; --from-lock reproducing the pinned commit even after a newer one lands; a pack with no skills/ subfolder; the secfoo skills install/update/remove/list CLI commands
  • New coverage: the trust prompt appearing once per skill id per invocation, --yes bypassing it, and a decline aborting the run
  • New coverage: the run detail page rendering a pack source, a URL source as a link, and the "definition changed" marker

Fixes #93

🤖 Generated with Claude Code

https://claude.ai/code/session_012MkDc2pyUgcPHyj5joTrip

… share packs (secfoo-com#93)

secfoo-com#79's --skill-file only covered one machine. This adds the two ways
skills actually get shared: a teammate's link and a team's pinned pack.

- --skill-file accepts https:// URLs (no http://, no redirect to one,
  256 KB cap); --skill-sha256 pins the content, checked before the
  file is even parsed.
- secfoo skills install/update/remove/list manage shared skill packs
  (a git repo of *.md skills) under ~/.secfoo/skills/packs/<name>,
  pinned in packs.lock; --from-lock reproduces the set in CI.
- The first run of a skill from any source other than a built-in or
  ~/.secfoo/skills/*.md prints its id/source/sha256 and asks for
  confirmation, since that text becomes agent instructions. --yes
  and non-interactive runs skip it.
- runs.skill_source now carries the URL or pack:<name>@<commit>
  instead of collapsing to "user"; the run page shows it and flags a
  "definition changed" run when the sha256 differs from the previous
  run of that skill id.

Fixes secfoo-com#93
@AdithKB
AdithKB requested a review from vsn411 as a code owner November 13, 2026 14:07
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.

Run your own skill from anywhere: --skill-file with URLs, and shared skill packs

2 participants