Skip to content

feat: add @tsops/skill — Claude Skill for tsops (with npm installer)#54

Open
Pom4H wants to merge 1 commit into
mainfrom
feat/claude-skill
Open

feat: add @tsops/skill — Claude Skill for tsops (with npm installer)#54
Pom4H wants to merge 1 commit into
mainfrom
feat/claude-skill

Conversation

@Pom4H
Copy link
Copy Markdown
Owner

@Pom4H Pom4H commented May 1, 2026

Summary

Adds @tsops/skill — a Claude Skill that teaches Claude how to operate tsops correctly. Ships the canonical Skill content at skills/tsops/ and a thin npm installer package.

After install, Claude Code, the Agent SDK, and any tool implementing the Agent Skills standard load the Skill automatically when relevant.

Why a Skill, not just docs

The docs explain what tsops is. The Skill tells an agent how to operate it without violating the load-bearing rules:

  • Never put internal service URLs in env vars — use config.url('api', 'service').
  • Always run tsops plan before tsops deploy.
  • After editing tsops.config.ts, run tsc --noEmit so renames propagate to every caller.
  • Never --no-verify past secret validation.

Without the Skill, an LLM agent reaches for BACKEND_URL=http://api:3000 because that pattern is everywhere else on the public internet. With the Skill, it reaches for config.url('api', 'service').

This compounds with the value tsops already provides: a typed operational model is one an agent can safely modify provided it knows the conventions. The Skill is how those conventions get transferred.

Distribution model

  • Canonical source on GitHub at skills/tsops/ — edited via PR review like any other code
  • npm installer @tsops/skill — one-shot npx @tsops/skill install copies the Skill into ~/.claude/skills/tsops (user scope) or ./.claude/skills/tsops (project scope, commit to repo)
  • Docs page at docs/guide/skill.md

A user installs with one command:

npx @tsops/skill install              # user scope
npx @tsops/skill install --project    # commit to repo

The installer is idempotent, supports --force overwrite, uninstall, and where subcommands.

Skill structure

skills/tsops/
├── SKILL.md                 entry point — frontmatter + hard rules + canonical workflow
├── reference/
│   ├── commands.md          CLI commands and flags
│   ├── runtime-helpers.md   config.url / config.env / config.dns / TSOPS_NAMESPACE
│   ├── secrets.md           secret validation, placeholder detection, cluster fallback
│   └── preview-overlays.md  overlay namespace lifecycle
└── examples/
    ├── add-app.md           recipe: add a new app
    ├── rename-app.md        recipe: rename safely (compiler-driven)
    └── add-secret.md        recipe: add a secret + consume it

The Skill is intentionally small. The entry-point SKILL.md covers the mental model and the hard rules — Claude reads this on session start to decide if the Skill is relevant. References under reference/ and examples/ load on demand, only when the current task touches them.

Package structure

packages/skill/
├── package.json           bin: { tsops-skill: ./bin/install.mjs }
├── bin/install.mjs        install/uninstall/where subcommands
├── scripts/sync-skill.mjs build step — syncs skills/tsops/ → packages/skill/skill/
└── skill/                 generated; the bundled skill content (in tarball)

The duplication between skills/tsops/ (canonical) and packages/skill/skill/ (bundled) exists because npm tarballs do not preserve symlinks reliably across all package managers. The build step keeps them in sync.

Verified

  • npx @tsops/skill install writes correct content under ~/.claude/skills/tsops/
  • Claude Code picked up the Skill in the next session and surfaced it in the available-skills list
  • Skill description triggers on tsops.config.ts files, tsops CLI mentions, and operational verbs (deploy, plan, preview)

Scope

Strictly additive — no existing files are modified, zero conflict risk with PR #51 (docs refresh) or #52 (RFC + Vercel skeleton). Mergeable in any order.

Follow-ups (separate small PRs after merge)

  • Surface /guide/skill in the docs sidebar (one line in docs/.vitepress/config.ts)
  • Link "Use with Claude" from the main README
  • Submit to anthropics/skills community registry once we have early-adopter signal

