agentleFS
AWSKnown publisherawslabs/llm-evaluation-system/.claude/skills/ship-it/SKILL.md

ship-it

Skill26 starsChanged 5 months agoApache-2.0View on GitHub

Ship work in the llm-evaluation-system repo end-to-end — commit with conventional-commit messages, push to a feature branch (never directly to main), open a PR with the proper title format, and after merge either run `make release` to publish to PyPI or just clean up branches. Use this skill whenever the user says ship/commit/push/open a PR/release/publish, or after code changes are done and ready to go out. Don't invent your own git workflow — invoke this skill so the repo conventions (conventional commits, manual release, setuptools-scm tag flow, branch cleanup) are applied consistently.

  • Commits and pushes

46 other projects use a version of this, 1 of them edited.

Adopted by

Most recently taken up by

Used with

Projects with it also use modern-go, loop-it and 10 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • jidechaoSkill

    modern-go

    Modernize Go code by applying version-appropriate idioms and APIs (gofix-style transformations). Scans go.mod for the Go version, then transforms Go source files to use modern patterns—from Go 1.0 through 1.26+. Use when the user says "现代化","现代Go语言", "地道的", "idiomatic", "modernize", "modern-go", "update Go code", "gofix", or wants to upgrade Go idioms.

    Also in 3 projects that use this

  • jidechaoSkill

    loop-it

    Automated issue loop with checkpoint/resume: fetch open GitHub issues → dependency-aware topological sort → implement each issue end-to-end → review with /review-it → document with /note-it → ship with /ship-it → repeat. Persists state to .loop-state.json for crash recovery. Triggers on: loop-it, loop issues, auto implement, 批量实现, 循环实现, 实现所有issue, 恢复循环, resume loop.

    Also in 3 projects that use this

  • SentrySkill

    create-pr

    Create pull requests following Sentry conventions. Use when opening PRs, writing PR descriptions, or preparing changes for review. Follows Sentry's code review guidelines.

    Also in 5 projects that use this

  • GitHubSkill

    refactor

    Surgical code refactoring to improve maintainability without changing behavior. Covers extracting functions, renaming variables, breaking down god functions, improving type safety, eliminating code smells, and applying design patterns. Less drastic than repo-rebuilder; use for gradual improvements.

    Also in 4 projects that use this

  • GoogleSkill

    to-issues

    Break a plan, spec, or PRD into independently-grabbable issues on the project issue tracker using tracer-bullet vertical slices.

    Also in 3 projects that use this

  • Hugging FaceSkill

    simplify

    Refactor code after tests pass. The "Refactor" phase of Red-Green-Refactor.

    Also in 3 projects that use this

  • +2 more from jidechao

The file

We split this skill into the rules it gives an agent

9 rules. 0 are common, 6 are distinctive, and 3 are very specific to this project.

  • 0

    Common

    Most of the 42 edited versions we read keep these.

  • 6

    Distinctive

    This author's own choices. Worth a look.

  • 3

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  • could be automatic: a setting could enforce it
  1. Distinctive:

    Read the whole skill before acting if it's your first invocation in a session.

    line 13
  2. Very specific:

    Never push directly to main: Every change goes through a PR.

    line 22
  3. Very specific:

    Releases are deliberate human actions: Use make release / make release-minor / make release-major from a clean main.

    line 28
  4. Distinctive:

    If you're invoked from main with uncommitted changes, stop and ask the user before doing anything.

    line 41
  5. Distinctive:

    Verify the working tree state: Run git status --short. If there are untracked or modified files that aren't part of THIS change (e.g.

    line 48
  6. Distinctive:

    Use a HEREDOC for multi-line commit messages so formatting is preserved:

    line 74
  7. Distinctive:

    Use a HEREDOC for the body so formatting is preserved:

    line 98
  8. Very specific:

    When the user reports the PR is merged (or you verify via gh pr view):

    line 125
  9. Distinctive:

    If it does, surface what's there and ask the user before forcing.

    line 142

