feat: codex support
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"hooks": {
|
||||
"SessionStart": [
|
||||
{
|
||||
"matcher": "startup|resume|clear|compact",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "node \"${PLUGIN_ROOT}/hooks/ponytail-activate.js\"",
|
||||
"commandWindows": "node \"%PLUGIN_ROOT%\\hooks\\ponytail-activate.js\"",
|
||||
"timeout": 5,
|
||||
"statusMessage": "Loading ponytail mode..."
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"UserPromptSubmit": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "node \"${PLUGIN_ROOT}/hooks/ponytail-mode-tracker.js\"",
|
||||
"commandWindows": "node \"%PLUGIN_ROOT%\\hooks\\ponytail-mode-tracker.js\"",
|
||||
"timeout": 5,
|
||||
"statusMessage": "Tracking ponytail mode..."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -10,24 +10,28 @@ const fs = require('fs');
|
||||
const path = require('path');
|
||||
const os = require('os');
|
||||
const { getDefaultMode } = require('./ponytail-config');
|
||||
const {
|
||||
clearMode,
|
||||
isCodex,
|
||||
setMode,
|
||||
writeHookOutput,
|
||||
} = require('./ponytail-runtime');
|
||||
|
||||
const claudeDir = path.join(os.homedir(), '.claude');
|
||||
const flagPath = path.join(claudeDir, '.ponytail-active');
|
||||
const settingsPath = path.join(claudeDir, 'settings.json');
|
||||
|
||||
const mode = getDefaultMode();
|
||||
|
||||
// "off" mode — skip activation entirely, don't write flag or emit rules
|
||||
if (mode === 'off') {
|
||||
try { fs.unlinkSync(flagPath); } catch (e) {}
|
||||
process.stdout.write('OK');
|
||||
clearMode();
|
||||
writeHookOutput('SessionStart', 'off', isCodex ? '' : 'OK');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// 1. Write flag file
|
||||
try {
|
||||
fs.mkdirSync(path.dirname(flagPath), { recursive: true });
|
||||
fs.writeFileSync(flagPath, mode);
|
||||
setMode(mode);
|
||||
} catch (e) {
|
||||
// Silent fail -- flag is best-effort, don't block the hook
|
||||
}
|
||||
@@ -45,7 +49,11 @@ try {
|
||||
const INDEPENDENT_MODES = new Set(['review']);
|
||||
|
||||
if (INDEPENDENT_MODES.has(mode)) {
|
||||
process.stdout.write('PONYTAIL MODE ACTIVE — level: ' + mode + '. Behavior defined by /ponytail-' + mode + ' skill.');
|
||||
writeHookOutput(
|
||||
'SessionStart',
|
||||
mode,
|
||||
'PONYTAIL MODE ACTIVE — level: ' + mode + '. Behavior defined by /ponytail-' + mode + ' skill.',
|
||||
);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
@@ -124,7 +132,7 @@ if (skillContent) {
|
||||
}
|
||||
|
||||
// 3. Detect missing statusline config — nudge Claude to help set it up
|
||||
try {
|
||||
if (!isCodex) try {
|
||||
let hasStatusline = false;
|
||||
if (fs.existsSync(settingsPath)) {
|
||||
const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
||||
@@ -153,4 +161,4 @@ try {
|
||||
// Silent fail — don't block session start over statusline detection
|
||||
}
|
||||
|
||||
process.stdout.write(output);
|
||||
writeHookOutput('SessionStart', mode, output);
|
||||
|
||||
@@ -2,12 +2,8 @@
|
||||
// ponytail — UserPromptSubmit hook to track which ponytail mode is active
|
||||
// Inspects user input for /ponytail commands and writes mode to flag file
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const os = require('os');
|
||||
const { getDefaultMode } = require('./ponytail-config');
|
||||
|
||||
const flagPath = path.join(os.homedir(), '.claude', '.ponytail-active');
|
||||
const { clearMode, setMode, writeHookOutput } = require('./ponytail-runtime');
|
||||
|
||||
let input = '';
|
||||
process.stdin.on('data', chunk => { input += chunk; });
|
||||
@@ -18,9 +14,9 @@ process.stdin.on('end', () => {
|
||||
const prompt = (data.prompt || '').trim().toLowerCase();
|
||||
|
||||
// Match /ponytail commands
|
||||
if (prompt.startsWith('/ponytail')) {
|
||||
if (/^[/@$]ponytail/.test(prompt)) {
|
||||
const parts = prompt.split(/\s+/);
|
||||
const cmd = parts[0]; // /ponytail, /ponytail-review, /ponytail:ponytail, etc.
|
||||
const cmd = parts[0].replace(/^[@$]/, '/');
|
||||
const arg = parts[1] || '';
|
||||
|
||||
let mode = null;
|
||||
@@ -36,16 +32,22 @@ process.stdin.on('end', () => {
|
||||
}
|
||||
|
||||
if (mode && mode !== 'off') {
|
||||
fs.mkdirSync(path.dirname(flagPath), { recursive: true });
|
||||
fs.writeFileSync(flagPath, mode);
|
||||
setMode(mode);
|
||||
writeHookOutput(
|
||||
'UserPromptSubmit',
|
||||
mode,
|
||||
'PONYTAIL MODE CHANGED — level: ' + mode,
|
||||
);
|
||||
} else if (mode === 'off') {
|
||||
try { fs.unlinkSync(flagPath); } catch (e) {}
|
||||
clearMode();
|
||||
writeHookOutput('UserPromptSubmit', 'off', 'PONYTAIL MODE OFF');
|
||||
}
|
||||
}
|
||||
|
||||
// Detect deactivation
|
||||
if (/\b(stop ponytail|normal mode)\b/i.test(prompt)) {
|
||||
try { fs.unlinkSync(flagPath); } catch (e) {}
|
||||
clearMode();
|
||||
writeHookOutput('UserPromptSubmit', 'off', 'PONYTAIL MODE OFF');
|
||||
}
|
||||
} catch (e) {
|
||||
// Silent fail
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const os = require('os');
|
||||
|
||||
const isCodex = Boolean(process.env.PLUGIN_DATA);
|
||||
const statePath = isCodex
|
||||
? path.join(process.env.PLUGIN_DATA, '.ponytail-active')
|
||||
: path.join(os.homedir(), '.claude', '.ponytail-active');
|
||||
|
||||
function setMode(mode) {
|
||||
fs.mkdirSync(path.dirname(statePath), { recursive: true });
|
||||
fs.writeFileSync(statePath, mode);
|
||||
}
|
||||
|
||||
function clearMode() {
|
||||
try { fs.unlinkSync(statePath); } catch (e) {}
|
||||
}
|
||||
|
||||
function writeHookOutput(event, mode, context = '') {
|
||||
if (!isCodex) {
|
||||
process.stdout.write(context);
|
||||
return;
|
||||
}
|
||||
const output = { systemMessage: `PONYTAIL:${mode.toUpperCase()}` };
|
||||
if (context) {
|
||||
output.hookSpecificOutput = {
|
||||
hookEventName: event,
|
||||
additionalContext: context,
|
||||
};
|
||||
}
|
||||
process.stdout.write(JSON.stringify(output));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
clearMode,
|
||||
isCodex,
|
||||
setMode,
|
||||
writeHookOutput,
|
||||
};
|
||||
Reference in New Issue
Block a user