Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions .cli-skill-install-state.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
{
"version": 1,
"files": {
"cli-skill/SKILL.md": {
"sourceHash": "571493ef1dd510d7b2c5efa388ab81805ca1bfb839b278554ac0e2d6028b11c8",
"installedHash": "571493ef1dd510d7b2c5efa388ab81805ca1bfb839b278554ac0e2d6028b11c8"
},
"cli-skill/adapters/README.md": {
"sourceHash": "9a52f0a729dd8c2f054f4e462f1d4de9a0666d123a6161b82d7f87776f2c7dd2",
"installedHash": "9a52f0a729dd8c2f054f4e462f1d4de9a0666d123a6161b82d7f87776f2c7dd2"
},
"cli-skill/adapters/claude-code/commands.yaml": {
"sourceHash": "10d1554e5d74376db1080eb82b1f6d4f296b268908f1684001e3d323051bd9f3",
"installedHash": "10d1554e5d74376db1080eb82b1f6d4f296b268908f1684001e3d323051bd9f3"
},
"cli-skill/adapters/copilot/SKILL.md": {
"sourceHash": "30314e5ce0f67887a47a7f36fd51bb52defcd1bcb45aadd6e9c4479ea5f402ac",
"installedHash": "30314e5ce0f67887a47a7f36fd51bb52defcd1bcb45aadd6e9c4479ea5f402ac"
},
"cli-skill/adapters/opencode/commands.json": {
"sourceHash": "d86ba471e92338ddaddd4c69558c78e6ad3594754bed8bfb2948aec88462c207",
"installedHash": "d86ba471e92338ddaddd4c69558c78e6ad3594754bed8bfb2948aec88462c207"
},
"cli-skill/adapters/pi-coding-agent/SKILL.md": {
"sourceHash": "770f9f095f7fd00913ab21326fc71f6a69b2363be0f5ea5db9fbf46fd0507628",
"installedHash": "770f9f095f7fd00913ab21326fc71f6a69b2363be0f5ea5db9fbf46fd0507628"
},
"cli-skill/commands/cli-behavioral-analysis.md": {
"sourceHash": "9c6545d9fd1cf9e8e42d797a9906f18e2895cc0b934b12c94da64643ff83dcc1",
"installedHash": "9c6545d9fd1cf9e8e42d797a9906f18e2895cc0b934b12c94da64643ff83dcc1"
},
"cli-skill/commands/cli-check-help.md": {
"sourceHash": "16e36e23668ecdf0e12600092218574199ffbccb80179d4bdb05dcecaa5c9b4d",
"installedHash": "16e36e23668ecdf0e12600092218574199ffbccb80179d4bdb05dcecaa5c9b4d"
},
"cli-skill/commands/cli-heuristic-analysis.md": {
"sourceHash": "9df2fb0997e5a6160b0c93920cf6ab8868469f84d6f5a701d9036cc9f191c748",
"installedHash": "9df2fb0997e5a6160b0c93920cf6ab8868469f84d6f5a701d9036cc9f191c748"
},
"cli-skill/commands/cli-review.md": {
"sourceHash": "4ba55617d0bb026fc0d4d74b5bd12ba93a591477026e13da48223a2d44fdf886",
"installedHash": "4ba55617d0bb026fc0d4d74b5bd12ba93a591477026e13da48223a2d44fdf886"
},
"cli-skill/commands/cli-semantic-analysis.md": {
"sourceHash": "d5ff5569ee41b777686c23fb3ae294b26f6583a12b6b1efbc8a6ae931eee52a6",
"installedHash": "d5ff5569ee41b777686c23fb3ae294b26f6583a12b6b1efbc8a6ae931eee52a6"
},
"cli-skill/commands/install-cli-pr-workflow.md": {
"sourceHash": "49b1c6c837a158f9690257cc6dbdbfe65382f628cf6f936d0ceb8d9a7d5c2ebf",
"installedHash": "49b1c6c837a158f9690257cc6dbdbfe65382f628cf6f936d0ceb8d9a7d5c2ebf"
},
"cli-skill/future-commands/cli-propose-command.md": {
"sourceHash": "2cda4adabb1ad05d9113c357c202248636d6223f32c830a0ec275728bca5e461",
"installedHash": "2cda4adabb1ad05d9113c357c202248636d6223f32c830a0ec275728bca5e461"
},
"cli-skill/future-commands/cli-rename-command.md": {
"sourceHash": "653b62a22fceb60fd8ca090fcf713d4d93eb554650817ec132c9e01081a8b9b1",
"installedHash": "653b62a22fceb60fd8ca090fcf713d4d93eb554650817ec132c9e01081a8b9b1"
},
"cli-skill/references/cli-help-examples.md": {
"sourceHash": "e4080251c73bd30734de33c1f31fb69d5be0569fb63043e32fd75aeeae93ef7d",
"installedHash": "e4080251c73bd30734de33c1f31fb69d5be0569fb63043e32fd75aeeae93ef7d"
},
"cli-skill/references/cli-help.md": {
"sourceHash": "50765456253ceb63c3cd80bdcd63bd29c02644c3190cb149defc1892e5c24ad5",
"installedHash": "50765456253ceb63c3cd80bdcd63bd29c02644c3190cb149defc1892e5c24ad5"
},
"cli-skill/references/cli-review-output-format.md": {
"sourceHash": "5ca3b52870c04341d6b9240c2f28edd1753ab33d8eba87ef247cb0b1492b0d10",
"installedHash": "5ca3b52870c04341d6b9240c2f28edd1753ab33d8eba87ef247cb0b1492b0d10"
},
"cli-skill/references/cli-skill-review-pr.yml": {
"sourceHash": "f9bf075bdae3239fce0da1a558d766932a0d0a206573ab2283c291787d07f0ac",
"installedHash": "f9bf075bdae3239fce0da1a558d766932a0d0a206573ab2283c291787d07f0ac"
},
"cli-skill/references/cli-standard.md": {
"sourceHash": "10f617f80610490d8c4a9795fbfbf5f1d4e7aac74f8da79d6db1c994a3c926d4",
"installedHash": "10f617f80610490d8c4a9795fbfbf5f1d4e7aac74f8da79d6db1c994a3c926d4"
},
"cli-skill/references/deprecation.md": {
"sourceHash": "cb47534e93c4daf78a621ba9754f214e82f2e8975d895b3f0029727417a13a4e",
"installedHash": "cb47534e93c4daf78a621ba9754f214e82f2e8975d895b3f0029727417a13a4e"
},
"cli-skill/schemas/commands.manifest.yaml": {
"sourceHash": "957b98b156ce1187ea932293b4a636c5d4d891bf3cafe5517780c66a21dbc803",
"installedHash": "957b98b156ce1187ea932293b4a636c5d4d891bf3cafe5517780c66a21dbc803"
},
"cli-skill/shared/cli-discovery-preflight.md": {
"sourceHash": "cb50539228b6d99cd859d81efcc75bb2823c3438c865b75479f65671757e7ee3",
"installedHash": "cb50539228b6d99cd859d81efcc75bb2823c3438c865b75479f65671757e7ee3"
},
".pi/skills/cli-skill/SKILL.md": {
"sourceHash": "dce5fc40f9861cc42b4cfdeaf53d9aea0219b851b9b3dd7d4ec65df4c9161b64",
"installedHash": "dce5fc40f9861cc42b4cfdeaf53d9aea0219b851b9b3dd7d4ec65df4c9161b64"
}
}
}
40 changes: 12 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,18 @@

