Skip to content
Open
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
10 changes: 10 additions & 0 deletions .factory-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "ponytail",
"version": "4.8.3",
"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"
},
"hooks": "./hooks/factory-hooks.json"
}
8 changes: 8 additions & 0 deletions .openclaw/skills/ponytail-ask/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
name: ponytail-ask
description: "Clarify requirements and ask targeted questions to avoid spec building."
homepage: https://github.com/DietrichGebert/ponytail
license: MIT
---

Understand the user's requirements, clarify ambiguity, and ask targeted questions to refine the task before coding. Keep questions focused and concise, ensuring we only build what is actually requested and avoid speculative features.
9 changes: 6 additions & 3 deletions .openclaw/skills/ponytail-help/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,15 @@ Level sticks until changed or session end.
|-------|---------|--------------|
| **ponytail** | `/ponytail` | Lazy mode itself. Simplest solution that works. |
| **ponytail-review** | `/ponytail-review` | Over-engineering review: `L42: yagni: factory, one product. Inline.` |
| **ponytail-audit** | `/ponytail-audit` | Whole-repo audit for over-engineering, ranked list of what to delete. |
| **ponytail-debt** | `/ponytail-debt` | Harvest every ponytail: shortcut comment into one debt ledger. |
| **ponytail-gain** | `/ponytail-gain` | Measured-impact scoreboard: less code, less cost, more speed. |
| **ponytail-jedi** | `/ponytail-jedi` | SOTA research: search, rank, clone, modify, reuse trusted repos. |
| **ponytail-plan** | `/ponytail-plan` | Create or simplify implementation plans to be clean, simple, and minimal. |
| **ponytail-ask** | `/ponytail-ask` | Clarify requirements and ask targeted questions to avoid spec building. |
| **ponytail-help** | `/ponytail-help` | This card. |

Codex uses `@ponytail`, `@ponytail-review`, and `@ponytail-help`; Claude Code
and OpenCode use the slash-command forms above (OpenCode ships `/ponytail` and
`/ponytail-review`).
Codex uses `@ponytail`, `@ponytail-review`, etc.; Claude Code, OpenCode, and Droid use the slash-command forms.

## Deactivate

Expand Down
8 changes: 8 additions & 0 deletions .openclaw/skills/ponytail-jedi/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
name: ponytail-jedi
description: "SOTA research: search, rank, clone, modify, reuse trusted repos."
homepage: https://github.com/DietrichGebert/ponytail
license: MIT
---

Perform deep open-source SOTA (State of the Art) research for the given task. Do not start from scratch: search, rank, clone, modify, extract, or connect to world-class trusted repositories that can do part or all of the work. Find and reuse existing high-quality, trusted open-source code rather than reinventing the wheel.
8 changes: 8 additions & 0 deletions .openclaw/skills/ponytail-plan/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
name: ponytail-plan
description: "Create or simplify implementation plans to be clean, simple, and minimal."
homepage: https://github.com/DietrichGebert/ponytail
license: MIT
---

Understand the user's task and create a clean, simple, and minimal implementation plan. Break down the task into component-level items and simplify the approach to avoid unnecessary abstractions, layers, or dependencies. If the user already has a plan, audit and simplify it to be clean and minimal.
5 changes: 5 additions & 0 deletions .opencode/command/ponytail-ask.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
description: Clarify requirements and ask targeted questions to refine tasks before coding
---

Understand the user's requirements, clarify ambiguity, and ask targeted questions to refine the task before coding. Keep questions focused and concise, ensuring we only build what is actually requested and avoid speculative features.
5 changes: 5 additions & 0 deletions .opencode/command/ponytail-jedi.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
description: Research SOTA open source solutions instead of starting from scratch
---

Perform deep open-source SOTA (State of the Art) research for the given task. Do not start from scratch: search, rank, clone, modify, extract, or connect to world-class trusted repositories that can do part or all of the work. Find and reuse existing high-quality, trusted open-source code rather than reinventing the wheel.
5 changes: 5 additions & 0 deletions .opencode/command/ponytail-lightsaber.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
description: Research SOTA open source solutions instead of starting from scratch
---

