npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@techfides/tf-skills-manager

v0.2.1

Published

Readme

tf-skills

The CLI for the TechFides AI skills library (TechFides/tf-skills-manager-library). It fetches and installs skills, checks their status, and opens pull requests to contribute new or changed ones — all through GitHub's API, with no git clone, no git pull, and no local checkout of the library.

What it can do

Two audiences, one tool: people who use skills, and people who write them. Neither ever clones the repository.

| You want to | Command | |---|---| | See every skill in the library, with descriptions and authors | list | | Install some, picked from a menu | install | | Install specific ones, or a whole bundle | install <name...>, install --bundle <name> | | Install everything | install --all | | Find out what is stale, locally edited, or untracked | status | | Bring installed skills back in line with the library | update | | Start a new skill from a template, offline | new <name> --section <section> | | Open a pull request adding or changing a skill | contribute [name] | | Read the usage text | help, --help, -h |

How it works

  • Nothing is cloned. Every read is a GitHub Git Data API call. The library's main is resolved to a single commit once per run and pinned for the rest of it, so one invocation can never mix content from two states of the library.
  • Each skill is copied into --target. The default is ./.claude/skills, under the folder you ran the command from, so a skill installed while working on a project belongs to that project and can be committed with it. install, update and contribute offer the machine-wide ~/.claude/skills as the alternative. A skill lands at <target>/<skill-name>/, without its section prefix, which is the layout Claude Code expects.
  • The install record is per user, not per project. ~/.claude/tf-skills/state.json stays in your home directory even for a project install, so nobody commits their install record. The trade-off is that skills you acquire by cloning a project read as unmanaged until you install them yourself.
  • A local record makes drift visible. ~/.claude/tf-skills/state.json holds a SHA-256 per installed file, keyed by target directory. That is how status tells current from outdated from locally modified, and how update knows to refuse rather than quietly overwrite your edits.
  • Bundles and dependencies resolve themselves. Installing a skill also installs whatever bundles.json records it as depending on, cycle-safe.
  • Authoring is clone-free too. new scaffolds on disk with no token and no network; contribute turns local files into a branch, commit, and pull request through the API. Anyone can contribute a new skill or change an existing one; merging the pull request is what makes it live, and there is no status field and no owner list anywhere in the library.

Content is read from main only. A skill that exists on a branch is invisible to this CLI until it merges, which is deliberate: everyone running install gets the same library. Use --repo owner/name to read from somewhere else entirely.

Quick start

No install needed — run it with npx, which always resolves the latest published version:

npx @techfides/tf-skills-manager@latest

With no arguments at all, that is install's interactive picker (requires a TTY). To install by name, the install keyword is required — a bare npx @techfides/tf-skills-manager@latest <name> is not the same as install <name>; the leading token is taken as the command word, and an unrecognized one is a usage error (see "Exit codes" below). Without a TTY, install needs install <names...>, --bundle <name>, or --all instead.

If you install the package globally or as a dev dependency, the same commands are available as tf-skills:

npm install -g @techfides/tf-skills-manager
tf-skills list

Every example below uses tf-skills; substitute npx @techfides/tf-skills-manager@latest for it if you are not installing globally.

Requirements

  • Node.js >= 24. Older versions warn (EBADENGINE) and are untested.

  • A GitHub token with read access to TechFides/tf-skills-manager-library (write access too, for contribute). Resolved in this order:

    1. GITHUB_TOKEN environment variable.
    2. GH_TOKEN environment variable.
    3. gh auth token, if the GitHub CLI is installed and logged in.

    If none of these resolve, every command except new fails naming the fix (gh auth login, or set GITHUB_TOKEN). new needs no token at all — it never makes a network call.

Commands

install (default)

tf-skills install [names...] [--all] [--bundle <name>]

install is the default command, but only for a bare invocation with no arguments at all (or one starting with a flag) — tf-skills alone, or tf-skills --all, dispatches to install. A leading skill name does not: tf-skills dev/sonar-fix-pr is parsed as the command word dev/sonar-fix-pr, which is unknown, not as install dev/sonar-fix-pr. Whenever one or more names are passed, write the install keyword explicitly.

