musyskills 0.0.0-stage → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ahmadammarm
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,40 @@
1
- # Temporary Holding Version
1
+ # musyskills
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Install [Musyskills](https://github.com/ahmadammarm/musyskills) AI agent skills into Claude Code, Codex, Cursor, and Antigravity with one command. Requires Node.js 24 or later.
4
+
5
+ ```
6
+ npx musyskills list
7
+ npx musyskills add pr-draft push-to-origin
8
+ npx musyskills add --all
9
+ ```
10
+
11
+ ## Commands
12
+
13
+ | Command | What it does |
14
+ |---|---|
15
+ | `list` | List the available skills |
16
+ | `add <skill...>` / `add --all` | Install skills, or update ones already installed by musyskills |
17
+ | `remove <skill...>` | Remove skills that musyskills installed |
18
+ | `update` | Update every skill musyskills installed to this CLI's version |
19
+ | `doctor` | Show which tools were detected, where skills are, and their state |
20
+
21
+ ## Options
22
+
23
+ - `--tool <name>` (`-t`): `claude`, `codex`, `cursor`, or `antigravity`. Repeat it, or separate with commas, for several tools. Without it, musyskills detects tools from the project (`.claude/`, `AGENTS.md`, `.cursor/`, `.gemini/`, and similar). If nothing is found, it asks in an interactive terminal, and otherwise uses `claude`.
24
+ - `--global` (`-g`): install for your user instead of the current project.
25
+ - `--force` (`-f`): overwrite or remove a skill that you edited, or that musyskills did not install.
26
+
27
+ ## Where skills go
28
+
29
+ | Tool | Project | Global (`--global`) |
30
+ |---|---|---|
31
+ | claude | `.claude/skills/` | `~/.claude/skills/` |
32
+ | codex | `.agents/skills/` | `~/.agents/skills/` |
33
+ | cursor | `.cursor/skills/` | `~/.cursor/skills/` |
34
+ | antigravity | `.agents/skills/` | `~/.gemini/config/skills/` |
35
+
36
+ musyskills records what it installed in a `.musyskills.json` file in each skills folder. It uses that record to update or remove only its own skills, and it never overwrites a skill you changed unless you pass `--force`.
37
+
38
+ ## License
39
+
40
+ MIT
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import { main, UsageError } from '../src/cli.js';
3
+
4
+ main(process.argv.slice(2)).catch((err) => {
5
+ console.error(`musyskills: ${err.message}`);
6
+ process.exit(err instanceof UsageError ? 2 : 1);
7
+ });
package/package.json CHANGED
@@ -1,6 +1,40 @@
1
1
  {
2
2
  "name": "musyskills",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.4.1",
4
+ "description": "Install Musyskills AI agent skills into Claude Code, Codex, Cursor, and Antigravity.",
5
+ "type": "module",
6
+ "bin": {
7
+ "musyskills": "bin/musyskills.js"
8
+ },
9
+ "files": [
10
+ "bin",
11
+ "src",
12
+ "skills"
13
+ ],
14
+ "scripts": {
15
+ "prepack": "node scripts/bundle.mjs",
16
+ "postpack": "node scripts/bundle.mjs --clean",
17
+ "test": "node --test"
18
+ },
19
+ "engines": {
20
+ "node": ">=24"
21
+ },
22
+ "keywords": [
23
+ "agent-skills",
24
+ "claude-code",
25
+ "codex",
26
+ "cursor",
27
+ "antigravity",
28
+ "skills",
29
+ "cli"
30
+ ],
31
+ "author": "ahmadammarm",
32
+ "license": "MIT",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "git+https://github.com/ahmadammarm/musyskills.git",
36
+ "directory": "packages/cli"
37
+ },
38
+ "homepage": "https://github.com/ahmadammarm/musyskills#readme",
39
+ "bugs": "https://github.com/ahmadammarm/musyskills/issues"
40
+ }
@@ -0,0 +1,85 @@
1
+ ---
2
+ name: apply-review-feedback
3
+ description: Implement fixes for existing code review comments or requested changes on a pull request or diff, across any language or framework. Use whenever the user pastes review comments, says "address this feedback," "fix review comments," or references reviewer requests that need to be implemented.
4
+ argument-hint: <review-comment-or-thread>
5
+ ---
6
+
7
+ # apply-review-feedback
8
+
9
+ ## Purpose
10
+
11
+ Take a set of review comments or requested changes and implement them accurately and traceably in the codebase, without introducing unrelated modifications, regressions, or stylistic drift.
12
+
13
+ ## Trigger
14
+
15
+ Activate this skill when the user:
16
+ - Pastes one or more reviewer comments (from GitHub, GitLab, Bitbucket, or plain text) and asks to address them.
17
+ - Says "fix the review feedback," "implement requested changes," "address this comment," or similar.
18
+ - References a specific pull request review thread and wants the code changes applied locally.
19
+
20
+ ## Pre-flight Checks
21
+
22
+ Before touching any file, perform the following checks in order:
23
+
24
+ 1. Run `git status` to confirm the current branch and working-tree state. If there are uncommitted changes unrelated to the review, note them and ask whether to stash or leave them before continuing.
25
+ 2. Run `git log --oneline -5` to understand recent commit context and branch name.
26
+ 3. Look for project-specific rules files (`.claude/rules`, `.agents/rules`, `.cursor/rules`, `CONTRIBUTING.md`, `.github/CONTRIBUTING.md`, or any similarly named convention file). Read whichever file is found. These rules take full priority over the generic guidance in this skill.
27
+ 4. If no project rules file exists, proceed with this skill's defaults below.
28
+
29
+ ## Workflow
30
+
31
+ Follow these steps sequentially for every batch of review comments provided:
32
+
33
+ ### Step 1: Parse and Catalogue Comments
34
+ - Read all review comments provided by the user.
35
+ - Convert each comment into a discrete, actionable checklist item.
36
+ - Number them in the order they will be addressed.
37
+ - If a comment is ambiguous, contradicts existing logic, or conflicts with another comment, flag it immediately and ask the user for clarification before proceeding. Do not guess at intent.
38
+
39
+ ### Step 2: Map Comments to Files
40
+ - For each checklist item, identify the target file and, if specified, the line or function referenced in the comment.
41
+ - If the comment references code that no longer exists or has moved, flag it and ask the user how to proceed.
42
+
43
+ ### Step 3: Implement Changes
44
+ - Address each comment individually in sequence.
45
+ - Apply the minimal, targeted change that satisfies the comment. Do not refactor, rename, or restructure code beyond what the comment explicitly requests.
46
+ - Preserve the existing code style, indentation, naming conventions, and patterns already present in the file.
47
+ - If a comment requests a fix that would require adding a new dependency or a significant refactor, pause, note the scope impact, and ask the user for approval before continuing.
48
+ - Do not resolve or mark comments as resolved on any review platform; only apply the local code change.
49
+
50
+ ### Step 4: Validate Changes
51
+ - After all changes are applied, run `git diff` to confirm only the expected lines were modified.
52
+ - If the project includes a test runner or linter in its configuration (`package.json`, `Makefile`, `pyproject.toml`, etc.), run the relevant command to verify no tests or lint rules are broken.
53
+ - If tests break, diagnose the root cause and fix only what the review comment necessitated. Do not silently suppress or skip tests.
54
+
55
+ ### Step 5: Summarize
56
+ - Produce a clear, traceable summary mapping each original comment to the specific change made.
57
+ - Include the file name, the lines changed, and a one-sentence description of what was done.
58
+ - List any comments that were left unresolved and the reason (ambiguity, scope concern, awaiting user input).
59
+
60
+ ## Rules
61
+
62
+ - Address each comment individually and traceably. Do not bundle unrelated fixes into a single change.
63
+ - Project rules files found during Pre-flight Checks take full priority over this skill's defaults. Apply them wherever they conflict.
64
+ - If any comment is ambiguous or conflicts with existing code patterns, stop and ask rather than making an assumption.
65
+ - Do not introduce new dependencies, abstract new utilities, or perform structural refactors beyond the explicit scope of the review comment.
66
+ - Do not modify files unrelated to the review comments, even if improvements are noticed.
67
+ - Preserve all existing comments, docstrings, and documentation in modified files unless the review comment specifically targets them.
68
+ - Do not force-push or amend commits. Only apply file changes locally.
69
+
70
+ ## Edge Cases
71
+
72
+ - If the user provides review comments for a file that does not exist in the current branch, state this clearly and ask whether the file was deleted or if the wrong branch is checked out.
73
+ - If the same line is targeted by two conflicting comments, present both to the user and wait for a decision before applying either.
74
+ - If the project has a CI/CD configuration (`.github/workflows`, `Jenkinsfile`, `.gitlab-ci.yml`), do not modify it unless the review comment explicitly targets it.
75
+
76
+ ## Output Format
77
+
78
+ Deliver the result as a checklist summary containing:
79
+
80
+ 1. **Review Comment** — the original reviewer text (or a short quote).
81
+ 2. **File Changed** — the file path relative to the repo root.
82
+ 3. **Lines Affected** — the line range that was modified.
83
+ 4. **Action Taken** — a one-sentence description of the change made.
84
+ 5. **Rules Source** — whether project-specific rules or this skill's defaults governed the change.
85
+ 6. **Unresolved Comments** — any items not addressed and the explicit reason why.
@@ -0,0 +1,102 @@
1
+ ---
2
+ name: code-changes-review
3
+ description: Review modified or staged code for correctness, security, readability, DRY-ness, performance, and overall best practices, regardless of language or framework. Use whenever the user asks to review code, review a diff, review changes, or check code before committing/merging.
4
+ argument-hint: <branch-or-file-to-review>
5
+ ---
6
+
7
+ # code-changes-review
8
+
9
+ ## Purpose
10
+
11
+ Provide a thorough, objective, and actionable review of code changes in the current repository. The goal is to catch bugs, design issues, security risks, duplication, and readability or performance problems before code is committed or merged, ensuring only well-reasoned changes reach the main branch.
12
+
13
+ ## Trigger
14
+
15
+ Activate this skill when the user:
16
+ - Asks to "review my code," "review this diff," "check my changes," "look at what I wrote," or similar.
17
+ - Is preparing to commit, push, or open a pull request and wants structured feedback first.
18
+ - Wants a quality gate check before sharing code with teammates or deploying.
19
+
20
+ ## Pre-flight Checks
21
+
22
+ Before reviewing any code, perform the following in order:
23
+
24
+ 1. Run `git status` to identify all modified, added, deleted, and renamed files.
25
+ 2. If `git status` shows no changes, state this clearly and ask the user what they would like reviewed instead. Do not proceed to generate a review file.
26
+ 3. Run `git diff` to see unstaged changes and `git diff --staged` to see staged changes. Capture both.
27
+ 4. Look for project-specific rules or coding conventions in files such as `.claude/rules`, `.agents/rules`, `.cursor/rules`, `CONTRIBUTING.md`, `.github/CONTRIBUTING.md`, style guide documents, or `eslint`/`pylint`/`rubocop` configuration files. Read whichever is found. These take full priority over this skill's generic guidance wherever they conflict.
28
+
29
+ ## Workflow
30
+
31
+ ### Step 1: Understand Context
32
+ - Read each changed file in its full context, not just the diff hunk. Understanding surrounding logic is essential for catching issues that span multiple lines or functions.
33
+ - Identify the apparent purpose of the change (bug fix, new feature, refactor, configuration update, etc.) to calibrate the review accordingly.
34
+
35
+ ### Step 2: Evaluate Each Change
36
+
37
+ Assess every changed file against the following dimensions:
38
+
39
+ **Correctness and Logic**
40
+ - Are there logic errors, off-by-one errors, or incorrect conditionals?
41
+ - Are all edge cases handled (null/undefined values, empty collections, boundary inputs)?
42
+ - Is error handling present and appropriate? Are exceptions caught at the right level?
43
+
44
+ **Security**
45
+ - Is any user input passed to a database query, shell command, file path, or external service without validation or sanitization?
46
+ - Are secrets, API keys, or credentials present in the diff?
47
+ - Are authentication and authorization checks applied correctly?
48
+ - Are dependencies introduced by this change up-to-date and free of known vulnerabilities?
49
+
50
+ **Readability**
51
+ - Are variable, function, and class names clear and descriptive?
52
+ - Are functions small and focused on a single responsibility?
53
+ - Is the nesting depth and cyclomatic complexity reasonable?
54
+ - Is self-explanatory logic preferred over clever or cryptic constructs?
55
+
56
+ **DRY (Don't Repeat Yourself)**
57
+ - Is any logic, string, or value duplicated across the diff when it could be extracted or reused?
58
+ - Are there copy-pasted blocks or magic values that should be constants or utilities?
59
+
60
+ **Performance**
61
+ - Are there unnecessary loops, redundant computations, or N+1 query patterns?
62
+ - Are expensive operations performed inside loops when they could be hoisted or memoized?
63
+ - Are there obvious algorithmic inefficiencies given the scale at which this code is expected to run?
64
+
65
+ **Best Practices**
66
+ - Does the code use the language and framework idiomatically?
67
+ - Are resources (file handles, database connections, HTTP sessions) properly opened and closed?
68
+ - Is the change consistent with the existing patterns and conventions in the repository?
69
+ - Do project-specific rules from Step Pre-flight Check 4 apply, and are they satisfied?
70
+
71
+ ### Step 3: Classify Findings
72
+
73
+ Group every finding into one of three categories:
74
+
75
+ - **Critical**: Bugs, security risks, incorrect logic, or correctness problems that should block merging. Each finding must include a concrete, implementable fix suggestion.
76
+ - **Suggestion**: Readability, DRY, performance, and best-practice improvements. These are recommended but do not block merging. Each must include a specific, actionable fix.
77
+ - **Info**: Observations, neutral context, or minor notes that require no action from the author.
78
+
79
+ ### Step 4: Write the Review File
80
+
81
+ - Format the review as a markdown file following the output structure below.
82
+ - Name the file `code-review-<YYYY-MM-DD>.md` or `code-review-<branch-name>.md`.
83
+ - Write it to the project root or a `reviews/` directory if one exists.
84
+ - Present the file path to the user after writing.
85
+
86
+ ## Rules
87
+
88
+ - Never assume a specific language, framework, or project structure. Infer everything from the repository itself.
89
+ - Project rules files discovered in Pre-flight Checks take full priority over this skill's generic guidance wherever they conflict.
90
+ - Do not rewrite or refactor code unless explicitly asked. Describe the issue and provide a concrete suggested fix.
91
+ - Every Critical and Suggestion finding must cite the file name and line number and include a specific, implementable fix, not a vague "consider improving this."
92
+ - Categorize missing or inadequate tests and DRY violations as Suggestion, not Critical, unless they directly cause a correctness or security risk.
93
+ - If `git status` shows no changes, state that clearly and do not generate a file.
94
+
95
+ ## Output Format
96
+
97
+ A markdown file structured as follows:
98
+
99
+ 1. **Summary** — Files reviewed, total findings per category (Critical / Suggestion / Info), and a one-line overall verdict (e.g., "Ready to merge" or "Needs fixes before merging").
100
+ 2. **Critical Findings** — For each finding: file path, line(s), description of the issue, and a concrete fix suggestion.
101
+ 3. **Suggestions** — For each finding: file path, line(s), category tag (Readability / DRY / Performance / Best Practice), description of the improvement opportunity, and a concrete fix suggestion.
102
+ 4. **Info** — For each finding: file path, line(s), and a short contextual note. No fix required.
@@ -0,0 +1,83 @@
1
+ ---
2
+ name: explain-changes
3
+ description: Summarize and explain the current uncommitted or unpushed code changes in a repository, in plain language, regardless of language or framework. Use whenever the user asks "what did I change," "explain my changes," "summarize this diff," or wants a recap before writing a commit message or PR description.
4
+ argument-hint: <branch-or-scope-to-explain>
5
+ ---
6
+
7
+ # explain-changes
8
+
9
+ ## Purpose
10
+
11
+ Give a clear, accurate, and human-readable explanation of what changed in the codebase and why it likely matters. The goal is to help the developer understand the full scope of their own modifications without needing to re-read the raw diff themselves, which is particularly useful before writing a commit message, PR description, or changelog entry.
12
+
13
+ ## Trigger
14
+
15
+ Activate this skill when the user:
16
+ - Asks to "explain my changes," "summarize what I did," "what did I change," or "recap this diff."
17
+ - Wants context or a summary before writing a commit message or PR description.
18
+ - Wants to verify the scope of their modifications before staging or pushing.
19
+ - Asks for a changelog entry or release note based on the current diff.
20
+
21
+ ## Pre-flight Checks
22
+
23
+ Before producing any explanation, perform the following in order:
24
+
25
+ 1. Run `git status` to identify all modified, added, deleted, and renamed files in both the working tree and the staging area.
26
+ 2. If `git status` shows no changes, state this clearly and do not generate an explanation file. Ask the user if they want to review a specific commit or branch instead.
27
+ 3. Run `git diff` to capture unstaged changes and `git diff --staged` to capture staged changes. Use both to form a complete picture.
28
+ 4. Run `git log --oneline -10` to understand recent commit history and the current branch, which provides context for inferring the intent behind the changes.
29
+
30
+ ## Workflow
31
+
32
+ ### Step 1: Group Changes Logically
33
+ - Do not list files in raw alphabetical or `git status` order.
34
+ - Group changes by their logical relationship: related feature files together, configuration changes separately, test files adjacent to the code they test, documentation changes as their own group.
35
+ - Common groupings include: core feature/logic changes, API or route changes, database or schema changes, configuration or environment changes, test additions or updates, and documentation or comment updates.
36
+
37
+ ### Step 2: Explain Each Group
38
+ For each logical group, provide:
39
+ - **What changed**: a plain-language description of the modifications (e.g., "Added a new `validateEmail` function to the utilities module").
40
+ - **Why it likely changed**: the inferred purpose based on what the code does (e.g., "This appears to centralize email validation that was previously duplicated across three files"). Only state what the code reasonably supports. Do not speculate beyond what is evident.
41
+ - **Impact**: whether the change is additive, a bug fix, a breaking change, a performance improvement, or a refactor. Note any changes to public interfaces, API contracts, or database schemas explicitly, as these carry downstream risk.
42
+
43
+ ### Step 3: Flag Unrelated or Suspicious Files
44
+ - Identify any files in the diff that appear unrelated to the main body of change.
45
+ - Common examples: a configuration file changed alongside a feature, a seemingly unrelated test file modified, or a lock file updated.
46
+ - Surface these explicitly so the user can verify they were intentional before committing.
47
+
48
+ ### Step 4: Note Side Effects
49
+ - Identify and call out any notable side effects of the changes:
50
+ - New packages or dependencies introduced.
51
+ - Environment variable additions or changes.
52
+ - Database migration files created or modified.
53
+ - Breaking changes to public APIs or exported interfaces.
54
+ - Changes to CI/CD configuration or deployment scripts.
55
+
56
+ ### Step 5: Confirm Output Location
57
+ - Before writing the output file, ask the user which directory they would like it saved to.
58
+ - Do not assume a default location or silently write to a directory without confirmation.
59
+ - Name the file `changes-explanation-<YYYY-MM-DD>.md` or `changes-explanation-<branch-name>.md` based on the context.
60
+
61
+ ### Step 6: Write the Explanation File
62
+ - Write the full explanation to a markdown file in the confirmed directory.
63
+ - Present the file path to the user after writing.
64
+ - Do not modify any source files. This skill is read-only with respect to the project's actual code.
65
+
66
+ ## Rules
67
+
68
+ - Do not speculate about intent beyond what the code reasonably supports. When the purpose is unclear, state the uncertainty explicitly rather than fabricating a plausible-sounding explanation.
69
+ - Keep the summary in plain language. Avoid restating the diff line by line or using excessive technical jargon.
70
+ - Do not modify any source file, staged file, or git history. This skill only reads code and writes the explanation document.
71
+ - Always confirm the target directory with the user before writing the output file. Never guess or silently default to a location.
72
+ - If `git status` shows no changes, state that clearly and stop. Do not generate a file with empty or fabricated content.
73
+ - Do not include sensitive information (secrets, credentials, personally identifiable data) in the explanation file, even if it appears in the diff.
74
+
75
+ ## Output Format
76
+
77
+ A markdown file with the following sections, in order:
78
+
79
+ 1. **Summary** — A single paragraph giving an overall description of what the changes accomplish and their general purpose.
80
+ 2. **Changes by Area** — Grouped by logical area, each group containing: what changed, why it likely changed, and the impact on the system.
81
+ 3. **Notable Side Effects** — New dependencies, environment variable changes, schema changes, breaking API changes, or CI/CD modifications. Omit this section if none exist.
82
+ 4. **Files to Double-Check** — Files that appear unrelated to the main change and warrant a second look before committing. Omit this section if all files appear intentional.
83
+ 5. **Full File List** — A complete list of modified, added, deleted, and renamed files as reported by `git status`.
@@ -0,0 +1,80 @@
1
+ ---
2
+ name: pr-draft
3
+ description: Prepare or update a pull request title and description for the current branch's changes, reusing existing PR content whenever available, across any language, framework, or Git hosting platform. Use whenever the user asks to create a PR, open a pull request, write a PR description, or update an existing PR.
4
+ argument-hint: <pr-title-or-context>
5
+ ---
6
+
7
+ # pr-draft
8
+
9
+ ## Purpose
10
+
11
+ Produce or update a well-structured pull request title and description that accurately reflects the current code changes. When an existing PR description is available, make targeted, incremental edits rather than rewriting it wholesale. The output should be immediately usable by the author with minimal edits.
12
+
13
+ ## Trigger
14
+
15
+ Activate this skill when the user:
16
+ - Asks to "create a PR," "open a pull request," "write a PR description," or "draft a PR."
17
+ - Asks to update or refresh an existing PR title or description.
18
+ - Wants to prepare a PR message before pushing or using the platform UI.
19
+
20
+ ## Pre-flight Checks
21
+
22
+ Before writing any PR content, perform the following in order:
23
+
24
+ 1. Run `git status` to confirm there is a working branch and understand the current state of the working tree.
25
+ 2. Run `git log --oneline origin/main..HEAD` (or `origin/master..HEAD` if `main` does not exist) to see all commits that are unique to this branch. If there are no commits ahead of the base branch, state this clearly and stop.
26
+ 3. Run `git diff origin/main...HEAD` (three-dot diff) to capture the full content diff between this branch and the base.
27
+ 4. Check for a PR template in the repository. Common locations include `.github/PULL_REQUEST_TEMPLATE.md`, `.github/PULL_REQUEST_TEMPLATE/`, `docs/PULL_REQUEST_TEMPLATE.md`, or `PULL_REQUEST_TEMPLATE.md` in the root. If found, read it and use its structure as the required format for the description.
28
+ 5. Check if the user has provided an existing PR title and description (pasted text or a file path). If so, treat it as the base to update rather than starting fresh.
29
+
30
+ ## Workflow
31
+
32
+ ### Step 1: Analyze the Changes
33
+ - Read the commit log from Step 2 to understand the scope and intent of the branch.
34
+ - Read the full diff from Step 3 to understand the specific modifications made to the codebase.
35
+ - Identify the primary type of change: new feature, bug fix, refactor, performance improvement, documentation update, dependency upgrade, or configuration change. A PR may span multiple types.
36
+
37
+ ### Step 2: Draft or Update the Title
38
+ - The title must be concise (ideally under 72 characters), written in the imperative mood, and accurately describe the primary change.
39
+ - Good examples: "Add email validation to the registration flow" or "Fix race condition in the session refresh handler."
40
+ - Avoid vague titles like "Updates" or "Fix bug." Be specific enough that a reviewer understands the scope without reading the full description.
41
+ - If an existing title is provided and still accurately reflects the change, keep it. Only update if the new commits have changed the scope or intent.
42
+
43
+ ### Step 3: Draft or Update the Description
44
+ - If a PR template was found in Step 4, fill in every section of that template. Do not omit sections unless the template itself marks them as optional.
45
+ - If no template exists, use the default structure defined in the Output Format section below.
46
+ - If an existing PR description was provided, update only the sections affected by new commits. Preserve all other sections exactly as they are. Do not rewrite unaffected content.
47
+ - Do not fabricate testing steps, context, or motivation that is not directly evidenced by the code or explicitly provided by the user.
48
+ - If the diff includes a migration, schema change, or breaking API change, ensure this is prominently noted in the description under a dedicated section.
49
+
50
+ ### Step 4: Review CI/CD Context
51
+ - Check for a CI/CD configuration file (`.github/workflows/`, `Jenkinsfile`, `.gitlab-ci.yml`, `.circleci/config.yml`). If one exists, note whether the PR changes affect the build or deployment pipeline and include a brief note in the PR description if so.
52
+
53
+ ### Step 5: Present the Output
54
+ - Present the drafted title and description clearly, separated from each other.
55
+ - If this is an update to an existing PR, explicitly state which sections were changed and which were preserved.
56
+ - Mark the output as "New PR Draft" or "Updated PR Description (changes from existing)" so the author knows at a glance what to expect.
57
+ - Ask the user if they would like any sections adjusted before they submit.
58
+
59
+ ## Rules
60
+
61
+ - Never discard an existing PR title or description wholesale. Always make targeted, incremental edits when a base exists.
62
+ - Match the repository's PR template structure exactly if one exists. The template's headings and section order are required, not optional.
63
+ - Do not fabricate testing steps, screenshots, issue references, or context that is not evidenced by the code changes or user-provided input.
64
+ - Keep the title concise and the description scannable. Use short sections, bullet points, and clear headings. Avoid writing paragraphs of dense prose where structured lists would be clearer.
65
+ - If the branch has no commits ahead of the base branch, state this clearly and do not generate a PR description.
66
+ - Do not push, create, or update PRs on any platform automatically. The output of this skill is a draft text only.
67
+
68
+ ## Output Format
69
+
70
+ When no PR template is found, use the following default structure:
71
+
72
+ **Title**: A concise, imperative summary of the change.
73
+
74
+ **Description**:
75
+ 1. **Summary** — A 2-4 sentence explanation of what this PR does and why.
76
+ 2. **Changes Made** — A bullet list of the specific modifications, organized by file or area.
77
+ 3. **Type of Change** — Checkboxes or a list indicating: Bug Fix / New Feature / Refactor / Performance / Documentation / Dependency Update / Breaking Change.
78
+ 4. **Testing Notes** — How the change was tested, or a note if testing is not applicable. Do not invent steps; only include what is evident.
79
+ 5. **Breaking Changes** — If applicable, describe what breaks and what consumers of this code need to do. Omit if no breaking changes.
80
+ 6. **Related Issues** — Links to relevant issues or tickets if provided by the user. Omit if none.
@@ -0,0 +1,83 @@
1
+ ---
2
+ name: prd-generator
3
+ description: Generate a structured Product Requirements Document (PRD) by interviewing the user about a new feature or product idea, and save the result as a markdown file. Use whenever the user asks to write a PRD or define product requirements.
4
+ argument-hint: <feature-idea-or-topic>
5
+ ---
6
+
7
+ # prd-generator
8
+
9
+ ## Purpose
10
+
11
+ To systematically interview the user to extract all necessary product requirements for a new feature or product, and structure that information into a comprehensive Markdown Product Requirements Document (PRD). The goal is to ensure that development does not begin until the scope, user stories, and technical constraints are well-defined and agreed upon.
12
+
13
+ ## Trigger
14
+
15
+ Activate this skill when the user:
16
+ - Asks to "write a PRD," "create a product requirements document," or "draft a PRD."
17
+ - Uses the explicit slash command `/prd-generator`.
18
+ - Asks to define, specify, or formalize a new feature's requirements before coding.
19
+
20
+ ## Pre-flight Checks
21
+
22
+ Before beginning the interview process, the agent must:
23
+ 1. Search the workspace for a PRD template (e.g., `docs/PRD_TEMPLATE.md` or `.github/PRD_TEMPLATE.md`). If found, use its structure as the target format.
24
+ 2. Check if the user has provided an existing partial PRD, notes, or an issue ticket. If so, treat those as the base requirements and identify which sections are missing.
25
+ 3. Check if there is an existing `docs/` folder in the project. If not, note that one may need to be created.
26
+
27
+ ## Workflow
28
+
29
+ ### Step 1: Initial Discovery
30
+ - If the user hasn't provided a specific feature idea, ask them for one.
31
+ - Ask clarifying questions to understand:
32
+ - The primary problem being solved (the "Why").
33
+ - The target audience and personas (who will use this feature).
34
+ - Any known technical or business constraints.
35
+ - *Tip:* Use interactive questions (e.g., the `ask_question` tool) or present a small, focused list of questions in the chat. Do not overwhelm the user with a massive questionnaire.
36
+
37
+ ### Step 2: Define Scope & Stories
38
+ - Based on the initial discovery, propose a discrete list of "In Scope" and "Out of Scope" (Non-Goals) items. This is crucial for preventing feature creep.
39
+ - Draft 3-5 core User Stories with basic Acceptance Criteria, following the format: *"As a [persona], I want to [action] so that [benefit]."*
40
+ - Ask the user to review, modify, or confirm the scope and user stories before proceeding to the full draft.
41
+
42
+ ### Step 3: Draft the PRD
43
+ - Once the user confirms the scope and stories, generate the full PRD according to the **Output Format** defined below.
44
+ - Flesh out the remaining sections (Technical Considerations, UX/Design, Risks, and Success Metrics) based on best practices, standard patterns, and the context gathered in steps 1 and 2.
45
+
46
+ ### Step 4: Save and Present
47
+ - Write the final PRD to a Markdown file in the project's documentation folder (e.g., `docs/PRD-[feature-name].md`).
48
+ - If the user named a location, save the file there.
49
+ - Otherwise, if a `docs/` folder does not exist, create it and save the file there. Tell the user the path so they can move it if they prefer another location.
50
+ - Inform the user that the file has been created, provide a direct link to it, and ask if any sections need further refinement.
51
+
52
+ ## Rules
53
+
54
+ - **No hallucinated requirements:** Never generate an entire PRD from a single vague sentence without first confirming the scope and user stories with the user. The interview phase is mandatory.
55
+ - **Pacing:** Group questions logically and proceed conversationally. Do not dump all questions at once.
56
+ - **Save to a file:** The final PRD MUST be saved as an actual `.md` file in the project. Do not just print the entire PRD in the chat response, as this pollutes the context window.
57
+ - **Strict adherence to structure:** The final PRD must contain all sections listed in the Output Format. If a section is not applicable, include the heading and write "N/A" with a brief reason.
58
+
59
+ ## Output Format
60
+
61
+ If a repository template is found in Pre-flight checks, use it exactly. Otherwise, the generated PRD must be formatted in Markdown and include the following sections exactly:
62
+
63
+ 1. **Title & Meta Information**
64
+ - Project/Feature Name, Author, Status (Draft/In Review/Approved), Date, Target Release.
65
+ 2. **Overview & Problem Statement**
66
+ - **What:** High-level summary of the feature.
67
+ - **Why:** The specific problem this solves.
68
+ 3. **Target Audience & Personas**
69
+ - Who will use this feature and what are their specific needs.
70
+ 4. **Goals & Non-Goals**
71
+ - **In Scope:** What is being built.
72
+ - **Out of Scope (Non-Goals):** What is explicitly NOT being built.
73
+ 5. **User Stories & Functional Requirements**
74
+ - Format: *"As a [persona], I want to [action] so that [benefit]."*
75
+ - Acceptance Criteria for each story (bulleted list defining when the story is "done").
76
+ 6. **User Experience (UX) & Design**
77
+ - Core user flows, key interactions, or references to wireframes.
78
+ 7. **Technical Considerations**
79
+ - High-level architecture, required API endpoints, database schema changes, etc.
80
+ 8. **Dependencies, Risks & Mitigations**
81
+ - Blockers, security considerations, dependencies on other systems, and mitigations.
82
+ 9. **Success Metrics**
83
+ - Quantifiable metrics to measure the feature's success (e.g., adoption rate, performance metrics).
@@ -0,0 +1,125 @@
1
+ ---
2
+ name: project-explanation
3
+ description: Understand a project comprehensively and explain it clearly to the user. Then (unless the user asks for no questions) ask which feature the user wants to develop, explain that feature in depth, and confirm whether the user wants to proceed with development. Trigger when the user asks to understand, explore, summarize, or explain a codebase/project, or asks "what features does this project have" or "help me understand this project".
4
+ argument-hint: <project-name-or-feature>
5
+ ---
6
+
7
+ # project-explanation
8
+
9
+ ## Purpose
10
+
11
+ Deeply understand a project's structure, architecture, and features, then explain it clearly in plain language. After summarizing the project, guide the user interactively to select a feature for deeper exploration and, optionally, active development.
12
+
13
+ ## Trigger
14
+
15
+ Activate this skill when the user:
16
+ - Runs the slash command `/project-explanation`.
17
+ - Asks to "understand this project," "explain this codebase," "give me a project overview," or similar.
18
+ - Asks "what does this project do," "what features exist," or "help me get up to speed on this repo."
19
+ - Wants an onboarding overview before deciding what to build or improve next.
20
+
21
+ ## Interaction Mode
22
+
23
+ Determine the mode before starting:
24
+
25
+ - **Interactive (default)**: Pause at the two decision points (feature selection and development confirmation) and wait for the user's answer.
26
+ - **Non-interactive**: Use this mode when the user's request or the skill arguments ask for no questions (e.g., "no questions," "make no questions," "don't ask," "just summarize"). Do not ask the user anything and do not wait for input. Instead:
27
+ - End Step 4 with a **Recommended Next Step** section in place of the feature-selection question: name one or two features or improvements worth developing first and give a one-sentence reason for each, based on evidence from the code.
28
+ - Stop after Step 4. Do not perform the deep-dive or produce an implementation plan unless the user asks for one in a later message.
29
+
30
+ ## Pre-flight Checks
31
+
32
+ Before exploring the project, perform the following in order:
33
+
34
+ 1. Run `git status` to confirm the current branch and working-tree state.
35
+ 2. List the root directory structure to understand the top-level layout and identify what type of project this is.
36
+ 3. Read the `README.md` (or `readme.md`, `README.rst`, `docs/index.md`) if one exists. This is the primary source of intent and feature documentation.
37
+ 4. Read configuration files relevant to the project type, such as:
38
+ - `package.json` / `package-lock.json` for JavaScript/TypeScript projects.
39
+ - `pyproject.toml` / `requirements.txt` for Python projects.
40
+ - `Gemfile` for Ruby projects.
41
+ - `go.mod` for Go projects.
42
+ - `Cargo.toml` for Rust projects.
43
+ - `.env.example` for environment variable requirements.
44
+ - `docker-compose.yml` / `Dockerfile` for containerized deployments.
45
+ 5. Identify the primary directories and their likely responsibilities (e.g., `src/`, `app/`, `api/`, `components/`, `services/`, `models/`, `tests/`, `scripts/`, `docs/`).
46
+
47
+ ## Workflow
48
+
49
+ ### Step 1: Identify the Tech Stack
50
+ - Determine the primary programming language(s) from file extensions and configuration files.
51
+ - Identify the main framework (e.g., Next.js, Django, Rails, Spring Boot, Express, FastAPI) from dependencies or configuration.
52
+ - Identify the database layer if evident (SQL, MongoDB, Redis, etc.).
53
+ - Identify the deployment or infrastructure approach (Docker, Kubernetes, serverless, etc.) if present.
54
+ - Note any significant external integrations (third-party APIs, authentication providers, payment systems).
55
+
56
+ ### Step 2: Identify the Architecture Pattern
57
+ - Determine the overall architectural approach from the directory structure and code organization:
58
+ - Frontend-only (SPA, static site)
59
+ - Backend-only (API server, CLI tool, library)
60
+ - Full-stack monolith
61
+ - Full-stack monorepo with separate frontend and backend packages
62
+ - Microservices
63
+ - Identify key architectural layers present (e.g., controllers/routes, services/use-cases, repositories/data access, models/entities, middleware, utilities).
64
+
65
+ ### Step 3: Map the Features
66
+ - Read key source files and entry points (e.g., `main.ts`, `app.py`, `index.js`, route definitions, page components) to enumerate distinct features.
67
+ - A feature is any self-contained piece of user-facing or system-level functionality (e.g., user authentication, dashboard, report generation, background jobs, API endpoints, notification system).
68
+ - List every feature identified with a brief one-line description.
69
+
70
+ ### Step 4: Present the Comprehensive Summary
71
+ Present the findings to the user in the following structure:
72
+ - **Project Name and Purpose** — what the project is and who it is for.
73
+ - **Tech Stack** — languages, frameworks, databases, and key integrations.
74
+ - **Architecture** — the overall pattern and how the main layers are organized.
75
+ - **Features** — a numbered list of all identified features with one-line descriptions.
76
+ - **Key Entry Points** — the main files a developer would start reading to understand the system.
77
+
78
+ After presenting the summary, ask the user:
79
+
80
+ > "From the features above, which one would you like to explore further?"
81
+
82
+ Wait for the user's response before continuing. Do not proceed to the next step without a selection.
83
+
84
+ In non-interactive mode, replace the question with the **Recommended Next Step** section described under Interaction Mode, then stop.
85
+
86
+ ### Step 5: Deep-Dive on the Selected Feature
87
+ Once the user selects a feature:
88
+ - Read all files directly related to that feature (routes, controllers, services, models, components, tests).
89
+ - Explain how the feature currently works end-to-end: the entry point, data flow, business logic, data persistence, and any output or response.
90
+ - List every file that contributes to this feature and describe each file's role.
91
+ - Identify the dependencies this feature has on other parts of the system.
92
+ - Identify any limitations, known edge cases, missing tests, or improvement opportunities observable from the code.
93
+
94
+ After the detailed explanation, ask the user:
95
+
96
+ > "Would you like to proceed with developing or improving this feature now?"
97
+
98
+ Wait for the user's response before continuing.
99
+
100
+ ### Step 6: Plan or Conclude
101
+ - If the user says **yes**, provide a concrete implementation plan:
102
+ - The specific files that need to be created or modified.
103
+ - A step-by-step technical approach.
104
+ - An estimated complexity level (low / medium / high) and a rationale.
105
+ - Any risks or prerequisites to address first.
106
+ - If the user says **no**, offer to return to the full feature list from Step 4 or to end the exploration session.
107
+
108
+ ## Rules
109
+
110
+ - In interactive mode, always wait for the user's explicit response at the two decision points (feature selection and development confirmation) before continuing.
111
+ - In non-interactive mode, never ask a question or wait for input; end with the Recommended Next Step section after Step 4.
112
+ - Use plain, accessible language. Assume the user may be new to this codebase; provide enough context to be useful without overwhelming them with jargon.
113
+ - Do not modify any source files during this skill. It is read-only with respect to the codebase.
114
+ - If the repository has no README and minimal configuration, state this honestly and note that the exploration will rely on reading source files directly.
115
+ - Do not fabricate features or behaviors not evidenced by the code or documentation.
116
+
117
+ ## Output Format
118
+
119
+ Deliver the output in up to three phases:
120
+
121
+ **Phase 1 (Steps 1-4)**: A structured project summary presented inline, followed by the interactive feature-selection question. In non-interactive mode, the summary is followed by the Recommended Next Step section and the output ends here.
122
+
123
+ **Phase 2 (Step 5)**: A detailed feature breakdown presented inline, including files, data flow, dependencies, and improvement opportunities, followed by the development confirmation question.
124
+
125
+ **Phase 3 (Step 6, if yes)**: An implementation plan with specific files, steps, complexity estimate, and any identified risks or prerequisites.
@@ -0,0 +1,101 @@
1
+ ---
2
+ name: push-to-origin
3
+ description: Reviews uncommitted changes, excludes files that shouldn't be committed, creates a well-formed commit, and pushes to origin (in its branch, no other branch). Runs git commands directly; no helper agent is required. ALWAYS confirms with the user before pushing — never pushes silently. Triggers on any request to commit, save, check in, or push changes — e.g. "commit my changes", "check this in", "save to git", "push to origin" — even without the word "push" or a commit message.
4
+ argument-hint: <commit-message>
5
+ ---
6
+
7
+ # push-to-origin
8
+
9
+ ## Purpose
10
+
11
+ Safely and reliably bundle local code changes into a well-formed commit and push to the appropriate remote branch. This skill enforces a mandatory confirmation step before any push occurs, prevents common dangerous operations, and ensures internal or ignored files are never accidentally committed.
12
+
13
+ ## Trigger
14
+
15
+ Activate this skill when the user:
16
+ - Says "commit my changes," "save to git," "check this in," "push to origin," "push my work," or any similar phrase.
17
+ - Requests a commit even without providing a commit message; draft one from the diff if needed.
18
+ - Asks to "save" or "check in" their current work, even without explicitly mentioning git.
19
+
20
+ ## Pre-flight Checks
21
+
22
+ Before staging or committing anything, perform the following in order:
23
+
24
+ 1. Run `git status` to identify the current branch, all modified files, and any untracked files.
25
+ 2. Run `git remote -v` to confirm an `origin` remote exists. If no `origin` remote is configured, stop and tell the user. Do not proceed.
26
+ 3. Run `git diff --stat` to get a summary of the scope of changes.
27
+ 4. Check for a CI/CD configuration file (`.github/workflows/`, `Jenkinsfile`, `.gitlab-ci.yml`, `.circleci/config.yml`) to determine whether a required commit message format exists (e.g., Conventional Commits). If one is found, read it and apply the format.
28
+
29
+ ## Exclusion List
30
+
31
+ The following files and patterns must never be staged or committed, regardless of whether they appear in `git status`. If they were accidentally staged, unstage them before proceeding:
32
+
33
+ - `.geminiignore`
34
+ - `.antigravityignore`
35
+ - `GEMINI.md`
36
+ - `pr-description.md`
37
+ - Any file matching patterns defined in `.gitignore`, `.geminiignore`, or `.antigravityignore`.
38
+ - Any file path under `.agents/` or `.gemini/` that contains internal skill or configuration files.
39
+ - Personal, machine-local agent files: `CLAUDE.local.md`, `.claude/settings.local.json`, and any other `*.local.*` file inside an agent configuration folder (`.claude/`, `.cursor/`, `.gemini/`, `.agents/`).
40
+ - Any file containing secrets, credentials, or API keys (check for patterns like `*_SECRET`, `*_KEY`, `*_TOKEN` in file names or content, and flag them).
41
+
42
+ If a file on the exclusion list is staged, unstage it immediately and notify the user before continuing.
43
+
44
+ Shared agent files are not excluded. `CLAUDE.md`, `AGENTS.md`, `.claude/skills/`, `.claude/settings.json`, and `.cursor/rules/` are meant to be shared with the team, so commit them normally if they are part of the change, unless a rule above (such as a secret in the content) applies.
45
+
46
+ ## Workflow
47
+
48
+ ### Step 1: Gather and Filter
49
+ - Run `git status` to get the full list of modified and untracked files.
50
+ - Cross-reference every file against the Exclusion List above. Unstage any excluded files that are already staged.
51
+ - Present the final, filtered list of files that will be staged to the user, so they can verify the scope before committing.
52
+
53
+ ### Step 2: Draft the Commit Message
54
+ - If the user provided a commit message, check whether it complies with the format required by the CI/CD configuration (if found in Pre-flight Check 4). If it does not comply, propose a corrected version and ask the user to approve it. Do not silently rewrite it.
55
+ - If no commit message was provided, run `git diff HEAD` to read the changes and draft a message that accurately describes the intent.
56
+ - Follow Conventional Commits format if required by the project: `<type>(<scope>): <description>` (e.g., `feat(auth): add email verification step`).
57
+ - Otherwise, write a clear imperative-mood summary (e.g., "Refactor session handling to use Redis").
58
+ - Present the drafted commit message to the user and ask for explicit approval before proceeding. Do not commit without approval.
59
+
60
+ ### Step 3: Commit
61
+ - Once the commit message is approved, stage the filtered files from Step 1.
62
+ - Run `git commit -m "<approved-message>"`.
63
+ - Confirm the commit was created successfully by running `git log --oneline -1`.
64
+
65
+ ### Step 4: Mandatory Push Confirmation
66
+ Before pushing, display the following information to the user and ask for explicit confirmation:
67
+
68
+ - The target remote and branch: `origin/<branch-name>`.
69
+ - Whether this push will create a new upstream branch (if no upstream is set for the current branch).
70
+ - A brief summary of the commit being pushed (message and files affected).
71
+ - A prominent warning if the current branch is `main` or `master`.
72
+
73
+ Do not push under any circumstance until the user explicitly says yes. If the user declines, leave the commit local, inform the user their changes are committed but not pushed, and stop.
74
+
75
+ ### Step 5: Push
76
+ - If the branch has no upstream set, run `git push -u origin <branch-name>`.
77
+ - If an upstream already exists, run `git push`.
78
+ - If the push is rejected (e.g., due to a diverged history or protected branch rules), capture the exact error message, report it to the user, and ask how they would like to proceed (e.g., rebase, merge, or leave as-is). Do not attempt to auto-resolve the conflict.
79
+
80
+ ### Step 6: Report Result
81
+ - If the push succeeds, confirm the result with the remote URL and branch name.
82
+ - If the push fails, report the exact error message and stop. Do not retry automatically.
83
+
84
+ ## Rules
85
+
86
+ - Confirmation before pushing is mandatory, every single time, without exception. Never push silently.
87
+ - Never use `--force` or `--force-with-lease`. Force-pushing is prohibited.
88
+ - Never amend commits (`--amend`) or rebase history as part of this skill.
89
+ - Never push directly to `main` or `master` without the Step 4 warning being displayed and the user explicitly acknowledging it.
90
+ - Never commit or push any file from the Exclusion List.
91
+ - If a commit message format is required by the project's CI/CD configuration, propose a fix rather than silently rewriting the user's message.
92
+ - If `git remote -v` shows no `origin` remote, stop immediately and tell the user.
93
+
94
+ ## Output Format
95
+
96
+ At the end of the workflow, report:
97
+
98
+ 1. **Staged Files** — the list of files included in the commit.
99
+ 2. **Commit** — the commit hash (short) and the approved message.
100
+ 3. **Push Result** — success confirmation with remote URL and branch, or the exact error message if the push failed.
101
+ 4. **Excluded Files** — any files that were unstaged due to the Exclusion List, with a note explaining why each was excluded.
@@ -0,0 +1,84 @@
1
+ ---
2
+ name: release
3
+ description: Cut a new release from the changes recorded under [Unreleased] in CHANGELOG.md. Picks the Semantic Versioning bump, moves the changelog entries into a dated version section, syncs version files, creates the release commit and an annotated tag, pushes after confirmation, and publishes release notes. Use whenever the user asks to "make a release," "cut a release," "bump the version," "tag a new version," or "publish vX.Y.Z."
4
+ argument-hint: <version-or-bump-type>
5
+ ---
6
+
7
+ # release
8
+
9
+ ## Purpose
10
+
11
+ Turn the work already recorded in the changelog into a published, tagged release in a predictable way. The skill decides the version from what actually changed, keeps the changelog and version files consistent, and never pushes or publishes without explicit confirmation.
12
+
13
+ ## Trigger
14
+
15
+ Activate this skill when the user:
16
+ - Runs the slash command `/release`.
17
+ - Says "make a release," "cut a release," "release this," "bump the version," "tag a new version," or "publish v1.4.0."
18
+ - Passes a version (`v1.4.0`) or a bump type (`patch`, `minor`, `major`) as an argument.
19
+
20
+ ## Pre-flight Checks
21
+
22
+ Before changing anything, perform the following in order:
23
+
24
+ 1. Run `git status`. If there are uncommitted changes, stop and ask the user to commit or stash them first. A release must contain only committed work.
25
+ 2. Confirm the current branch is the release branch (`main` or `master`, or the branch named in a release guide such as `RELEASING.md` or `CONTRIBUTING.md`). If it is not, stop and tell the user.
26
+ 3. Run `git fetch origin` and compare with the upstream. If the local branch is behind, stop and ask the user to pull first.
27
+ 4. Read `CHANGELOG.md`. If it does not exist, or the `[Unreleased]` section is empty, stop and tell the user there is nothing to release.
28
+ 5. Find the latest version from `git tag --list --sort=-v:refname` and from the newest dated section in the changelog. If they disagree, report both and ask which one is correct.
29
+ 6. Look for a validation or test command (for example `scripts/validate.mjs`, `npm test`, `make test`) and run it. If it fails, stop and report the failure.
30
+ 7. List the files that carry a version number (for example `package.json`, `.claude-plugin/plugin.json`, `pyproject.toml`, `Cargo.toml`). These must be updated to the new version.
31
+
32
+ ## Workflow
33
+
34
+ ### Step 1: Choose the Version
35
+ - If the user gave an explicit version, use it, but warn if it does not match the rules below.
36
+ - Otherwise, derive the bump from the `[Unreleased]` entries using Semantic Versioning:
37
+ - **MAJOR**: any change that breaks existing usage, such as a removed or renamed skill, command, or API, a required format change, or anything listed under "Removed" or marked as breaking.
38
+ - **MINOR**: new capabilities with existing usage still working, such as anything under "Added".
39
+ - **PATCH**: only fixes, under "Fixed" or "Security", with no new capability.
40
+ - Internal-only changes (CI, tooling, docs) do not raise the bump above PATCH on their own.
41
+ - The largest change in the release decides the bump.
42
+ - Present the proposed version and the reason in one or two sentences, then ask the user to confirm.
43
+
44
+ ### Step 2: Update the Changelog and Version Files
45
+ - Insert a new `## [vX.Y.Z] - YYYY-MM-DD` heading directly under `## [Unreleased]`, so the existing entries move into the new version and `[Unreleased]` is left empty. Use today's date and match the heading style already used in the file (with or without the `v` prefix).
46
+ - Update every version file found in Pre-flight Check 7 to the new version.
47
+ - Run the validation or test command again.
48
+
49
+ ### Step 3: Commit and Tag
50
+ - Stage only the changelog and version files.
51
+ - Commit using the repository's existing release commit style, found with `git log --oneline --grep=release`. If there is none, use `release: vX.Y.Z` with a short bullet list of the main changes in the body.
52
+ - Create an annotated tag: `git tag -a vX.Y.Z -m "vX.Y.Z"`, using the same prefix style as existing tags.
53
+
54
+ ### Step 4: Mandatory Push Confirmation
55
+ Show the user:
56
+ - The commit and tag that will be pushed, and the target remote and branch.
57
+ - The release notes draft from Step 5.
58
+
59
+ Do not push until the user explicitly says yes. If the user declines, leave the commit and tag local, say so, and stop.
60
+
61
+ ### Step 5: Push and Publish
62
+ - Push the branch, then the tag: `git push origin <branch>` and `git push origin vX.Y.Z`.
63
+ - Draft release notes from the new changelog section. Match the format of previous releases (check with `gh release view <previous-tag>` if the GitHub CLI is available). End with a full changelog link comparing the previous tag to the new one.
64
+ - If the GitHub CLI is available and authenticated, publish with `gh release create vX.Y.Z --title vX.Y.Z --notes-file <file>`. Otherwise, give the user the notes to paste into their hosting platform.
65
+ - If the repository publishes packages on tag (for example an npm publish workflow), check the run with `gh run list` and report its result.
66
+
67
+ ## Rules
68
+
69
+ - Never release uncommitted work, and never release from a branch that is behind its upstream.
70
+ - Never push a commit or tag, or publish release notes, without explicit user confirmation.
71
+ - Never use `--force` on pushes or tags, and never move or delete an existing tag. If a tag already exists for the chosen version, stop and ask the user.
72
+ - Never invent changelog entries. Release notes must come only from the `[Unreleased]` section and the commits since the previous tag.
73
+ - Never skip a failing validation or test command.
74
+
75
+ ## Output Format
76
+
77
+ At the end of the workflow, report:
78
+
79
+ 1. **Version** — the new version and why that bump was chosen.
80
+ 2. **Files Updated** — the changelog and every version file changed.
81
+ 3. **Commit and Tag** — the short commit hash, message, and tag name.
82
+ 4. **Push Result** — success with remote and branch, or the exact error.
83
+ 5. **Release** — the release URL, or the notes to publish manually.
84
+ 6. **Follow-up** — the status of any publish workflow triggered by the tag.
package/src/cli.js ADDED
@@ -0,0 +1,187 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { homedir } from 'node:os';
3
+ import { dirname, join } from 'node:path';
4
+ import { createInterface } from 'node:readline/promises';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { parseArgs } from 'node:util';
7
+ import { TOOLS, TOOL_NAMES, targetDir } from './targets.js';
8
+ import { listSkills } from './skills.js';
9
+ import { installSkills, readManifest, removeSkills, skillState } from './install.js';
10
+
11
+ const pkg = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), '..', 'package.json'), 'utf8'));
12
+
13
+ const HELP = `musyskills ${pkg.version} - install AI agent skills
14
+
15
+ Usage:
16
+ musyskills list List available skills
17
+ musyskills add <skill...> [--all] Install skills
18
+ musyskills remove <skill...> Remove skills installed by musyskills
19
+ musyskills update Update installed skills to this version
20
+ musyskills doctor Show where skills are installed and their state
21
+
22
+ Options:
23
+ -t, --tool <name> claude, codex, cursor, antigravity (repeatable).
24
+ Default: detected from the project, otherwise claude.
25
+ -g, --global Install for your user instead of the current project
26
+ -a, --all With add: install every skill
27
+ -f, --force Overwrite or remove skills you edited or did not install
28
+ with musyskills
29
+ -h, --help Show this help
30
+ -v, --version Show the version
31
+
32
+ Examples:
33
+ npx musyskills add pr-draft push-to-origin
34
+ npx musyskills add --all --tool cursor
35
+ npx musyskills update --global`;
36
+
37
+ const REASONS = {
38
+ foreign: 'exists but was not installed by musyskills (use --force to overwrite)',
39
+ modified: 'was edited after install (use --force to overwrite)',
40
+ missing: 'is not installed',
41
+ };
42
+
43
+ export async function main(argv, { cwd = process.cwd(), home = process.env.MUSYSKILLS_HOME || homedir(), log = console.log, stdin = process.stdin } = {}) {
44
+ let parsed;
45
+ try {
46
+ parsed = parseArgs({
47
+ args: argv,
48
+ allowPositionals: true,
49
+ options: {
50
+ tool: { type: 'string', short: 't', multiple: true },
51
+ global: { type: 'boolean', short: 'g' },
52
+ all: { type: 'boolean', short: 'a' },
53
+ force: { type: 'boolean', short: 'f' },
54
+ help: { type: 'boolean', short: 'h' },
55
+ version: { type: 'boolean', short: 'v' },
56
+ },
57
+ });
58
+ } catch (e) {
59
+ throw new UsageError(e.message);
60
+ }
61
+ const { values: opts, positionals } = parsed;
62
+ const [command, ...args] = positionals;
63
+
64
+ if (opts.version) return log(pkg.version);
65
+ if (opts.help || !command) return log(HELP);
66
+
67
+ const skills = listSkills();
68
+ const ctx = { cwd, home, global: Boolean(opts.global) };
69
+
70
+ switch (command) {
71
+ case 'list': {
72
+ const width = Math.max(...skills.map((s) => s.name.length));
73
+ for (const s of skills) log(`${s.name.padEnd(width)} ${firstSentence(s.description)}`);
74
+ return;
75
+ }
76
+ case 'add': {
77
+ const chosen = opts.all ? skills : pickSkills(skills, args);
78
+ if (chosen.length === 0) throw new UsageError('Name at least one skill, or use --all. Run "musyskills list" to see them.');
79
+ const tools = await resolveTools(opts.tool, ctx, { log, stdin });
80
+ for (const dir of uniqueDirs(tools, ctx)) {
81
+ report(log, dir, installSkills(dir.path, chosen, { version: pkg.version, force: opts.force }));
82
+ }
83
+ return;
84
+ }
85
+ case 'remove': {
86
+ if (args.length === 0) throw new UsageError('Name at least one skill to remove.');
87
+ const tools = await resolveTools(opts.tool, ctx, { log, stdin });
88
+ for (const dir of uniqueDirs(tools, ctx)) {
89
+ report(log, dir, removeSkills(dir.path, args, { force: opts.force }));
90
+ }
91
+ return;
92
+ }
93
+ case 'update': {
94
+ const tools = opts.tool ? validateTools(opts.tool) : TOOL_NAMES;
95
+ let any = false;
96
+ for (const dir of uniqueDirs(tools, ctx)) {
97
+ const installed = Object.keys(readManifest(dir.path).skills);
98
+ if (installed.length === 0) continue;
99
+ any = true;
100
+ const chosen = skills.filter((s) => installed.includes(s.name));
101
+ report(log, dir, installSkills(dir.path, chosen, { version: pkg.version, force: opts.force }));
102
+ }
103
+ if (!any) log('No skills installed by musyskills were found. Use "musyskills add" first.');
104
+ return;
105
+ }
106
+ case 'doctor': {
107
+ log(`musyskills ${pkg.version} (${ctx.global ? 'global' : 'project'}: ${ctx.global ? home : cwd})`);
108
+ const detected = detectTools(ctx);
109
+ log(`Detected tools: ${detected.length ? detected.join(', ') : 'none'}`);
110
+ for (const dir of uniqueDirs(TOOL_NAMES, ctx)) {
111
+ if (!existsSync(dir.path)) continue;
112
+ const manifest = readManifest(dir.path);
113
+ const rows = skills
114
+ .map((s) => [s.name, skillState(dir.path, s, manifest)])
115
+ .filter(([, state]) => state !== 'missing');
116
+ if (rows.length === 0) continue;
117
+ log(`\n${dir.path} (${dir.tools.join(', ')})`);
118
+ for (const [name, state] of rows) log(` ${name}: ${state}`);
119
+ }
120
+ return;
121
+ }
122
+ default:
123
+ throw new UsageError(`Unknown command "${command}". Run "musyskills --help".`);
124
+ }
125
+ }
126
+
127
+ export class UsageError extends Error {}
128
+
129
+ function firstSentence(text) {
130
+ const s = text.split(/(?<=\.)\s/)[0];
131
+ return s.length > 90 ? s.slice(0, 87) + '...' : s;
132
+ }
133
+
134
+ function pickSkills(skills, names) {
135
+ const byName = new Map(skills.map((s) => [s.name, s]));
136
+ const unknown = names.filter((n) => !byName.has(n));
137
+ if (unknown.length) throw new UsageError(`Unknown skill: ${unknown.join(', ')}. Run "musyskills list" to see them.`);
138
+ return [...new Set(names)].map((n) => byName.get(n));
139
+ }
140
+
141
+ function validateTools(tools) {
142
+ const list = tools.flatMap((t) => t.split(',')).map((t) => t.trim().toLowerCase()).filter(Boolean);
143
+ const unknown = list.filter((t) => !TOOLS[t]);
144
+ if (unknown.length) throw new UsageError(`Unknown tool: ${unknown.join(', ')}. Use one of: ${TOOL_NAMES.join(', ')}.`);
145
+ return [...new Set(list)];
146
+ }
147
+
148
+ export function detectTools({ cwd, home, global }) {
149
+ const base = global ? home : cwd;
150
+ return TOOL_NAMES.filter((t) => TOOLS[t].markers.some((m) => existsSync(join(base, m))));
151
+ }
152
+
153
+ async function resolveTools(flag, ctx, { log, stdin }) {
154
+ if (flag) return validateTools(flag);
155
+ const detected = detectTools(ctx);
156
+ if (detected.length) {
157
+ log(`Detected: ${detected.join(', ')}`);
158
+ return detected;
159
+ }
160
+ if (stdin.isTTY) {
161
+ const rl = createInterface({ input: stdin, output: process.stdout });
162
+ const answer = await rl.question(`No agent tool detected. Install for which tool? (${TOOL_NAMES.join('/')}) [claude] `);
163
+ rl.close();
164
+ return validateTools([answer.trim() || 'claude']);
165
+ }
166
+ log('No agent tool detected; installing for claude. Use --tool to choose another.');
167
+ return ['claude'];
168
+ }
169
+
170
+ // Several tools can share one folder (codex and antigravity both use
171
+ // .agents/skills in a project), so install there once.
172
+ function uniqueDirs(tools, ctx) {
173
+ const dirs = new Map();
174
+ for (const tool of tools) {
175
+ const path = targetDir(tool, ctx);
176
+ if (!dirs.has(path)) dirs.set(path, { path, tools: [] });
177
+ dirs.get(path).tools.push(tool);
178
+ }
179
+ return [...dirs.values()];
180
+ }
181
+
182
+ function report(log, dir, results) {
183
+ log(`\n${dir.path} (${dir.tools.join(', ')})`);
184
+ for (const r of results) {
185
+ log(r.action === 'skipped' ? ` skipped ${r.name}: ${REASONS[r.reason]}` : ` ${r.action} ${r.name}`);
186
+ }
187
+ }
package/src/install.js ADDED
@@ -0,0 +1,91 @@
1
+ import { cpSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { hashDir } from './skills.js';
4
+
5
+ export const MANIFEST = '.musyskills.json';
6
+
7
+ export function readManifest(dir) {
8
+ const file = join(dir, MANIFEST);
9
+ if (!existsSync(file)) return { skills: {} };
10
+ try {
11
+ const data = JSON.parse(readFileSync(file, 'utf8'));
12
+ return { skills: {}, ...data };
13
+ } catch {
14
+ throw new Error(`${file} is not valid JSON. Fix or delete it, then retry.`);
15
+ }
16
+ }
17
+
18
+ function writeManifest(dir, manifest) {
19
+ const names = Object.keys(manifest.skills);
20
+ const file = join(dir, MANIFEST);
21
+ if (names.length === 0) {
22
+ rmSync(file, { force: true });
23
+ return;
24
+ }
25
+ writeFileSync(file, JSON.stringify(manifest, null, 2) + '\n');
26
+ }
27
+
28
+ // State of one skill in a target folder:
29
+ // missing not on disk
30
+ // foreign on disk but not installed by musyskills
31
+ // modified installed by musyskills, edited since
32
+ // outdated installed by musyskills, unchanged, newer version available
33
+ // current installed by musyskills, same as the bundled copy
34
+ export function skillState(dir, skill, manifest) {
35
+ const dest = join(dir, skill.name);
36
+ if (!existsSync(dest)) return 'missing';
37
+ const entry = manifest.skills[skill.name];
38
+ if (!entry) return 'foreign';
39
+ const onDisk = hashDir(dest);
40
+ if (onDisk !== entry.hash) return 'modified';
41
+ return onDisk === hashDir(skill.path) ? 'current' : 'outdated';
42
+ }
43
+
44
+ // Installs or updates skills in one target folder. Returns one result per skill.
45
+ export function installSkills(dir, skills, { version, force = false } = {}) {
46
+ mkdirSync(dir, { recursive: true });
47
+ const manifest = readManifest(dir);
48
+ const results = [];
49
+ for (const skill of skills) {
50
+ const state = skillState(dir, skill, manifest);
51
+ if ((state === 'foreign' || state === 'modified') && !force) {
52
+ results.push({ name: skill.name, action: 'skipped', reason: state });
53
+ continue;
54
+ }
55
+ if (state === 'current') {
56
+ results.push({ name: skill.name, action: 'unchanged' });
57
+ continue;
58
+ }
59
+ const dest = join(dir, skill.name);
60
+ rmSync(dest, { recursive: true, force: true });
61
+ cpSync(skill.path, dest, { recursive: true });
62
+ manifest.skills[skill.name] = { version, hash: hashDir(dest) };
63
+ results.push({ name: skill.name, action: state === 'missing' ? 'installed' : 'updated' });
64
+ }
65
+ manifest.version = version;
66
+ writeManifest(dir, manifest);
67
+ return results;
68
+ }
69
+
70
+ export function removeSkills(dir, names, { force = false } = {}) {
71
+ const manifest = readManifest(dir);
72
+ const results = [];
73
+ for (const name of names) {
74
+ const entry = manifest.skills[name];
75
+ const dest = join(dir, name);
76
+ if (!entry) {
77
+ const reason = existsSync(dest) ? 'foreign' : 'missing';
78
+ results.push({ name, action: 'skipped', reason });
79
+ continue;
80
+ }
81
+ if (existsSync(dest) && hashDir(dest) !== entry.hash && !force) {
82
+ results.push({ name, action: 'skipped', reason: 'modified' });
83
+ continue;
84
+ }
85
+ rmSync(dest, { recursive: true, force: true });
86
+ delete manifest.skills[name];
87
+ results.push({ name, action: 'removed' });
88
+ }
89
+ writeManifest(dir, manifest);
90
+ return results;
91
+ }
package/src/skills.js ADDED
@@ -0,0 +1,58 @@
1
+ import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
2
+ import { createHash } from 'node:crypto';
3
+ import { dirname, join, relative } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+
6
+ const here = dirname(fileURLToPath(import.meta.url));
7
+
8
+ // Published package: skills are bundled next to src/. Inside the repo (tests,
9
+ // local runs) they are read straight from the top-level skills/ folder.
10
+ export function bundledSkillsDir() {
11
+ const bundled = join(here, '..', 'skills');
12
+ if (existsSync(bundled)) return bundled;
13
+ return join(here, '..', '..', '..', 'skills');
14
+ }
15
+
16
+ export function parseFrontmatter(text) {
17
+ const match = text.replace(/\r\n/g, '\n').match(/^---\n([\s\S]*?)\n---\n/);
18
+ if (!match) return null;
19
+ const fields = {};
20
+ for (const line of match[1].split('\n')) {
21
+ const kv = line.match(/^([\w-]+):\s*(.*)$/);
22
+ if (kv) fields[kv[1]] = kv[2].trim();
23
+ }
24
+ return fields;
25
+ }
26
+
27
+ export function listSkills(dir = bundledSkillsDir()) {
28
+ return readdirSync(dir)
29
+ .filter((name) => existsSync(join(dir, name, 'SKILL.md')))
30
+ .sort()
31
+ .map((name) => {
32
+ const fm = parseFrontmatter(readFileSync(join(dir, name, 'SKILL.md'), 'utf8')) ?? {};
33
+ return { name, description: fm.description ?? '', path: join(dir, name) };
34
+ });
35
+ }
36
+
37
+ function walk(dir) {
38
+ const out = [];
39
+ for (const entry of readdirSync(dir).sort()) {
40
+ const full = join(dir, entry);
41
+ if (statSync(full).isDirectory()) out.push(...walk(full));
42
+ else out.push(full);
43
+ }
44
+ return out;
45
+ }
46
+
47
+ // Hash of every file in a skill folder. Line endings are normalized so a
48
+ // checkout with CRLF does not look "modified".
49
+ export function hashDir(dir) {
50
+ const h = createHash('sha256');
51
+ for (const file of walk(dir)) {
52
+ h.update(relative(dir, file).split('\\').join('/'));
53
+ h.update('\0');
54
+ h.update(readFileSync(file, 'utf8').replace(/\r\n/g, '\n'));
55
+ h.update('\0');
56
+ }
57
+ return h.digest('hex');
58
+ }
package/src/targets.js ADDED
@@ -0,0 +1,38 @@
1
+ import { join } from 'node:path';
2
+
3
+ // Where each tool loads skills from. Sources:
4
+ // claude https://code.claude.com/docs/en/skills
5
+ // codex https://developers.openai.com/codex/skills (REPO and USER scopes)
6
+ // cursor https://cursor.com/docs/skills
7
+ // antigravity https://codelabs.developers.google.com/getting-started-with-antigravity-skills
8
+ // `markers` are paths that suggest the tool is in use, checked in the project
9
+ // directory (or the home directory with --global).
10
+ export const TOOLS = {
11
+ claude: {
12
+ project: '.claude/skills',
13
+ global: '.claude/skills',
14
+ markers: ['.claude', 'CLAUDE.md'],
15
+ },
16
+ codex: {
17
+ project: '.agents/skills',
18
+ global: '.agents/skills',
19
+ markers: ['.codex', 'AGENTS.md'],
20
+ },
21
+ cursor: {
22
+ project: '.cursor/skills',
23
+ global: '.cursor/skills',
24
+ markers: ['.cursor', '.cursorrules'],
25
+ },
26
+ antigravity: {
27
+ project: '.agents/skills',
28
+ global: '.gemini/config/skills',
29
+ markers: ['.gemini', 'GEMINI.md'],
30
+ },
31
+ };
32
+
33
+ export const TOOL_NAMES = Object.keys(TOOLS);
34
+
35
+ export function targetDir(tool, { global, cwd, home }) {
36
+ const t = TOOLS[tool];
37
+ return global ? join(home, t.global) : join(cwd, t.project);
38
+ }