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
19 changes: 19 additions & 0 deletions .agents/plugins/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "llama-cpp-local",
"interface": {
"displayName": "llama.cpp local plugins"
},
"plugins": [
{
"name": "ponytail",
"source": {
"source": "local",
"path": "./third_party/ponytail"
},
"category": "Productivity",
"policy": {
"installation": "AVAILABLE"
}
}
]
}
6 changes: 6 additions & 0 deletions .agents/skills/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,9 @@ The lock file generated by the updater becomes the ongoing record of installed c
## Repository setup

After installing or materially updating the bundle, run `/setup-matt-pocock-skills` when repository-specific tracker, triage-label, or documentation configuration needs to be initialized or refreshed.

## Ponytail

Ponytail is **not** part of this vendored skill directory. It is installed as the official Codex plugin because its standard behavior depends on lifecycle hooks and runtime mode state, not only its six skills. See [docs/agents/ponytail.md](../../docs/agents/ponytail.md).

Do not add Ponytail skill names to the Matt Pocock update allowlist; that would create duplicate skill installations.
118 changes: 118 additions & 0 deletions docs/agents/ponytail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# Ponytail integration

This repository carries a reviewable copy of the **official Ponytail Codex plugin**
from [DietrichGebert/ponytail](https://github.com/DietrichGebert/ponytail).

The canonical project copy lives at:

`third_party/ponytail/`

Codex sees it through the repository marketplace:

`.agents/plugins/marketplace.json`

This keeps Ponytail's standard architecture intact while making the exact hooks and
skills used by this project part of the repository history.

## What is vendored

The project copy includes Ponytail's Codex runtime payload:

- native `.codex-plugin/plugin.json`
- lifecycle hooks
- all six Ponytail skills
- package metadata
- upstream `AGENTS.md`
- MIT license
- uninstall helper
- upstream logo asset

The executable hook and skill files are copied from upstream unchanged.

There is one packaging-only difference: the local manifest points its cosmetic icon
fields at Ponytail's upstream `assets/logo-dark.svg` instead of the much larger PNG.
This does not change Ponytail behavior.

The exact upstream commit is recorded in:

`third_party/ponytail/UPSTREAM_REVISION`

## Install

Windows:

```powershell
./scripts/setup-ponytail.ps1
```

POSIX:

```bash
./scripts/setup-ponytail.sh
```

The setup registers this repository as a local Codex marketplace when needed and
installs:

`ponytail@llama-cpp-local`

Codex supports repository marketplaces at `.agents/plugins/marketplace.json` and
local plugin entries that point at another path in the same repository.

## Hook trust

After installation, start Codex and open:

`/hooks`

Review and trust Ponytail's hooks. Do not bypass this approval boundary.

The standard plugin then provides:

- `SessionStart`: activates Ponytail and injects the active ruleset.
- `UserPromptSubmit`: tracks `lite`, `full`, `ultra`, and `off` mode changes.
- `SubagentStart`: propagates the active ruleset to subagents.

Node.js must be available on `PATH`.

## Default mode

Ponytail's upstream default remains **full**. This repository does not override it.

## Updating

Refresh the project copy from upstream with:

Windows:

```powershell
./scripts/update-ponytail.ps1
```

POSIX:

```bash
./scripts/update-ponytail.sh
```

The updater shallow-clones current upstream `main`, replaces only the vendored
Ponytail runtime payload, records the new upstream commit, and reapplies the single
cosmetic SVG icon-path adaptation.

Always inspect the resulting hook and skill diff before committing. Ponytail updates
can change executable lifecycle code, not just prompts.

After accepting an update, restart Codex/ChatGPT so the local plugin cache refreshes
from the updated repository source.

## Relationship to Matt Pocock skills

The systems intentionally remain separate:

- Matt Pocock skills: project-local skill copies under `.agents/skills/`, managed by
the `skills` CLI and `skills-lock.json`.
- Ponytail: a complete local Codex plugin under `third_party/ponytail/`, exposed
through the repository marketplace.

Do not separately install Ponytail's six skills with the `skills` CLI; the plugin is
their authoritative source and also supplies their lifecycle behavior.
37 changes: 37 additions & 0 deletions scripts/setup-ponytail.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
$ErrorActionPreference = "Stop"

function Require-Command([string]$Name) {
if (-not (Get-Command $Name -ErrorAction SilentlyContinue)) {
throw "'$Name' is required but was not found on PATH."
}
}

Require-Command "node"
Require-Command "codex"

$RepoRoot = Split-Path -Parent $PSScriptRoot
Push-Location $RepoRoot
try {
$marketplaces = (& codex plugin marketplace list 2>&1 | Out-String)
if ($marketplaces -notmatch "llama-cpp-local") {
Write-Host "Registering the repository-local plugin marketplace..."
& codex plugin marketplace add .
if ($LASTEXITCODE -ne 0) {
throw "Failed to register the repository-local marketplace."
}
}

Write-Host "Installing Ponytail from the repository-local marketplace..."
& codex plugin add ponytail@llama-cpp-local
if ($LASTEXITCODE -ne 0) {
throw "Failed to install the local Ponytail plugin."
}
}
finally {
Pop-Location
}

Write-Host ""
Write-Host "Ponytail is installed from third_party/ponytail."
Write-Host "Start Codex, open /hooks, review Ponytail's hooks, and trust them."
Write-Host "Ponytail's upstream default mode is full."
23 changes: 23 additions & 0 deletions scripts/setup-ponytail.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
set -euo pipefail

command -v node >/dev/null 2>&1 || { echo "node is required but was not found on PATH." >&2; exit 1; }
command -v codex >/dev/null 2>&1 || { echo "codex is required but was not found on PATH." >&2; exit 1; }

repo_root="$(cd "$(dirname "$0")/.." && pwd)"
cd "$repo_root"

if ! codex plugin marketplace list 2>&1 | grep -q 'llama-cpp-local'; then
echo "Registering the repository-local plugin marketplace..."
codex plugin marketplace add .
fi

echo "Installing Ponytail from the repository-local marketplace..."
codex plugin add ponytail@llama-cpp-local

cat <<'EOF'

Ponytail is installed from third_party/ponytail.
Start Codex, open /hooks, review Ponytail's hooks, and trust them.
Ponytail's upstream default mode is full.
EOF
83 changes: 83 additions & 0 deletions scripts/update-ponytail.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
$ErrorActionPreference = "Stop"

function Require-Command([string]$Name) {
if (-not (Get-Command $Name -ErrorAction SilentlyContinue)) {
throw "'$Name' is required but was not found on PATH."
}
}

Require-Command "git"

$RepoRoot = Split-Path -Parent $PSScriptRoot
$Dest = Join-Path $RepoRoot "third_party/ponytail"
$Temp = Join-Path ([System.IO.Path]::GetTempPath()) ("ponytail-" + [guid]::NewGuid().ToString("N"))

try {
& git clone --depth 1 https://github.com/DietrichGebert/ponytail.git $Temp
if ($LASTEXITCODE -ne 0) {
throw "Failed to clone DietrichGebert/ponytail."
}

$Revision = (& git -C $Temp rev-parse HEAD).Trim()

if (Test-Path $Dest) {
Remove-Item -Recurse -Force $Dest
}
New-Item -ItemType Directory -Force -Path $Dest | Out-Null
New-Item -ItemType Directory -Force -Path (Join-Path $Dest "assets") | Out-Null
New-Item -ItemType Directory -Force -Path (Join-Path $Dest "scripts") | Out-Null

Copy-Item -Recurse (Join-Path $Temp ".codex-plugin") $Dest
Copy-Item -Recurse (Join-Path $Temp "hooks") $Dest
Copy-Item -Recurse (Join-Path $Temp "skills") $Dest
Copy-Item (Join-Path $Temp "AGENTS.md") $Dest
Copy-Item (Join-Path $Temp "LICENSE") $Dest
Copy-Item (Join-Path $Temp "package.json") $Dest
Copy-Item (Join-Path $Temp "scripts/uninstall.js") (Join-Path $Dest "scripts/uninstall.js")
Copy-Item (Join-Path $Temp "assets/logo-dark.svg") (Join-Path $Dest "assets/logo-dark.svg")

$ManifestPath = Join-Path $Dest ".codex-plugin/plugin.json"
$Manifest = [System.IO.File]::ReadAllText($ManifestPath)
$Manifest = $Manifest.Replace("./assets/logo.png", "./assets/logo-dark.svg")
[System.IO.File]::WriteAllText($ManifestPath, $Manifest, [System.Text.UTF8Encoding]::new($false))

[System.IO.File]::WriteAllText(
(Join-Path $Dest "UPSTREAM_REVISION"),
$Revision + [Environment]::NewLine,
[System.Text.UTF8Encoding]::new($false)
)

$VendorNote = @"
# Vendored Ponytail plugin

Source: https://github.com/DietrichGebert/ponytail

Upstream revision: `$Revision`

This directory contains Ponytail's Codex runtime payload: its native plugin manifest,
lifecycle hooks, six skills, package metadata, license, upstream AGENTS.md, uninstall
helper, and logo asset.

The runtime files are copied from upstream unchanged except for one packaging-only
manifest adjustment: the icon paths use the upstream `assets/logo-dark.svg` instead
of `assets/logo.png`. This avoids carrying a large binary asset while leaving all
skills and executable hook behavior unchanged.

Refresh with `scripts/update-ponytail.ps1` or `scripts/update-ponytail.sh`, then
review the full diff before committing.
"@
[System.IO.File]::WriteAllText(
(Join-Path $Dest "VENDORED.md"),
$VendorNote,
[System.Text.UTF8Encoding]::new($false)
)

Write-Host "Ponytail vendored at upstream revision $Revision"
Write-Host "Review: git diff -- third_party/ponytail"
Write-Host "Restart Codex/ChatGPT after accepting the update so the local plugin cache refreshes."
}
finally {
if (Test-Path $Temp) {
Remove-Item -Recurse -Force $Temp
}
}
62 changes: 62 additions & 0 deletions scripts/update-ponytail.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/usr/bin/env bash
set -euo pipefail

command -v git >/dev/null 2>&1 || { echo "git is required but was not found on PATH." >&2; exit 1; }

repo_root="$(cd "$(dirname "$0")/.." && pwd)"
dest="$repo_root/third_party/ponytail"
tmp="$(mktemp -d)"

cleanup() {
rm -rf "$tmp"
}
trap cleanup EXIT

git clone --depth 1 https://github.com/DietrichGebert/ponytail.git "$tmp/src"
revision="$(git -C "$tmp/src" rev-parse HEAD)"

rm -rf "$dest"
mkdir -p "$dest/assets" "$dest/scripts"

cp -R "$tmp/src/.codex-plugin" "$dest/"
cp -R "$tmp/src/hooks" "$dest/"
cp -R "$tmp/src/skills" "$dest/"
cp "$tmp/src/AGENTS.md" "$dest/"
cp "$tmp/src/LICENSE" "$dest/"
cp "$tmp/src/package.json" "$dest/"
cp "$tmp/src/scripts/uninstall.js" "$dest/scripts/"
cp "$tmp/src/assets/logo-dark.svg" "$dest/assets/"

python3 - "$dest/.codex-plugin/plugin.json" <<'PY'
from pathlib import Path
import sys
p = Path(sys.argv[1])
s = p.read_text(encoding="utf-8")
p.write_text(s.replace("./assets/logo.png", "./assets/logo-dark.svg"), encoding="utf-8")
PY

printf '%s\n' "$revision" > "$dest/UPSTREAM_REVISION"

cat > "$dest/VENDORED.md" <<EOF
# Vendored Ponytail plugin

Source: https://github.com/DietrichGebert/ponytail

Upstream revision: `$revision`

This directory contains Ponytail's Codex runtime payload: its native plugin manifest,
lifecycle hooks, six skills, package metadata, license, upstream AGENTS.md, uninstall
helper, and logo asset.

The runtime files are copied from upstream unchanged except for one packaging-only
manifest adjustment: the icon paths use the upstream `assets/logo-dark.svg` instead
of `assets/logo.png`. This avoids carrying a large binary asset while leaving all
skills and executable hook behavior unchanged.

Refresh with `scripts/update-ponytail.ps1` or `scripts/update-ponytail.sh`, then
review the full diff before committing.
EOF

echo "Ponytail vendored at upstream revision $revision"
echo "Review: git diff -- third_party/ponytail"
echo "Restart Codex/ChatGPT after accepting the update so the local plugin cache refreshes."
32 changes: 32 additions & 0 deletions third_party/ponytail/.codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "ponytail",
"version": "4.10.0",
"description": "Lazy senior dev mode. Forces the simplest, shortest solution that actually works: YAGNI, stdlib first, no unrequested abstractions.",
"author": {
"name": "Dietrich Gebert",
"url": "https://github.com/DietrichGebert"
},
"homepage": "https://github.com/DietrichGebert/ponytail",
"repository": "https://github.com/DietrichGebert/ponytail",
"license": "MIT",
"keywords": ["yagni", "minimalism", "code-review", "productivity"],
"skills": "./skills/",
"hooks": "./hooks/claude-codex-hooks.json",
"interface": {
"displayName": "Ponytail",
"shortDescription": "Lazy senior developer mode",
"longDescription": "Prefer YAGNI, the standard library, native platform features, and the smallest correct implementation.",
"developerName": "Dietrich Gebert",
"category": "Productivity",
"capabilities": ["Instructions", "Lifecycle hooks"],
"websiteURL": "https://github.com/DietrichGebert/ponytail",
"defaultPrompt": [
"Use Ponytail mode for this task.",
"Review this diff for over-engineering.",
"Find the smallest correct implementation."
],
"brandColor": "#111111",
"composerIcon": "./assets/logo-dark.svg",
"logo": "./assets/logo-dark.svg"
}
}
Loading