Fetches and places skills into the target directory. With no --target, and a terminal to ask on, it first asks whether you mean this project's ./.claude/skills (the default, so Enter takes it) or the machine-wide ~/.claude/skills. Accepts a bare skill name (sonar-fix-pr) or a <section>/<name> path (dev/sonar-fix-pr); both forms resolve to the same skill. Any dependency a requested skill declares is installed automatically alongside it.

  • With one or more names and/or --bundle <name>, installs exactly that selection (plus dependencies). --all silently wins over both if given alongside them.
  • With --all, installs every skill in the library.
  • With no names, no --bundle, and no --all, and a TTY, prompts interactively with a multiselect.
  • With none of the above and no TTY, fails naming --all/--bundle/a name as the fix — it never guesses in a script or agent context.

A skill already installed and unchanged is reported as already current and left untouched. A directory that already exists at the destination and either isn't tracked by this CLI, or has local edits, is refused by name; re-run with --force to overwrite it, or use contribute first to keep the changes. Unlike update, install stops at the first such conflict in a multi-skill run rather than accumulating failures across all of them.

Exit code: 0 on success (including "nothing to do"); 1 on a hard failure (unknown skill/bundle name, an unresolved conflict without --force).

update

tf-skills update [names...] [--all]

Refreshes skills already installed under the target directory to the library's current main. update never installs something new — a name that isn't already installed is reported, not installed.

  • No names and no --all: refreshes everything currently installed. This is also what bare update does — it never prompts.
  • update <names...>: refreshes only those (accepts the same bare-name or <section>/<name> forms as install). --all silently wins over any names given alongside it, same as install.

A skill with local edits is refused (name and reason reported) unless --force is given; other requested names keep processing rather than aborting the whole run. A name no longer on disk, a locally-created (new) skill, or a skill removed from the library upstream, is reported and skipped without ever refetching.

Exit code: 1 if anything was refused or not found, 0 otherwise.

list

tf-skills list [--json]

Prints every skill the library currently offers, grouped under its section in the canonical role order, with names aligned into a column and authors in a column of their own on the right. Bundles, if the library defines any, come first:

15 skills in TechFides/tf-skills-manager-library

Bundles (1)
  docs        Documentation authoring set
              docs-base, docs-commands, docs-tests, ff-analysis

dev (3)
  review-ticket-branch    Review the branch implementing one defined ticket…        Dalibor Šimon
  sonar-fix-pr            List and fix all open SonarQube quality gate issu…         Filip Koukal
  mam-adhd                Piš výstup tak, aby podle něj mozek s ADHD dokáz…        Tomáš Pokorný

analyza (4)
  docs-base               Documentation foundation for the entire ana-docs…           Dávid Šilon

Descriptions are shortened to one line and the layout follows the terminal width, because a description is written for an agent deciding whether a skill applies and the longest in the library runs past a thousand characters. The author is never shortened: it has its own column precisely so that clipping a description cannot take it with it. A skill that names no author leaves the cell empty.

Pass --json for a machine-readable { "skills": [{ section, name, description, author }], "bundles": [{ name, description, skills }] } with every description in full — that output is unaffected by the layout above. A skill with no author has no author key at all, rather than a null one.

status

tf-skills status [--json]

Reports where every skill stands relative to both the library and the target directory on disk: current, outdated, modified, unmanaged, not-installed, local-only (created with new, never contributed), or removed-from-library. This is a report only — it never writes anything, and always exits 0 on a successful run regardless of what it finds.

tf-skills help explains each of those seven states and what to do about it.

Pass --json for { "<name>": { "state": ..., "section": ... } } instead of the plain-text table.

new

tf-skills new <name> --section <qa|pm|dev|analyza|shared>

Scaffolds <name>/SKILL.md locally under the target directory, with name, description and metadata.author frontmatter and a placeholder body, and records it as not yet part of the library. Fill in the real description and instructions, add any supporting files, then run contribute when it's ready to become a pull request.

The author is --author "Your Name" if you pass it, otherwise your git user.name. If neither is available the block is left out entirely rather than filled with a placeholder — the library's validator warns about a skill that names no author, which is a better outcome than a fake name showing up in list.