“Common” is measured: kept by at least 6 in 10 of the 42 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Ship It

This skill ships changes in the llm-evaluation-system repo from "I have local changes" through to "merged + (optionally) on PyPI." It exists because this repo has specific conventions that are easy to get wrong individually and straightforward when followed as a unit.

Read the whole skill before acting if it's your first invocation in a session. After that, the quick reference at the bottom is usually enough.

Conventions this repo follows

  • Conventional Commits for every commit message AND every PR title. Valid prefixes: feat, fix, docs, chore, refactor, test, build, ci, perf, style, revert. Use feat(scope): when a scope adds clarity (e.g. feat(mcp): ..., fix(release): ...).
  • Never push directly to main. Every change goes through a PR. Direct pushes are blocked by the auto-mode classifier anyway, but the deeper reason is reviewability and not bypassing CI checks on publish.yml paths.
  • Never force-push. Rewriting public history breaks others' clones and is essentially never the right answer.
  • Releases are deliberate human actions. Use make release / make release-minor / make release-major from a clean main. There is no auto-release on merge (this was explored and rejected; see the Releasing section below for why).
  • After PRs merge, branches need manual cleanup (auto-delete head branches isn't enabled on this repo).

Branch state

You should already be on a feature branch with your changes — worktree-based by default, per CLAUDE.md. This skill picks up from there.

If you're invoked from main with uncommitted changes, stop and ask the user before doing anything. Moving in-flight work into a worktree retroactively is awkward (stash + apply, or branch in place, or something else), and the user should pick which.

Workflow: commit and open a PR

  1. Verify the working tree state. Run git status --short. If there are untracked or modified files that aren't part of THIS change (e.g. someone else's experimental directory, build artifacts from a previous run, leftover test files), pause and check with the user before touching them. Don't auto-stage with git add -A or git add ..
  2. Stage only the files relevant to this change by name:

    git add path/to/file1 path/to/file2
  3. Commit with a conventional commit message.

    Title format:

    <type>(<scope>): <short imperative subject>

    Body should explain WHY, not WHAT — the diff already shows the what. Examples from this repo's actual history:

    • feat(mcp): apply mcp-builder best practices to eval-mcp tools
    • fix(release): force tag version + strip local identifier in CI
    • docs: document PyPI release workflow + add CLAUDE.md pointer
    • revert: remove release-please + PR title lint automation

    Use a HEREDOC for multi-line commit messages so formatting is preserved:

    git commit -m "$(cat <<'EOF'
    feat(scope): short subject line
    
    Longer explanation of why this change is being made and what
    problem it solves. Reference other PRs or issues if relevant.
    EOF
    )"
  4. Push the branch. From inside the worktree (or the main checkout if not using a worktree):

    git push -u origin <branch-name>
  5. Open the PR with gh pr create. The PR title must follow the same conventional-commit format as the commit message — the lint workflow (if/when re-added) reads PR titles, and human reviewers expect consistency.

    Use a HEREDOC for the body so formatting is preserved:

    gh pr create --base main --title "<type>(<scope>): <subject>" --body "$(cat <<'EOF'
    ## Summary
    
    - what changed in 1-3 bullet points
    - link to related PRs / issues if applicable
    
    ## Why
    
    The motivation. What problem this solves.
    
    ## Test plan
    
    - [x] tests run locally (uv run pytest ...)
    - [x] manual smoke test of the changed behavior
    - [ ] post-merge verification step (if applicable)
    EOF
    )"
  6. Stop and report the PR URL to the user. Merging is the user's call, never auto-merge. Wait for the user to say it's merged.

Workflow: after the PR is merged