Test plan

  • npx @tsops/skill install --help — usage prints
  • npx @tsops/skill install --user — files appear under ~/.claude/skills/tsops/
  • npx @tsops/skill install --project — files appear under ./.claude/skills/tsops/
  • npx @tsops/skill where — prints target path + (in)stalled state
  • npx @tsops/skill uninstall — removes target dir cleanly
  • In a Claude Code session with the Skill installed, asking "add a worker app to tsops" produces output that follows examples/add-app.md (uses config.url, runs tsops plan before deploy)

Ships the canonical Skill content at skills/tsops/ and a thin npm
package (@tsops/skill) that installs it into ~/.claude/skills/tsops or
./.claude/skills/tsops. After install, Claude Code, the Agent SDK, and
any other tool implementing the Agent Skills standard load the Skill
automatically when relevant.

Why a Skill, not just docs: the docs explain what tsops is. The Skill
tells an agent how to operate it without violating the load-bearing
rules — no internal URLs in env vars, always run `tsops plan` before
deploy, always `tsc --noEmit` after a rename, never `--no-verify` past
secret validation. Without the Skill, an LLM agent reaches for
BACKEND_URL=http://api:3000 because that pattern is everywhere else
on the public internet. With it, it reaches for config.url('api', 'service').

Distribution model (mirrors workflows-sdk.dev structure):
- canonical source on GitHub at skills/tsops/
- npm package @tsops/skill that installs the Skill via `npx @tsops/skill install`
- docs page at docs/guide/skill.md

Skill structure:
  skills/tsops/
  ├── SKILL.md                       entry point — frontmatter + hard rules
  ├── reference/
  │   ├── commands.md                CLI flags
  │   ├── runtime-helpers.md         config.url / config.env / config.dns
  │   ├── secrets.md                 secret validation, cluster fallback
  │   └── preview-overlays.md        overlay namespace lifecycle
  └── examples/
      ├── add-app.md                 recipe
      ├── rename-app.md              recipe — compiler-driven rename
      └── add-secret.md              recipe

Package structure (packages/skill/):
- bin/install.mjs — `tsops-skill install [--user|--project] [--force]`,
                    plus uninstall and where subcommands
- scripts/sync-skill.mjs — build step that copies skills/tsops/ into
                          packages/skill/skill/ for the npm tarball
                          (npm doesn't preserve symlinks reliably)
- README.md — install + verify + uninstall instructions

This PR is strictly additive — no existing files are modified, so no
conflict with the in-flight docs refresh in PR #51.

Follow-ups (separate small PRs after both merge):
- surface /guide/skill in the docs sidebar
- add a "Use with Claude" link from the main README
- submit to anthropics/skills community registry if/when accepted
@Pom4H Pom4H requested a review from arhebs May 4, 2026 17:42
Copy link
Copy Markdown
Collaborator

@arhebs arhebs left a comment

Choose a reason for hiding this comment

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

Thanks, direction looks good. I verified the important package paths:

  • tsops-skill install works for user install.
  • tsops-skill install --project works.
  • pnpm --filter @tsops/skill pack includes the expected skill files.
  • Canonical skills/tsops and packaged packages/skill/skill match.

Two small blockers before I’d merge:

  1. skills/tsops/SKILL.md and packages/skill/skill/SKILL.md reference examples/hybrid-vercel-k8s.md, but that file is not present in either skill copy. Please add the example or remove the reference.

  2. packages/skill/package.json has "lint": "pnpm -w exec eslint .", but the repo uses Biome and ESLint is not installed. pnpm --filter @tsops/skill lint currently fails with Command "eslint" not found. Please switch this to Biome or remove the package-local lint script.

CI is also red on root pnpm lint; from the logs it looks like repo-level Biome config/schema drift and existing diagnostics, not this PR specifically, but it should be green before merge.

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.

3 participants