Needs no GitHub token — it is entirely local (reading git config user.name is the one subprocess it runs, and it carries on without it). Without --section and with a TTY it prompts for one; without a TTY it fails naming --section.

contribute

tf-skills contribute [name] [--section <section>]

Opens (or, if one is already open, reports the URL of) a pull request from a local skill's current content — a new-scaffolded skill, or a locally-edited one — via GitHub's API: blob, tree, commit, branch, PR. No local git branch, no git push.

  • With a name, contributes exactly that skill.
  • With no name and a TTY, offers a multiselect of local candidates (skills that are local-only or otherwise unmanaged by the library).
  • With no name and no TTY, fails asking for one.

The pull request contains the skill's local content in full: a file present locally is added or updated, and a file the library has that no longer exists locally is deleted, so an edit that removes or renames a supporting file contributes correctly.

A skill that names no metadata.author still contributes — the check is one stderr warning before the pull request opens, not a refusal. The library's own CI warns about it too, but only once the PR is already up.

The section is resolved from --section, else a <section>/ prefix typed on the name itself (contribute dev/foo), else the section recorded for that skill locally (set by new, or by a prior install/update), else an interactive prompt; without a TTY and without any of those, it fails naming --section. contribute itself never writes to that local record — only new, install, and update do, which is why a successful run prints how to re-sync once the pull request is merged. Validation runs before anything is written — a failure names every issue and nothing is created. Those checks mirror the errors the tf-skills-manager-library validator enforces in CI, though a few messages are the CLI's own: an unquoted keyword-shaped name or description (name: no) is reported here as the quoting problem it is, where CI reports only the missing or mismatched value it resolves to.

Exit code: 1 if any requested skill failed to contribute, 0 otherwise.

help

tf-skills help
tf-skills --help
tf-skills -h

Prints the usage summary: every command with its arguments, every flag with the commands that read it, how the token is resolved, and the exit codes. Needs no token and makes no network call.

--help and -h are answered wherever they appear, so tf-skills install --help prints this text rather than installing anything. Everything else on the command line is ignored in that case — including flags that would otherwise be rejected, so a half-remembered invocation still gets you the help instead of a usage error.

Exit code: 0.

Global flags

| Flag | Read by | Meaning | |---|---|---| | --target <dir> | all (list accepts but ignores it) | Skills directory to read/write. Default ./.claude/skills, relative to where the command ran. Passing it skips the project-or-global question. ~ and ~/... are expanded. | | --json | list, status | Machine-readable output instead of a plain-text table. | | --force | install, update | Overwrite an unmanaged or locally-modified directory instead of refusing. | | --repo <owner/name> | commands that talk to GitHub | Fetch from a different repository instead of TechFides/tf-skills-manager-library. Must be owner/name. | | --all | install, update | Every skill in the library (install) or every skill currently installed (update). | | --bundle <name> | install | Add a named bundle from bundles.json to the install selection. | | --section <section> | new, contribute | One of qa, pm, dev, analyza, shared. | | --author <name> | new | Who to record as the skill's author. Defaults to git config user.name. Must contain no double quote or backslash. | | --help, -h | any | Print the usage text and exit 0, ignoring the rest of the command line. |

Every flag above is accepted on every command — the parser has no per-command restriction — but only the commands listed in "Read by" do anything with it. An unrecognized --flag is a usage error (exit 2), not silently ignored. --help/-h are the one exception to both rules: they are resolved before any other parsing, so they work on every command and are never rejected.

Exit codes

| Code | Meaning | |---|---| | 0 | Success, including "nothing to do" and (for status) a clean report of drift. | | 1 | Operational failure: a refusal, a validation failure, an unresolved conflict, missing auth. | | 2 | Usage error: unknown command or flag, wrong number of arguments, malformed flag value. |

An expected failure prints one message and exits 1 or 2. An unexpected one — a bug — prints a single Unexpected error: line; set TF_SKILLS_DEBUG=1 to get the stack trace with it.

Notes for agent / scripted use

Every command runs non-interactively when given enough on the command line — none of them require a TTY as long as the relevant flag or name is supplied (see each command's section above for exactly what that is). Use --json on list/status to consume their output programmatically instead of parsing the plain-text table.