Perform deep open-source SOTA (State of the Art) research for the given task. Do not start from scratch: search, rank, clone, modify, extract, or connect to world-class trusted repositories that can do part or all of the work. Find and reuse existing high-quality, trusted open-source code rather than reinventing the wheel.
5 changes: 5 additions & 0 deletions .opencode/command/ponytail-plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
description: Create or simplify implementation plans to be clean, simple, and minimal
---

Understand the user's task and create a clean, simple, and minimal implementation plan. Break down the task into component-level items and simplify the approach to avoid unnecessary abstractions, layers, or dependencies. If the user already has a plan, audit and simplify it to be clean and minimal.
2 changes: 2 additions & 0 deletions commands/ponytail-ask.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
description = "Clarify requirements and ask targeted questions to refine tasks before coding"
prompt = "Understand the user's requirements, clarify ambiguity, and ask targeted questions to refine the task before coding. Keep questions focused and concise, ensuring we only build what is actually requested and avoid speculative features."
2 changes: 2 additions & 0 deletions commands/ponytail-jedi.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
description = "Research SOTA open source solutions instead of starting from scratch"
prompt = "Perform deep open-source SOTA (State of the Art) research for the given task. Do not start from scratch: search, rank, clone, modify, extract, or connect to world-class trusted repositories that can do part or all of the work. Find and reuse existing high-quality, trusted open-source code rather than reinventing the wheel."
2 changes: 2 additions & 0 deletions commands/ponytail-lightsaber.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
description = "Research SOTA open source solutions instead of starting from scratch"
prompt = "Perform deep open-source SOTA (State of the Art) research for the given task. Do not start from scratch: search, rank, clone, modify, extract, or connect to world-class trusted repositories that can do part or all of the work. Find and reuse existing high-quality, trusted open-source code rather than reinventing the wheel."
2 changes: 2 additions & 0 deletions commands/ponytail-plan.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
description = "Create or simplify implementation plans to be clean, simple, and minimal"
prompt = "Understand the user's task and create a clean, simple, and minimal implementation plan. Break down the task into component-level items and simplify the approach to avoid unnecessary abstractions, layers, or dependencies. If the user already has a plan, audit and simplify it to be clean and minimal."
1 change: 1 addition & 0 deletions docs/agent-portability.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ to load in a given agent.
| Cline | `.clinerules/ponytail.md` | Project rule. |
| GitHub Copilot | `.github/copilot-instructions.md` | Repository instruction file. |
| GitHub Copilot CLI | `.github/plugin/`, `AGENTS.md`, `.github/copilot-instructions.md`, `~/.copilot/copilot-instructions.md` | Plugin-supported (`copilot plugin marketplace add DietrichGebert/ponytail` + `copilot plugin install ponytail@ponytail`). Fallback instruction mode remains: per-project from `AGENTS.md` or `.github/copilot-instructions.md`, or globally from `~/.copilot/copilot-instructions.md` (instruction-tier, no `/ponytail` levels or hooks). |
| Factory Droid | `.factory-plugin/plugin.json`, `hooks/factory-hooks.json`, `skills/`, `hooks/`, `AGENTS.md` | Plugin install with session activation, mode tracking, and commands. Fallback instruction mode: copy `AGENTS.md` + `skills/` to `~/.factory/` or repo root. |
| Antigravity | `AGENTS.md` | Reads `AGENTS.md` at the repo root as always-on rules (like `.cursorrules`/`CLAUDE.md`); `.agents/rules/` also works for workspace rules. Instruction-tier. |
| CodeWhale | `AGENTS.md` | Reads `AGENTS.md` from the repo root as project instructions; also reads `CLAUDE.md` and `.claude/instructions.md` as fallbacks. Instruction-tier. |
| Swival | `.swival/skills/`, `AGENTS.md` | `swival skills add https://github.com/DietrichGebert/ponytail` installs the six skills straight into `.swival/skills/`. Add `--global` to stage them in the library (`~/.config/swival/library`) first, then `swival skills add ponytail` (or `--global ponytail`) to activate per-project or everywhere. Also reads `AGENTS.md` from the repo root and `~/.config/swival/AGENTS.md` globally as instruction-tier fallback. |
Expand Down
44 changes: 44 additions & 0 deletions hooks/factory-hooks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"hooks": {
"SessionStart": [
{
"matcher": "startup|resume|clear|compact",
"hooks": [
{
"type": "command",
"command": "node \"${DROID_PLUGIN_ROOT}/hooks/ponytail-activate.js\"; exit 0",
"commandWindows": "if (Get-Command node -ErrorAction SilentlyContinue) { node \"$env:DROID_PLUGIN_ROOT\\hooks\\ponytail-activate.js\" }",
"timeout": 5,
"statusMessage": "Loading ponytail mode..."
}
]
}
],
"SubagentStart": [
{
"hooks": [
{
"type": "command",
"command": "node \"${DROID_PLUGIN_ROOT}/hooks/ponytail-subagent.js\"; exit 0",
"commandWindows": "if (Get-Command node -ErrorAction SilentlyContinue) { node \"$env:DROID_PLUGIN_ROOT\\hooks\\ponytail-subagent.js\" }",
"timeout": 5,
"statusMessage": "Loading ponytail mode..."
}
]
}
],
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "node \"${DROID_PLUGIN_ROOT}/hooks/ponytail-mode-tracker.js\"; exit 0",
"commandWindows": "if (Get-Command node -ErrorAction SilentlyContinue) { node \"$env:DROID_PLUGIN_ROOT\\hooks\\ponytail-mode-tracker.js\" }",
"timeout": 5,
"statusMessage": "Tracking ponytail mode..."
}
]
}
]
}
}
3 changes: 2 additions & 1 deletion hooks/ponytail-activate.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const {
clearMode,
isCodex,
isCopilot,
isDroid,
setMode,
writeHookOutput,
} = require('./ponytail-runtime');
Expand Down Expand Up @@ -42,7 +43,7 @@ try {
let output = getPonytailInstructions(mode);

// 3. Detect missing statusline config — nudge Claude to help set it up
if (!isCodex && !isCopilot) try {
if (!isCodex && !isCopilot && !isDroid) try {
let hasStatusline = false;
if (fs.existsSync(settingsPath)) {
// Strip UTF-8 BOM some editors prepend on Windows (breaks JSON.parse)
Expand Down
6 changes: 5 additions & 1 deletion hooks/ponytail-runtime.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
const fs = require('fs');
const path = require('path');
const os = require('os');
const { getClaudeDir } = require('./ponytail-config');

const STATE_FILE = '.ponytail-active';
const isCopilot = Boolean(process.env.COPILOT_PLUGIN_DATA);
const isCodex = !isCopilot && Boolean(process.env.PLUGIN_DATA);
const isDroid = !isCopilot && !isCodex && Boolean(process.env.DROID_PLUGIN_ROOT);

let stateDir = getClaudeDir();
if (isCodex) stateDir = process.env.PLUGIN_DATA;
if (isCopilot) stateDir = process.env.COPILOT_PLUGIN_DATA;
if (isDroid) stateDir = process.env.DROID_CONFIG_DIR || path.join(os.homedir(), '.factory');

const statePath = path.join(stateDir, STATE_FILE);

Expand Down Expand Up @@ -37,7 +40,7 @@ function writeHookOutput(event, mode, context = '') {
event === 'SessionStart' && context ? { additionalContext: context } : {}));
return;
}
if (isCodex) {
if (isCodex || isDroid) {
const output = { systemMessage: `PONYTAIL:${mode.toUpperCase()}` };
if (context) {
output.hookSpecificOutput = {
Expand All @@ -62,6 +65,7 @@ module.exports = {
clearMode,
isCodex,
isCopilot,
isDroid,
readMode,
setMode,
writeHookOutput,
Expand Down
57 changes: 57 additions & 0 deletions pi-extension/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,63 @@ export default function ponytailExtension(pi) {
handler: (_args, ctx) => sendAlias("/skill:ponytail-help", "", ctx),
});

pi.registerCommand("ponytail-jedi", {
description: "Run /skill:ponytail-jedi",
handler: (_args, ctx) => sendAlias("/skill:ponytail-jedi", "", ctx),
});

pi.registerCommand("ponytail-lightsaber", {
description: "Run /skill:ponytail-jedi (research)",
handler: (_args, ctx) => sendAlias("/skill:ponytail-jedi", "", ctx),
});

pi.registerCommand("ponytail-plan", {
description: "Run /skill:ponytail-plan",
handler: (_args, ctx) => sendAlias("/skill:ponytail-plan", "", ctx),
});

pi.registerCommand("ponytail-ask", {
description: "Run /skill:ponytail-ask",
handler: (_args, ctx) => sendAlias("/skill:ponytail-ask", "", ctx),
});

pi.registerShortcut("ponytail:cycleMode", {
description: "Cycle ponytail modes (off -> lite -> full -> ultra -> off)",
handler: async (ctx) => {
const nextModes = { off: "lite", lite: "full", full: "ultra", ultra: "off" };
const nextMode = nextModes[currentMode] || "full";
setMode(nextMode, ctx);
},
});

pi.registerShortcut("ponytail:modeLite", {
description: "Set ponytail mode to lite",
handler: async (ctx) => {
setMode("lite", ctx);
},
});

pi.registerShortcut("ponytail:modeFull", {
description: "Set ponytail mode to full",
handler: async (ctx) => {
setMode("full", ctx);
},
});

pi.registerShortcut("ponytail:modeUltra", {
description: "Set ponytail mode to ultra",
handler: async (ctx) => {
setMode("ultra", ctx);
},
});

pi.registerShortcut("ponytail:modeOff", {
description: "Turn ponytail mode off",
handler: async (ctx) => {
setMode("off", ctx);
},
});

pi.on("input", async (event) => {
if (event?.source === "extension") return;

Expand Down
37 changes: 35 additions & 2 deletions pi-extension/test/extension.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import ponytailExtension from "../index.js";
function createPiHarness() {
const events = new Map();
const commands = new Map();
const shortcuts = new Map();
const appendedEntries = [];
const sentUserMessages = [];

Expand All @@ -19,6 +20,9 @@ function createPiHarness() {
registerCommand(name, options) {
commands.set(name, options);
},
registerShortcut(keyId, options) {
shortcuts.set(keyId, options);
},
appendEntry(customType, data) {
appendedEntries.push({ customType, data });
},
Expand All @@ -28,7 +32,7 @@ function createPiHarness() {
};

ponytailExtension(pi);
return { events, commands, appendedEntries, sentUserMessages };
return { events, commands, shortcuts, appendedEntries, sentUserMessages };
}

function createCommandContext(overrides = {}) {
Expand Down Expand Up @@ -57,7 +61,36 @@ function withTempConfig(fn) {
test("extension registers Ponytail commands", () => {
const { commands } = createPiHarness();

assert.deepEqual([...commands.keys()].sort(), ["ponytail", "ponytail-audit", "ponytail-debt", "ponytail-gain", "ponytail-help", "ponytail-review"]);
assert.deepEqual(
[...commands.keys()].sort(),
[
"ponytail",
"ponytail-ask",
"ponytail-audit",
"ponytail-debt",
"ponytail-gain",
"ponytail-help",
"ponytail-jedi",
"ponytail-lightsaber",
"ponytail-plan",
"ponytail-review",
]
);
});

test("extension registers Ponytail shortcuts", () => {
const { shortcuts } = createPiHarness();

assert.deepEqual(
[...shortcuts.keys()].sort(),
[
"ponytail:cycleMode",
"ponytail:modeFull",
"ponytail:modeLite",
"ponytail:modeOff",
"ponytail:modeUltra",
]
);
});

test("/ponytail updates session mode and injects instructions", async () => withTempConfig(async () => {
Expand Down
7 changes: 7 additions & 0 deletions plugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,17 @@ provides_commands:
- ponytail-debt
- ponytail-gain
- ponytail-help
- ponytail-jedi
- ponytail-lightsaber
- ponytail-plan
- ponytail-ask
provides_skills:
- ponytail
- ponytail-review
- ponytail-audit
- ponytail-debt
- ponytail-gain
- ponytail-help
- ponytail-jedi
- ponytail-plan
- ponytail-ask
3 changes: 3 additions & 0 deletions scripts/build-openclaw-skills.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ const DESCRIPTIONS = {
'ponytail-debt': 'Harvest every ponytail: shortcut comment into one debt ledger, so deferrals get tracked instead of forgotten. One-shot report.',
'ponytail-gain': 'Show ponytail measured impact as a scoreboard: less code, less cost, more speed, from the benchmark medians. One-shot display.',
'ponytail-help': "Quick reference for ponytail's modes, skills, and commands. One-shot display.",
'ponytail-jedi': 'SOTA research: search, rank, clone, modify, reuse trusted repos.',
'ponytail-plan': 'Create or simplify implementation plans to be clean, simple, and minimal.',
'ponytail-ask': 'Clarify requirements and ask targeted questions to avoid spec building.',
};

const NAMES = Object.keys(DESCRIPTIONS);
Expand Down
9 changes: 9 additions & 0 deletions skills/ponytail-ask/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
name: ponytail-ask
description: >
Clarify requirements and ask targeted questions to refine tasks before writing code.
Ensures we only build what is requested. Use when the user says "ask questions",
"clarify requirements", "what is needed", or invokes /ponytail-ask.
---

Understand the user's requirements, clarify ambiguity, and ask targeted questions to refine the task before coding. Keep questions focused and concise, ensuring we only build what is actually requested and avoid speculative features.
9 changes: 6 additions & 3 deletions skills/ponytail-help/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,15 @@ Level sticks until changed or session end.
|-------|---------|--------------|
| **ponytail** | `/ponytail` | Lazy mode itself. Simplest solution that works. |
| **ponytail-review** | `/ponytail-review` | Over-engineering review: `L42: yagni: factory, one product. Inline.` |
| **ponytail-audit** | `/ponytail-audit` | Whole-repo audit for over-engineering, ranked list of what to delete. |
| **ponytail-debt** | `/ponytail-debt` | Harvest every ponytail: shortcut comment into one debt ledger. |
| **ponytail-gain** | `/ponytail-gain` | Measured-impact scoreboard: less code, less cost, more speed. |
| **ponytail-jedi** | `/ponytail-jedi` | SOTA research: search, rank, clone, modify, reuse trusted repos. |
| **ponytail-plan** | `/ponytail-plan` | Create or simplify implementation plans to be clean, simple, and minimal. |
| **ponytail-ask** | `/ponytail-ask` | Clarify requirements and ask targeted questions to avoid spec building. |
| **ponytail-help** | `/ponytail-help` | This card. |

Codex uses `@ponytail`, `@ponytail-review`, and `@ponytail-help`; Claude Code
and OpenCode use the slash-command forms above (OpenCode ships `/ponytail` and
`/ponytail-review`).
Codex uses `@ponytail`, `@ponytail-review`, etc.; Claude Code, OpenCode, and Droid use the slash-command forms.

## Deactivate

Expand Down
10 changes: 10 additions & 0 deletions skills/ponytail-jedi/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
name: ponytail-jedi
description: >
Search, rank, clone, modify, extract, or connect to world-class trusted open-source
repositories. SOTA research to avoid starting from scratch. Use when the user says
"research SOTA", "use open-source repos", "find a trusted repo", or invokes
/ponytail-jedi / /ponytail-lightsaber.
---

Perform deep open-source SOTA (State of the Art) research for the given task. Do not start from scratch: search, rank, clone, modify, extract, or connect to world-class trusted repositories that can do part or all of the work. Find and reuse existing high-quality, trusted open-source code rather than reinventing the wheel.
Loading