* feat: add Grok Build adapter (revive #561 on current main) Thin Grok packaging under .grok-plugin/ with root plugin.json path overrides (hooks + MCP). SessionStart/UserPromptSubmit/SubagentStart reuse shared hooks/ponytail-*.js; mode state under GROK_PLUGIN_DATA. Rebases the approach from #561 onto current main: keep Qoder detection and output paths, add isGrok, export getGrokPluginDataDir, drop bash-only exec from Grok hooks, and document install/enable/uninstall on the front-page README (en/es/ko) plus agent-portability. Direct install works today: grok plugin install DietrichGebert/ponytail --trust Marketplace root source ("./") matches Claude; Grok's scanner still rejects it (see xai-org/plugin-marketplace#123 class of bugs). Co-authored-by: Vinícius Souza <souza.vinicius@bb.com.br> * fix(grok): drop MCP, harden host detection and tests Review feedback on #661: - Remove MCP wiring (git install never installs ponytail-mcp deps; no other host ships MCP; hooks+skills cover always-on) - Drop static plugin-index.json (optional catalog fluff) - Clear GROK_PLUGIN_* in hooks.test.js so host suites cannot leak - Exclusive isGrok after Copilot/Codex; state falls back to ROOT not ~/.claude - Tighten Qoder regression assert; structural checks for plugin.json/hooks - List Grok Build among skill-capable hosts in README * refactor(grok): DRY — reuse Claude/Codex hooks map Second review pass for #661: - Delete .grok-plugin/hooks.json (near-copy of claude-codex-hooks.json). Root plugin.json points at the shared map; Grok sets CLAUDE_PLUGIN_ROOT. - Drop getGrokPluginDataDir; inline GROK_PLUGIN_DATA || ROOT like other hosts. - Grok uses Claude-compatible writeHookOutput (raw SessionStart, JSON SubagentStart) instead of a separate raw-only branch. - Slim .grok-plugin/marketplace.json to match .claude-plugin. - Tests: shared-map assert, SubagentStart JSON under Grok, Qoder isolation. * fix(grok): use native skill activation * chore: drop unrelated Qoder formatting --------- Co-authored-by: Vinícius Souza <souza.vinicius@bb.com.br>
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "ponytail",
|
||||
"description": "Lazy senior dev mode for AI agents. The best code is the code you never wrote.",
|
||||
"owner": {
|
||||
"name": "Dietrich Gebert",
|
||||
"url": "https://github.com/DietrichGebert"
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "ponytail",
|
||||
"description": "Forces the laziest solution that works. YAGNI, stdlib first, one line over fifty.",
|
||||
"source": "./",
|
||||
"category": "productivity"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -214,6 +214,23 @@ clawhub install ponytail
|
||||
|
||||
Instala ponytail como skill de OpenClaw desde ClawHub; los skills de review, audit, debt y help se instalan igual (`clawhub install ponytail-review`, etc.). OpenClaw lo aplica en tareas de código y también lo expone como comando `/ponytail`. Sin ClawHub, copia [`.openclaw/skills/ponytail`](.openclaw/skills/) a `~/.openclaw/skills/`.
|
||||
|
||||
### Grok Build
|
||||
|
||||
```bash
|
||||
grok plugin install DietrichGebert/ponytail --trust
|
||||
```
|
||||
|
||||
Habilita el plugin (está desactivado por defecto): `/plugins` → Plugins → Space en `ponytail`, o en `~/.grok/config.toml`:
|
||||
|
||||
```toml
|
||||
[plugins]
|
||||
enabled = ["ponytail"]
|
||||
```
|
||||
|
||||
Abre una sesión nueva (o recarga los plugins). Los skills aparecen como `/ponytail`, `/ponytail-review`, `/ponytail-audit`, `/ponytail-debt`, `/ponytail-gain`, `/ponytail-help`. Verifica con `grok inspect`. Grok puede invocar ponytail automáticamente en tareas de código según la descripción del skill; usa `/ponytail` (o `/ponytail lite`, `/ponytail full`, `/ponytail ultra`) cuando necesites activarlo de forma explícita. No se usan hooks de ciclo de vida de Grok: la salida de `SessionStart` no puede inyectar instrucciones.
|
||||
|
||||
`AGENTS.md` sigue funcionando solo como instrucciones desde un checkout sin el plugin. Desinstalar: `grok plugin uninstall ponytail`.
|
||||
|
||||
Eso fue todo. Él estaría orgulloso. No lo va a decir.
|
||||
|
||||
Activo en cada sesión, con un puñado de comandos (ver [Comandos](#comandos)). `/ponytail ultra` existe para cuando el codebase te hizo algo personal. El texto de inicio y de cambio de modo muestra el nivel activo.
|
||||
|
||||
@@ -233,6 +233,23 @@ clawhub install ponytail
|
||||
|
||||
ClawHub에서 ponytail을 OpenClaw 스킬로 설치한다. review, audit, debt, gain, help 스킬도 같은 식으로 깐다(`clawhub install ponytail-review` 등). OpenClaw는 코딩 작업에 이를 적용하고 `/ponytail` 명령으로도 열어 준다. ClawHub가 없으면 [`.openclaw/skills/ponytail`](.openclaw/skills/)을 `~/.openclaw/skills/`에 복사하면 된다.
|
||||
|
||||
### Grok Build
|
||||
|
||||
```bash
|
||||
grok plugin install DietrichGebert/ponytail --trust
|
||||
```
|
||||
|
||||
플러그인은 기본이 꺼져 있다. `/plugins` → Plugins에서 `ponytail`에 Space, 또는 `~/.grok/config.toml`:
|
||||
|
||||
```toml
|
||||
[plugins]
|
||||
enabled = ["ponytail"]
|
||||
```
|
||||
|
||||
새 세션을 열거나 플러그인을 다시 로드한다. 스킬은 `/ponytail`, `/ponytail-review`, `/ponytail-audit`, `/ponytail-debt`, `/ponytail-gain`, `/ponytail-help`로 보인다. `grok inspect`로 확인. Grok은 스킬 설명을 바탕으로 코딩 작업에서 ponytail을 자동으로 호출할 수 있다. 명시적으로 활성화해야 하면 `/ponytail`(또는 `/ponytail lite`, `/ponytail full`, `/ponytail ultra`)을 사용한다. `SessionStart` 출력으로는 지시문을 주입할 수 없으므로 Grok 라이프사이클 훅은 사용하지 않는다.
|
||||
|
||||
체크아웃의 `AGENTS.md`만으로도 지시문 전용 모드는 된다. 제거: `grok plugin uninstall ponytail`.
|
||||
|
||||
이게 끝이었다. 그 사람이라면 흐뭇해할 거다. 입 밖으로 내진 않겠지만.
|
||||
|
||||
매 세션 켜져 있고, 명령 몇 개가 딸려 온다([Commands](#commands) 참고). `/ponytail ultra`는 코드베이스가 당신에게 단단히 밉보인 날을 위해 있다. 시작할 때와 모드를 바꿀 때 지금 모드를 보여 준다.
|
||||
|
||||
@@ -246,6 +246,23 @@ clawhub install ponytail
|
||||
|
||||
Installs ponytail as an OpenClaw skill from ClawHub; the review, audit, debt, gain, and help skills install the same way (`clawhub install ponytail-review`, and so on). OpenClaw applies it on coding tasks and also exposes it as a `/ponytail` command. Without ClawHub, copy [`.openclaw/skills/ponytail`](.openclaw/skills/) into `~/.openclaw/skills/`.
|
||||
|
||||
### Grok Build
|
||||
|
||||
```bash
|
||||
grok plugin install DietrichGebert/ponytail --trust
|
||||
```
|
||||
|
||||
Enable the plugin (off by default): `/plugins` → Plugins → Space on `ponytail`, or in `~/.grok/config.toml`:
|
||||
|
||||
```toml
|
||||
[plugins]
|
||||
enabled = ["ponytail"]
|
||||
```
|
||||
|
||||
Start a new session (or reload plugins). Skills show as `/ponytail`, `/ponytail-review`, `/ponytail-audit`, `/ponytail-debt`, `/ponytail-gain`, `/ponytail-help`. Verify with `grok inspect`. Grok can auto-invoke ponytail for coding tasks from its skill description; use `/ponytail` (or `/ponytail lite`, `/ponytail full`, `/ponytail ultra`) when activation needs to be explicit. Grok lifecycle hooks are not used because their SessionStart output cannot inject instructions.
|
||||
|
||||
`AGENTS.md` still works instruction-only from a checkout without the plugin.
|
||||
|
||||
That was it. He'd be proud. He won't say it.
|
||||
|
||||
Active every session, with a handful of commands (see [Commands](#commands)). `/ponytail ultra` exists for when the codebase has wronged you personally. Startup and mode-change text shows the current mode.
|
||||
@@ -277,6 +294,7 @@ Which files map to which agent: [Agent portability](docs/agent-portability.md).
|
||||
| Claude Code | `/plugin remove ponytail` |
|
||||
| Codex | `codex plugin remove ponytail` |
|
||||
| Devin CLI | `devin plugins remove ponytail` |
|
||||
| Grok Build | `grok plugin uninstall ponytail` |
|
||||
| Pi agent | `pi uninstall ponytail` |
|
||||
| Cursor / Windsurf / Cline / Qoder / etc. | Delete the copied rule file |
|
||||
|
||||
@@ -293,7 +311,7 @@ These remove the plugin's own files. They leave behind a small amount of state p
|
||||
| `/ponytail-gain` | Show the measured impact scoreboard (less code, less cost, more speed) from the benchmark. |
|
||||
| `/ponytail-help` | Quick reference for the commands above. |
|
||||
|
||||
Commands need a skill-capable host (Claude Code, Codex, Devin CLI, OpenCode, Gemini, pi, Swival, Hermes Agent, Qoder). In Codex they're skills, invoke with `@` (`@ponytail-review`). The instruction-only adapters (Cursor, Windsurf, Cline, Copilot, Kiro, Antigravity) load the always-on ruleset without the commands.
|
||||
Commands need a skill-capable host (Claude Code, Codex, Devin CLI, OpenCode, Gemini, pi, Swival, Hermes Agent, Qoder, Grok Build). In Codex they're skills, invoke with `@` (`@ponytail-review`). The instruction-only adapters (Cursor, Windsurf, Cline, Copilot, Kiro, Antigravity) load the always-on ruleset without the commands.
|
||||
|
||||
## Development
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ to load in a given agent.
|
||||
|------|-------|-------|
|
||||
| Claude Code | `.claude-plugin/plugin.json`, `commands/`, `hooks/claude-codex-hooks.json`, `hooks/` | Full plugin install with session activation, mode tracking, commands, and statusline support. |
|
||||
| Codex | `.codex-plugin/plugin.json`, `hooks/claude-codex-hooks.json`, `hooks/`, `skills/` | Plugin install with the same skills plus lifecycle hooks for activation and mode tracking. |
|
||||
| Grok Build | root `plugin.json`, `.grok-plugin/marketplace.json`, `skills/`, `commands/` | `grok plugin install DietrichGebert/ponytail --trust`, then enable. Grok can auto-invoke ponytail from its coding-task skill description; `/ponytail` makes activation explicit. Grok lifecycle hooks are not used because passive hook output cannot inject instructions. |
|
||||
| OpenCode | `.opencode/plugins/ponytail.mjs`, `.opencode/command/`, `hooks/`, `skills/` | Server plugin injects the ruleset each turn via `experimental.chat.system.transform` and persists `/ponytail` switches; reuses the shared instruction builder. |
|
||||
| pi | `pi-extension/`, `skills/`, `hooks/` | Package extension: injects the ruleset each turn through the shared instruction builder and registers the `/ponytail` commands. |
|
||||
| Hermes Agent | `plugin.yaml`, `__init__.py`, `skills/` | Native Hermes plugin: injects active mode through `pre_llm_call`, rewrites gateway `/ponytail-*` skill commands into agent prompts, registers `/ponytail` mode switching, and exposes bundled skills as `ponytail:<skill>`. |
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"name": "ponytail"
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env node
|
||||
// Grok Build loads Ponytail through its native skill system. Lifecycle-hook
|
||||
// stdout is passive in Grok, so this adapter must not register any hooks.
|
||||
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const root = path.join(__dirname, '..');
|
||||
|
||||
test('Grok manifest is a skill-only adapter with no lifecycle hooks', () => {
|
||||
const manifest = JSON.parse(fs.readFileSync(path.join(root, 'plugin.json'), 'utf8'));
|
||||
assert.equal(manifest.name, 'ponytail');
|
||||
assert.equal(manifest.hooks, undefined);
|
||||
assert.equal(manifest.mcpServers, undefined);
|
||||
assert.ok(!fs.existsSync(path.join(root, 'hooks', 'hooks.json')));
|
||||
assert.ok(!fs.existsSync(path.join(root, '.grok-plugin', 'hooks.json')));
|
||||
});
|
||||
|
||||
test('Ponytail skill describes every coding task for Grok auto-invocation', () => {
|
||||
const skill = fs.readFileSync(path.join(root, 'skills', 'ponytail', 'SKILL.md'), 'utf8');
|
||||
assert.match(skill, /Use on ANY\s+coding task/i);
|
||||
assert.match(skill, /writing, adding, refactoring, fixing, reviewing, or designing\s+code/i);
|
||||
assert.doesNotMatch(skill, /disable-model-invocation:\s*true/i);
|
||||
});
|
||||
Reference in New Issue
Block a user