Skip to content

feat(skills): prototype hosted skill installation and updates - #26

Closed
tobi12345 wants to merge 3 commits into
mainfrom
lf-202-cli-poc-install-and-update-langfuse-hosted-skills
Closed

tobi12345 wants to merge 3 commits into
mainfrom
lf-202-cli-poc-install-and-update-langfuse-hosted-skills

Conversation

@tobi12345

@tobi12345 tobi12345 commented Oct 8, 2026 •

Copy link
Copy Markdown

Adds a proof of concept for installing and updating Langfuse-hosted skills through the CLI. Users can select a skill by name, label, or immutable version, or install all skills with a tag. The PR remains a draft for evaluating the CLI workflow.

Behavior

  • langfuse skills install <name[@selector]> defaults to the production label and .agents/skills. Supports --tag, --label, --version, --directory, --no-lockfile, --force, and --json.
  • Bare langfuse skills install restores exact versions and directories from langfuse-skills-lock.json.
  • langfuse skills update [name] follows saved labels while keeping explicit versions pinned. Clean recorded installations can update; local differences require --force.
  • Downloads batch up to 50 unique file hashes, validate paths, sizes, and SHA-256 checksums, and stage directory replacement with rollback. Matching local files skip content downloads. Tag installs may partially succeed if a later download fails.
  • Staging uses exclusive file writes and verifies the completed directory against the manifest before replacing an installation, detecting collisions under the filesystem's naming rules. Destination checks reject overlapping recorded installations before writing, including paths reached through symlink aliases.
  • Lockfile-enabled installations must be strict descendants of the working project directory. Absolute lockfile entries, escaping relative paths, and symlinks that lead outside the project are rejected before skill downloads or writes. Explicit external installations require --directory together with --no-lockfile.
  • Tag selection is bounded to 100 list pages and fails before installation if the server still reports another page.
  • Updates preflight every selected installation before writing. If a previous version was deleted and local content cannot be verified, the batch stops; --force allows replacement without the historical check. --no-lockfile skips lockfile reads/writes and recorded-directory overlap checks.
  • A skill named help can be installed and updated. Use --help or -h for action help.
  • Invalid or inconsistent API responses, including checksum failures, use exit code 7. Non-success HTTP statuses remain 5, and local file or lockfile failures remain 6.
  • Adds the pinned API 4.48.0 spec and command goldens, exposing seven operations under langfuse api skills. Installer modules use shared Zod validation. No release version bump.

Try it

With the usual Langfuse key and host configuration, use a disposable directory:

langfuse skills install support-triage
langfuse skills install support-triage@staging
langfuse skills install support-triage@3
langfuse skills install --tag support
langfuse skills install
langfuse skills update
langfuse skills --help
langfuse api skills --help

Replace example skill names/tags with ones available in your project.

Validation

Impacted package: @langfuse/cli.

  • bun test: 108 pass, 0 fail (local socket access required for HTTP capture tests).
  • pnpm exec tsc --noEmit: exit 0.
  • bun run build: Built native Bun CLI with 7 contracts and 720 operations.
  • Nine regressions in the existing CLI suite failed before the fixes and pass afterward: filename/directory case collisions, overlapping bulk/single-target/install operations, a symlink alias, the help skill name, response error codes, and checksum failure preservation. Fixtures use mocked API responses and temporary directories; no database seed is needed for these filesystem and HTTP-contract cases.
  • Six further regressions cover absolute/relative/symlink escapes in shared lockfiles, the project root itself, explicit external installs that ignore a malformed lockfile, and bounded tag pagination with a terminal page at the cap. The rejecting cases failed before their fixes and pass afterward.
  • Initial PoC rebased cleanly onto origin/main.
  • git diff --check flags two trailing-whitespace lines in the checksum-pinned upstream OpenAPI snapshot; retained verbatim.
  • Live Langfuse integration testing was not performed; API compatibility was checked against the pinned spec and backend schemas.

@tobi12345

Copy link
Copy Markdown
Author

@claude review

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Beyond the inline findings, I also checked whether binary (non-UTF-8) skill files would be corrupted by writeVerifiedFile's Buffer.from(content, "utf8") — the pinned OpenAPI spec defines file content as a plain string with no base64/binary encoding, so this looks like an intentional scope limit for text-based skills rather than a bug.

Extended reasoning...

The diff adds a new skills install/update CLI feature with filesystem writes (atomic directory staging/swap), a lockfile, and new HTTP calls with zod validation against a hosted API — security-relevant in the sense of untrusted file paths and checksums, though path traversal itself is guarded. Four confirmed findings (case-insensitive path collision, nested-directory --force crash, misleading exit code on malformed JSON, and a skill literally named "help" being unreachable) already exist as inline comments, and the hunt's exit reason was a budget bound rather than running dry, so approval is not warranted here.

Findings marked 🟡 are optional suggestions and need no follow-up push.

Comment thread src/skills.ts Outdated
Comment thread src/skills.ts
Comment thread src/skills/api.ts Outdated
Comment thread src/cli.ts
@tobi12345

Copy link
Copy Markdown
Author

@claude review

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I reviewed this PR; the inline findings above cover the issues I found. Beyond those, I also checked the rollback path in replaceDirectory (src/skills.ts:211-225): if the restore rename after a failed install also fails, the original error still propagates rather than being silently swallowed, so I ruled that out as a separate bug.

Extended reasoning...

This run surfaced four new CONFIRMED findings (lock-file path traversal in targets.ts, an update loop that can abort entirely on one pruned skill version, an overlap-check bypass via --no-lockfile enabling later silent deletion, and an unbounded pagination loop in the tag-fetch path) that will be posted as inline comments; these touch filesystem writes outside the project tree and availability/DoS-adjacent behavior, which is security-sensitive enough to warrant human review. A prior review round from this same system already left four inline threads that were resolved only by the PR author (not independent verification), so those remain effectively open per the review policy. Given the volume and nature of confirmed findings, approval is not appropriate; I additionally verified the one ruled-out candidate (rollback-failure data loss in replaceDirectory) by reading the code and confirmed the original error still surfaces rather than being swallowed.

Findings marked 🟡 are optional suggestions and need no follow-up push.

Comment thread src/skills/targets.ts
Comment thread src/skills.ts
Comment thread src/skills.ts Outdated
Comment thread src/skills/api.ts Outdated
@tobi12345

Copy link
Copy Markdown
Author

@claude review

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nothing blocking. The comments below are optional suggestions. There is no need to push a fix for them before merging.

Beyond the newly flagged finding, I re-verified the concerns raised in my two earlier reviews against this push. The literal skill name "help" being swallowed by the help-flag check, the nested-directory overlap crash mid-update, lockfile paths escaping the project (absolute/relative/symlink), and the unbounded --tag pagination loop are now fixed in commits 6f36485 and a0e1113.

Extended reasoning...

This push hardens the new skills install/update feature (lockfile confinement via realpath checks, overlap rejection, EXIT_RESPONSE vs EXIT_HTTP separation, bounded tag-list pagination). Reading the diff, I confirmed four previously-raised concerns from my earlier reviews are now fixed in commits 6f36485 and a0e1113. A new finding was confirmed this run, and one earlier concern remains unaddressed in the code despite its thread being marked resolved by the author, so a human should still look before merge.

Comment thread src/skills.ts
@tobi12345 tobi12345 closed this Oct 9, 2026
@tobi12345
tobi12345 deleted the lf-202-cli-poc-install-and-update-langfuse-hosted-skills branch October 9, 2026 09:29
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