cli-skill is a command based, cross agent CLI review framework. It uses one canonical command set and thin adapters so the same workflows can run in Copilot, Claude Code, Pi Coding Agent, and OpenCode.

## Install via npm

This repository is also packaged as `canonical-cli-skill` for consumers that want to install the skill files into their own repo.

```bash
npx canonical-cli-skill install
```

By default, the installer resolves the target directory to the top-level of the current Git repository, so generated paths are anchored at the repo root even when you run it from a subdirectory. If there is no Git repository, it falls back to the current directory. Use `--target <path>` to override this behavior.

Auto-detection is based on repository markers for the supported agents. Existing unmanaged files are not overwritten unless `--force` is used, and managed files are only updated when they have not been edited since the last install.

## Project Structure

- Canonical skill index: [cli-skill/SKILL.md](cli-skill/SKILL.md)
Expand All @@ -22,34 +34,6 @@ Future scaffolds:
- [cli-skill/future-commands/cli-propose-command.md](cli-skill/future-commands/cli-propose-command.md)
- [cli-skill/future-commands/cli-rename-command.md](cli-skill/future-commands/cli-rename-command.md)

## Use with Different Agents

1. Sync adapters from the manifest (single maintained helper script):

node scripts/sync-cli-skill-adapters.js

2. Copilot (GitHub skills path):

- Entry point: [.github/skills/cli-skill/SKILL.md](.github/skills/cli-skill/SKILL.md)
- Adapter file: [cli-skill/adapters/copilot/SKILL.md](cli-skill/adapters/copilot/SKILL.md)

3. Pi Coding Agent:

- Entry point: [.pi/skills/cli-skill/SKILL.md](.pi/skills/cli-skill/SKILL.md)
- Adapter file: [cli-skill/adapters/pi-coding-agent/SKILL.md](cli-skill/adapters/pi-coding-agent/SKILL.md)

4. Claude Code:

- Adapter file: [cli-skill/adapters/claude-code/commands.yaml](cli-skill/adapters/claude-code/commands.yaml)

5. OpenCode:

- Adapter file: [cli-skill/adapters/opencode/commands.json](cli-skill/adapters/opencode/commands.json)

6. Adapter docs:

- [cli-skill/adapters/README.md](cli-skill/adapters/README.md)

## Quick Start for GitHub Action: cli-skill-build

Use the packaged workflow at [.github/workflows/cli-skill-build.yml](.github/workflows/cli-skill-build.yml).
Expand Down
9 changes: 4 additions & 5 deletions cli-skill/commands/cli-review.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ CLI standard compliance review only.
- Findings must map to explicit rules from the standard
- Non-compliance and compliant evidence based on observed CLI behavior/docs/code
- Use these rules to determine severity. Severity can only be [High|Medium|Low|Unrated]:
* High: violations of command structure and naming (DO NOT APPLY SHOULD RULES), use of positional parameters, accessibility/color violations
* High: violations of command structure and naming (SHOULD RULES DO NOT COUNT), use of positional parameters, accessibility/color violations
* Medium: use if non-standard verbs for commands, inconsistent flag names or usage, extremely high complexity (eg. created by >20 commands)
* Low: formatting violations, duplicate short/long flags
* Unrated: use if no standard rule applies, or if the finding is not certain, there is a SHOULD rule, or the rule applies to a debug/secret command
- All SHOULD rules result in unrated violations - report them, but don't include them in the scoring.
- All SHOULD rules must be unrated violations - report them, but don't include them in the scoring. This can be a use of non-standard verbs, or in cases where the standard says "you should", or "prefer".

## Out Of Scope

Expand Down Expand Up @@ -71,10 +71,9 @@ To calculate the score:
1. Create a JSON table with structure: `{"commands": <int>, "issues": [{"severity": "High|Medium|Low|Unrated", "category": <str>, "message": <str>}, ...]}`
2. Execute: `python3 <resolved_script_path> <json_file>` using the path resolution defined in `Execution Order`
3. This script returns JSON with `score` (0-100), `passed` (boolean), `rating badge`, and severity counts
4. Use this score and rating in the summary section of the markdown output
5. Use the rating badge in the summary section of the markdown output
4. Use this `score` and `rating badge` in the summary section of the markdown output

The script implements the standard algorithm: Start with 100%, weight W=100/#commands. For each High violation, reduce by 2*W; Medium violation by 1*W; Low violation by 0.5*W. Clamp to 0-100%.
The script implements the standard algorithm: Start with 100%, weight W=100/#commands. For each High violation, reduce by W; Medium violation by 0.5*W; Low violation by 0.2*W. Clamp to 0-100%.

### CLI Change Requirements
Analyze the files that have been changes as part of this PR. Create a detailed summary of how each change affects the compliance of the CLI.
Expand Down
2 changes: 1 addition & 1 deletion cli-skill/references/cli-review-output-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
| Unrated | <# unrated> | <main categories for unrated issues> |
| **Total** | **<# total>** | |

**Overall rating:** <rating badge>
**Overall rating:** <score> <rating badge>
> The scoring algorithm starts with 100%, number of commands N, weight W=100/N. For each High violation, reduce by 2*W; Medium violation by 1*W; Low violation by 0.5*W. Clamp to 0-100.

---
Expand Down
32 changes: 32 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 36 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "canonical-cli-skill",
"version": "0.1.0",
"description": "Cross-agent CLI review skill installer for Copilot, Pi, Claude Code, and OpenCode.",
"license": "MIT",
"type": "commonjs",
"bin": {
"canonical-cli-skill": "scripts/cli.js"
},
"scripts": {
"postinstall": "node scripts/cli.js install --postinstall",
"install:skill": "node scripts/cli.js install",
"install:skill:dry-run": "node scripts/cli.js install --dry-run"
},
"files": [
"scripts/cli.js",
"cli-skill",
".github/skills/cli-skill/SKILL.md",
".pi/skills/cli-skill/SKILL.md",
"README.md"
],
"keywords": [
"cli",
"skill",
"copilot",
"pi",
"claude",
"opencode"
],
"engines": {
"node": ">=18"
},
"dependencies": {
"commander": "15.0.0"
}
}
8 changes: 4 additions & 4 deletions scripts/calculate_cli_score.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,15 @@ def calculate_score(issues_data: dict) -> dict:
medium_count = sum(1 for issue in issues if issue.get("severity") == "Medium")
low_count = sum(1 for issue in issues if issue.get("severity") == "Low")

# Calculate score: W = 100/N, High: -2W, Medium: -1W, Low: -0.5W
# Calculate score: W = 100/N, High: -W, Medium: -0.5W, Low: -0.2W
if num_commands == 0:
score = 100.0
else:
weight = 100.0 / num_commands
score = 100.0
score -= high_count * 2 * weight
score -= medium_count * 1 * weight
score -= low_count * 0.5 * weight
score -= high_count * weight
score -= medium_count * 0.5 * weight
score -= low_count * 0.2 * weight

score = max(0.0, min(100.0, score)) # Clamp to 0-100

Expand Down
Loading