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
20 changes: 20 additions & 0 deletions .agents/plugins/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "agent-scripts",
"interface": {
"displayName": "Agent Scripts"
},
"plugins": [
{
"name": "agent-scripts",
"source": {
"source": "local",
"path": "./"
},
"policy": {
"installation": "AVAILABLE",
"authentication": "ON_INSTALL"
},
"category": "Developer Tools"
}
]
}
16 changes: 16 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "agent-scripts",
"owner": {
"name": "shaug"
},
"metadata": {
"description": "Install the complete agent-scripts skill suite as one dependency-closed plugin."
},
"plugins": [
{
"name": "agent-scripts",
"source": "./",
"description": "Implementation, code-review, PR-lifecycle, and changeset workflows that install and run together."
}
]
}
17 changes: 17 additions & 0 deletions .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "agent-scripts",
"version": "0.1.0",
"description": "Install the complete agent-scripts implementation, review, PR-lifecycle, and changeset skill suite.",
"author": {
"name": "shaug"
},
"homepage": "https://github.com/shaug/agent-scripts",
"repository": "https://github.com/shaug/agent-scripts",
"keywords": [
"agent-skills",
"code-review",
"github",
"pull-requests"
],
"skills": "./skills/"
}
35 changes: 35 additions & 0 deletions .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "agent-scripts",
"version": "0.1.0",
"description": "Install the complete agent-scripts implementation, review, PR-lifecycle, and changeset skill suite.",
"author": {
"name": "shaug",
"url": "https://github.com/shaug"
},
"homepage": "https://github.com/shaug/agent-scripts",
"repository": "https://github.com/shaug/agent-scripts",
"keywords": [
"agent-skills",
"code-review",
"github",
"pull-requests"
],
"skills": "./skills/",
"interface": {
"displayName": "Agent Scripts",
"shortDescription": "Implementation and review workflows",
"longDescription": "Install the dependency-closed suite for ticket and epic implementation, code review, PR babysitting, and changeset carving.",
"developerName": "shaug",
"category": "Developer Tools",
"capabilities": [
"Read",
"Write"
],
"websiteURL": "https://github.com/shaug/agent-scripts",
"defaultPrompt": [
"Implement one ticket through review and merge.",
"Review this code change with the full suite.",
"Babysit this pull request until it is ready."
]
}
}
7 changes: 5 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,19 @@ jobs:
fi
done

- name: Validate plugin packaging
run: python scripts/validate_plugins.py

- name: Run unit tests
run: |
found=0
for tests in skills/*/scripts/tests review-suite/scripts/tests; do
for tests in scripts/tests skills/*/scripts/tests review-suite/scripts/tests; do
if [ -d "$tests" ]; then
found=1
echo "Running tests in $tests"
python -m unittest discover -s "$tests" -p 'test_*.py'
fi
done
if [ "$found" -eq 0 ]; then
echo "No tests found under skills/*/scripts/tests or review-suite/scripts/tests"
echo "No tests found under scripts/tests, skills/*/scripts/tests, or review-suite/scripts/tests"
fi
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ summary: Chronological history of repository and skill changes.

## 2026-07-21 — Completed carve-changesets and integrated ticket publication

- feat: package the workflow suite as a plugin
- fix: fail closed on invalid carved handoffs
(`dc4f5c1f3e33c25ad6258f7365506bd33255ed82`)
- feat: integrate carved ticket publication
(`54c67f7cd7ace3269eee4fe628f974b090a4d699`)
- refactor: derive the eval action vocabulary from expectations
Expand Down
49 changes: 49 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,55 @@

A personal monorepo for agent skills and supporting scripts.

## Installation

Install the plugin when you need any composed workflow. It packages all eight
skills together so stable-name dependencies such as `implement-ticket`,
`review-code-change`, and `babysit-pr` are available in the same fresh session.

### Claude Code

Add the repository marketplace, install the plugin, and start a fresh session:

```text
/plugin marketplace add shaug/agent-scripts
/plugin install agent-scripts@agent-scripts
```

The equivalent non-interactive commands are:

```bash
claude plugin marketplace add shaug/agent-scripts
claude plugin install agent-scripts@agent-scripts
```

### Codex

Codex CLI 0.117 or newer can add the repository marketplace and install the same
plugin:

```bash
codex plugin marketplace add shaug/agent-scripts
codex plugin add agent-scripts@agent-scripts
```

The repository marketplace also appears in the Codex plugin browser. Start a
fresh Codex task after installation so the complete skill set is loaded.

### Individual skills

Standalone-capable skills can still be installed independently:

```bash
npx skills add shaug/agent-scripts
```

Codex users can also invoke `$skill-installer` with this repository. Prefer the
plugin for `implement-epic`, `implement-ticket`, `babysit-pr`,
`review-code-change`, or `carve-changesets`: installing one of those entrypoints
alone intentionally leaves required stable-name dependencies unavailable and
causes the workflow to fail closed.

## Repository Layout

- `skills/` — skill folders, each containing a `SKILL.md` and bundled resources
Expand Down
10 changes: 8 additions & 2 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ sync-contracts:
echo "Synced $dest"; \
done

test:
test: test-plugins
@found=0; \
for tests in {{skills_dir}}/*/scripts/tests; do \
if [ -d "$tests" ]; then \
Expand All @@ -41,6 +41,9 @@ test:
test-review-suite:
python3 -m unittest discover -s review-suite/scripts/tests -p 'test_*.py'

test-plugins:
python3 -m unittest discover -s scripts/tests -p 'test_*.py'

test-babysit-pr:
python3 -m unittest discover -s {{skills_dir}}/babysit-pr/scripts/tests -p 'test_*.py'

Expand Down Expand Up @@ -71,6 +74,9 @@ eval-carve-changesets-executor executor:

validate-skills: lint-skills

validate-plugins:
python3 scripts/validate_plugins.py

fmt-py:
@if command -v ruff >/dev/null 2>&1; then \
ruff check --select I,RUF022 --fix {{py_targets}}; \
Expand Down Expand Up @@ -150,7 +156,7 @@ lint-skills:
fi; \
done

lint: lint-py lint-md lint-skills
lint: lint-py lint-md lint-skills validate-plugins

format: fmt-py fmt-md

Expand Down
55 changes: 55 additions & 0 deletions scripts/tests/test_validate_plugins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from __future__ import annotations

import importlib.util
import json
import shutil
import tempfile
import unittest
from pathlib import Path

REPOSITORY_ROOT = Path(__file__).resolve().parents[2]
SPEC = importlib.util.spec_from_file_location(
"validate_plugins", REPOSITORY_ROOT / "scripts" / "validate_plugins.py"
)
assert SPEC is not None and SPEC.loader is not None
validate_plugins = importlib.util.module_from_spec(SPEC)
SPEC.loader.exec_module(validate_plugins)


class ValidatePluginsTests(unittest.TestCase):
def copy_fixture(self, destination: Path) -> None:
for name in (".agents", ".claude-plugin", ".codex-plugin", "skills"):
shutil.copytree(REPOSITORY_ROOT / name, destination / name)

def test_repository_plugin_package_is_complete(self) -> None:
validate_plugins.validate(REPOSITORY_ROOT)

def test_manifest_versions_must_match(self) -> None:
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
self.copy_fixture(root)
manifest_path = root / ".codex-plugin" / "plugin.json"
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
manifest["version"] = "0.2.0"
manifest_path.write_text(json.dumps(manifest), encoding="utf-8")

with self.assertRaisesRegex(
validate_plugins.PluginValidationError, "versions must match"
):
validate_plugins.validate(root)

def test_required_bundled_resource_cannot_disappear(self) -> None:
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
self.copy_fixture(root)
watcher = root / "skills" / "babysit-pr" / "scripts" / "gh_pr_watch.py"
watcher.unlink()

with self.assertRaisesRegex(
validate_plugins.PluginValidationError, "missing the babysit-pr watcher"
):
validate_plugins.validate(root)


if __name__ == "__main__":
unittest.main()
Loading
Loading