When the user reports the PR is merged (or you verify via gh pr view):

  1. Switch to main and pull:

    cd <main-repo-path>           # if you were in a worktree
    git checkout main
    git pull origin main
  2. Remove the worktree (if you used one):

    git worktree remove .claude/worktrees/<branch-name>

    git worktree remove refuses if the worktree has uncommitted changes. If it does, surface what's there and ask the user before forcing.

  3. Delete the local branch (cleanup; the worktree removal doesn't delete the ref):

    git branch -d <branch-name>
  4. Delete the remote branch:

    git push origin --delete <branch-name>

    Auto-delete-on-merge is intentionally NOT enabled on this repo; the manual cleanup step is the convention.

Workflow: cutting a release

Releases publish a new version to PyPI as llm-evaluation-system==X.Y.Z. This is a deliberate human-initiated step — never auto-release on merge.

  1. Sync main first. Releases must come from a clean main:

    git checkout main
    git pull --ff-only origin main
    git status --short    # should be empty (or only untracked files unrelated to release)
  2. Pick the version bump from semver:

    BumpCommandWhen
    patchmake releasebug fixes only, no new public API
    minormake release-minornew features, backwards-compatible
    majormake release-majorbreaking changes (rare)

    Pick conservatively but accurately. New tool parameters or new functionality = minor (don't undersell as patch — users pin against minor versions and miss features otherwise). Pure bug fixes = patch. Breaking API changes = major.

  3. Run the chosen target. It reads the latest v* tag, computes the next version, tags it, and pushes the tag. Versions are derived from the tag at build time by setuptools-scm — no source file is bumped and no "Release vX.Y.Z" commits appear on main.
  4. Watch the publish workflow. The tag push triggers .github/workflows/publish.yml which builds the frontend, builds the Python distribution, and uploads to PyPI via trusted publisher:

    gh run list --workflow=publish.yml --limit 1
    gh run watch <run-id> --exit-status
  5. Verify the release on PyPI:

    curl -s https://pypi.org/pypi/llm-evaluation-system/json | \
      python3 -c "import sys,json; print(json.load(sys.stdin)['info']['version'])"

    The latest version should match what you just tagged.

Pitfalls and rejected patterns

These are explicitly rejected — don't reintroduce them:

  • Don't push directly to main. Blocked by classifier; bypasses review.
  • Don't force-push to main or any branch with active PRs.
  • Don't add release-please or similar auto-release bots. Requires enabling "Allow GitHub Actions to create and approve pull requests" which OpenSSF best practices explicitly recommend against. Real supply-chain attacks have exploited this exact pattern (CVE-2025-30066 / tj-actions/changed-files compromise affected 23,000+ repos). awslabs peer projects (awslabs/mcp, aws-lambda-powertools-python, etc.) all use manual releases.
  • Don't reintroduce a static version field to pyproject.toml. Version is dynamic via setuptools-scm (declared as dynamic = ["version"]). Adding a static field reintroduces the drift bug where source said one version and PyPI said another.
  • Don't release without explicit user instruction. "I merged the PR" is not "release it." Wait for an explicit ship/release/publish instruction.
  • Don't use gh pr merge --admin to bypass branch protection or any required checks. If a check is blocking the merge, fix the check (e.g. fix the PR title), don't override.

Quick reference

SituationCommand
New worktree + branchgit worktree add .claude/worktrees/<name> -b <type>/<name>
Stage specific filesgit add path/to/file1 path/to/file2
Commitgit commit -m "<type>(<scope>): <subject>"
Push branchgit push -u origin <branch>
Open PRgh pr create --base main --title "..." --body "..."
Pull main after mergegit checkout main && git pull
Remove worktreegit worktree remove .claude/worktrees/<name>
Delete branch localgit branch -d <name>
Delete branch remotegit push origin --delete <name>
Patch releasemake release
Minor releasemake release-minor
Major releasemake release-major
Watch publishgh run watch $(gh run list --workflow=publish.yml --limit 1 --json databaseId --jq '.[0].databaseId')
Verify PyPIcurl -s https://pypi.org/pypi/llm-evaluation-system/json | python3 -c "import sys,json; print(json.load(sys.stdin)['info']['version'])"

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.