@ranger-testing/ranger-cli 2.0.5 → 2.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cli.js +1 -914
- package/build/commands/addEnv.js +1 -1
- package/build/commands/authEncrypt.js +1 -36
- package/build/commands/clean.js +1 -1
- package/build/commands/config.js +1 -93
- package/build/commands/env.js +1 -98
- package/build/commands/feature.js +1 -653
- package/build/commands/hook.js +1 -33
- package/build/commands/hooks/autoPrompt.js +1 -32
- package/build/commands/hooks/disable.js +1 -33
- package/build/commands/hooks/enable.js +1 -58
- package/build/commands/hooks/exitPlanMode.js +1 -35
- package/build/commands/hooks/index.js +1 -12
- package/build/commands/hooks/output.js +1 -71
- package/build/commands/hooks/planReminder.js +1 -46
- package/build/commands/hooks/planStart.js +1 -30
- package/build/commands/hooks/postEdit.js +1 -43
- package/build/commands/hooks/preCompact.js +1 -30
- package/build/commands/hooks/sessionEnd.js +1 -25
- package/build/commands/hooks/sessionStart.js +1 -93
- package/build/commands/hooks/stopHook.js +1 -155
- package/build/commands/index.js +1 -12
- package/build/commands/login.js +1 -26
- package/build/commands/setupCi.js +1 -189
- package/build/commands/skillup.js +1 -80
- package/build/commands/start.js +1 -1
- package/build/commands/status.js +1 -198
- package/build/commands/update.js +1 -182
- package/build/commands/updateEnv.js +1 -1
- package/build/commands/useEnv.js +1 -1
- package/build/commands/utils/activeProfile.js +1 -76
- package/build/commands/utils/browserSessionsApi.js +1 -1
- package/build/commands/utils/claudeConfig.js +1 -73
- package/build/commands/utils/claudePlugin.js +1 -85
- package/build/commands/utils/crypto.js +1 -42
- package/build/commands/utils/desirePathLog.js +1 -139
- package/build/commands/utils/deviceAuth.js +1 -232
- package/build/commands/utils/environment.js +1 -65
- package/build/commands/utils/featureApi.js +1 -371
- package/build/commands/utils/featureReportGenerator.js +1 -204
- package/build/commands/utils/fixWebmDuration.js +1 -0
- package/build/commands/utils/git.js +1 -44
- package/build/commands/utils/keychain.js +1 -1
- package/build/commands/utils/localAgentInstallationsApi.js +1 -1
- package/build/commands/utils/profileMessages.js +1 -8
- package/build/commands/utils/profileSetupBanner.js +1 -167
- package/build/commands/utils/rangerRoot.js +1 -60
- package/build/commands/utils/reportGenerator.js +1 -130
- package/build/commands/utils/retry.js +1 -25
- package/build/commands/utils/sessionCache.js +1 -299
- package/build/commands/utils/settings.js +1 -313
- package/build/commands/utils/skillContent.js +1 -28
- package/build/commands/utils/skills.js +1 -1
- package/build/commands/utils/telemetry.js +1 -254
- package/build/commands/utils/userApi.js +1 -32
- package/build/commands/utils/version.js +1 -62
- package/build/commands/verifyFeature.js +1 -1343
- package/build/commands/verifyInBrowser.js +1 -1
- package/package.json +4 -1
- package/build/cli.js.map +0 -1
- package/build/commands/addEnv.js.map +0 -1
- package/build/commands/authEncrypt.js.map +0 -1
- package/build/commands/clean.js.map +0 -1
- package/build/commands/config.js.map +0 -1
- package/build/commands/env.js.map +0 -1
- package/build/commands/feature.js.map +0 -1
- package/build/commands/hook.js.map +0 -1
- package/build/commands/hooks/autoPrompt.js.map +0 -1
- package/build/commands/hooks/disable.js.map +0 -1
- package/build/commands/hooks/enable.js.map +0 -1
- package/build/commands/hooks/exitPlanMode.js.map +0 -1
- package/build/commands/hooks/index.js.map +0 -1
- package/build/commands/hooks/output.js.map +0 -1
- package/build/commands/hooks/planReminder.js.map +0 -1
- package/build/commands/hooks/planStart.js.map +0 -1
- package/build/commands/hooks/postEdit.js.map +0 -1
- package/build/commands/hooks/preCompact.js.map +0 -1
- package/build/commands/hooks/sessionEnd.js.map +0 -1
- package/build/commands/hooks/sessionStart.js.map +0 -1
- package/build/commands/hooks/stopHook.js.map +0 -1
- package/build/commands/index.js.map +0 -1
- package/build/commands/login.js.map +0 -1
- package/build/commands/setupCi.js.map +0 -1
- package/build/commands/skillup.js.map +0 -1
- package/build/commands/start.js.map +0 -1
- package/build/commands/status.js.map +0 -1
- package/build/commands/update.js.map +0 -1
- package/build/commands/updateEnv.js.map +0 -1
- package/build/commands/useEnv.js.map +0 -1
- package/build/commands/utils/activeProfile.js.map +0 -1
- package/build/commands/utils/browserSessionsApi.js.map +0 -1
- package/build/commands/utils/claudeConfig.js.map +0 -1
- package/build/commands/utils/claudePlugin.js.map +0 -1
- package/build/commands/utils/crypto.js.map +0 -1
- package/build/commands/utils/desirePathLog.js.map +0 -1
- package/build/commands/utils/deviceAuth.js.map +0 -1
- package/build/commands/utils/environment.js.map +0 -1
- package/build/commands/utils/featureApi.js.map +0 -1
- package/build/commands/utils/featureReportGenerator.js.map +0 -1
- package/build/commands/utils/git.js.map +0 -1
- package/build/commands/utils/keychain.js.map +0 -1
- package/build/commands/utils/localAgentInstallationsApi.js.map +0 -1
- package/build/commands/utils/profileMessages.js.map +0 -1
- package/build/commands/utils/profileSetupBanner.js.map +0 -1
- package/build/commands/utils/rangerRoot.js.map +0 -1
- package/build/commands/utils/reportGenerator.js.map +0 -1
- package/build/commands/utils/retry.js.map +0 -1
- package/build/commands/utils/sessionCache.js.map +0 -1
- package/build/commands/utils/settings.js.map +0 -1
- package/build/commands/utils/skillContent.js.map +0 -1
- package/build/commands/utils/skills.js.map +0 -1
- package/build/commands/utils/telemetry.js.map +0 -1
- package/build/commands/utils/userApi.js.map +0 -1
- package/build/commands/utils/version.js.map +0 -1
- package/build/commands/verifyFeature.js.map +0 -1
- package/build/commands/verifyInBrowser.js.map +0 -1
package/build/commands/hook.js
CHANGED
|
@@ -1,33 +1 @@
|
|
|
1
|
-
|
|
2
|
-
const HOOKS = {
|
|
3
|
-
'session-start': sessionStart,
|
|
4
|
-
'session-end': sessionEnd,
|
|
5
|
-
'pre-compact': preCompact,
|
|
6
|
-
'post-edit': postEdit,
|
|
7
|
-
'plan-start': planStart,
|
|
8
|
-
'plan-reminder': planReminder,
|
|
9
|
-
'exit-plan-mode': exitPlanMode,
|
|
10
|
-
stop: stopHook,
|
|
11
|
-
enable: enable,
|
|
12
|
-
disable: disable,
|
|
13
|
-
'auto-prompt': autoPrompt,
|
|
14
|
-
};
|
|
15
|
-
/**
|
|
16
|
-
* Unified hook command handler.
|
|
17
|
-
* Routes to the appropriate hook based on the --name parameter.
|
|
18
|
-
*
|
|
19
|
-
* When sessionId is provided (via --session-id flag), it is passed through
|
|
20
|
-
* to the hook function, bypassing stdin/env-based session ID resolution.
|
|
21
|
-
* This is used by non-Claude integrations like OpenCode.
|
|
22
|
-
*/
|
|
23
|
-
export async function hook(name, sessionId) {
|
|
24
|
-
const hookFn = HOOKS[name];
|
|
25
|
-
if (!hookFn) {
|
|
26
|
-
const validNames = Object.keys(HOOKS).join(', ');
|
|
27
|
-
console.error(`Unknown hook: ${name}`);
|
|
28
|
-
console.error(`Valid hooks: ${validNames}`);
|
|
29
|
-
process.exit(1);
|
|
30
|
-
}
|
|
31
|
-
await hookFn(sessionId);
|
|
32
|
-
}
|
|
33
|
-
//# sourceMappingURL=hook.js.map
|
|
1
|
+
function _0x5daf(_0xa722a6,_0x4b3c1f){_0xa722a6=_0xa722a6-0x178;const _0x5e1260=_0x5e12();let _0x5daf83=_0x5e1260[_0xa722a6];return _0x5daf83;}(function(_0x3dde39,_0x5d1dbf){const _0x2034c7=_0x5daf,_0x5a137a=_0x3dde39();while(!![]){try{const _0x31e5ca=-parseInt(_0x2034c7(0x184))/0x1*(parseInt(_0x2034c7(0x178))/0x2)+parseInt(_0x2034c7(0x17e))/0x3+-parseInt(_0x2034c7(0x179))/0x4*(-parseInt(_0x2034c7(0x183))/0x5)+-parseInt(_0x2034c7(0x181))/0x6*(-parseInt(_0x2034c7(0x17f))/0x7)+parseInt(_0x2034c7(0x185))/0x8+-parseInt(_0x2034c7(0x186))/0x9*(-parseInt(_0x2034c7(0x182))/0xa)+parseInt(_0x2034c7(0x17d))/0xb*(-parseInt(_0x2034c7(0x180))/0xc);if(_0x31e5ca===_0x5d1dbf)break;else _0x5a137a['push'](_0x5a137a['shift']());}catch(_0x534f30){_0x5a137a['push'](_0x5a137a['shift']());}}}(_0x5e12,0xaa065));import{sessionStart,sessionEnd,preCompact,postEdit,planStart,planReminder,exitPlanMode,stopHook,enable,disable,autoPrompt}from'./hooks/index.js';function _0x5e12(){const _0x1639fb=['675990ivDNoh','join','2242558LvvwuI','40GSJYRI','exit','keys','error','484CrWlce','2347041PZlxgb','297185ZrLYZT','346044QEknmV','42eXxcmB','100edKUoA','336290VQSVQi','1lIhMAm','4666528juYZhI'];_0x5e12=function(){return _0x1639fb;};return _0x5e12();}const HOOKS={'session-start':sessionStart,'session-end':sessionEnd,'pre-compact':preCompact,'post-edit':postEdit,'plan-start':planStart,'plan-reminder':planReminder,'exit-plan-mode':exitPlanMode,'stop':stopHook,'enable':enable,'disable':disable,'auto-prompt':autoPrompt};export async function hook(_0x42ec7a,_0x10e525){const _0x32e667=_0x5daf,_0x558179={'eKEkb':function(_0x30d56e,_0x2e0a6f){return _0x30d56e(_0x2e0a6f);}},_0x3049d0=HOOKS[_0x42ec7a];if(!_0x3049d0){const _0x1a7941=Object[_0x32e667(0x17b)](HOOKS)[_0x32e667(0x187)](',\x20');console['error']('Unknown\x20hook:\x20'+_0x42ec7a),console[_0x32e667(0x17c)]('Valid\x20hooks:\x20'+_0x1a7941),process[_0x32e667(0x17a)](0x1);}await _0x558179['eKEkb'](_0x3049d0,_0x10e525);}
|
|
@@ -1,32 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { isSessionEnabled, hasSessionBeenPrompted, markSessionPrompted, } from '../utils/sessionCache.js';
|
|
3
|
-
const AUTO_PROMPT_TEXT = `
|
|
4
|
-
🚨 🚨 [ACTION REQUIRED] 🚨 🚨
|
|
5
|
-
Before responding to the user's message, consider whether this task will involve ANY frontend, UI, or browser work.
|
|
6
|
-
If so, you MUST first ask them:
|
|
7
|
-
"Would you like to enable Ranger Feature Review for this session? It verifies feature review scenarios and user workflows in a real browser while Claude works."
|
|
8
|
-
Asking this question is ABSOLUTELY ESSENTIAL. DO NOT SKIP THIS STEP.
|
|
9
|
-
If they say yes, run \`ranger hook enable\` (Bash tool).
|
|
10
|
-
If they say no, say "Sounds good. If you change your mind, you can enable it with /ranger:enable" and then proceed with their request.
|
|
11
|
-
This is mandatory — do not skip this step.`;
|
|
12
|
-
/**
|
|
13
|
-
* UserPromptSubmit hook that prompts Claude to ask the user about enabling Ranger.
|
|
14
|
-
* Only fires once per session (on the first prompt), and only when Ranger is not already enabled.
|
|
15
|
-
*
|
|
16
|
-
* Outputs plain text (not JSON) because UserPromptSubmit plain stdout is added as
|
|
17
|
-
* visible context in the transcript, while JSON additionalContext is added "more
|
|
18
|
-
* discretely" and Claude tends to ignore it.
|
|
19
|
-
*/
|
|
20
|
-
export async function autoPrompt() {
|
|
21
|
-
const input = await readHookInput();
|
|
22
|
-
const sessionId = input?.session_id;
|
|
23
|
-
if (!sessionId)
|
|
24
|
-
return;
|
|
25
|
-
if (isSessionEnabled(sessionId) || hasSessionBeenPrompted(sessionId))
|
|
26
|
-
return;
|
|
27
|
-
markSessionPrompted(sessionId);
|
|
28
|
-
// Plain text stdout from UserPromptSubmit is added as visible context for Claude.
|
|
29
|
-
// This is more prominent than JSON additionalContext which is injected "discretely".
|
|
30
|
-
console.log(AUTO_PROMPT_TEXT);
|
|
31
|
-
}
|
|
32
|
-
//# sourceMappingURL=autoPrompt.js.map
|
|
1
|
+
const _0x5e93b2=_0x610c;(function(_0x374dff,_0x5b69ac){const _0x3ffc66=_0x610c,_0x2a3a07=_0x374dff();while(!![]){try{const _0x358391=-parseInt(_0x3ffc66(0xa7))/0x1+parseInt(_0x3ffc66(0xa2))/0x2*(parseInt(_0x3ffc66(0xa8))/0x3)+-parseInt(_0x3ffc66(0x9e))/0x4*(-parseInt(_0x3ffc66(0xa1))/0x5)+-parseInt(_0x3ffc66(0xa6))/0x6+parseInt(_0x3ffc66(0xa0))/0x7*(parseInt(_0x3ffc66(0x9d))/0x8)+parseInt(_0x3ffc66(0xa5))/0x9+parseInt(_0x3ffc66(0x9f))/0xa;if(_0x358391===_0x5b69ac)break;else _0x2a3a07['push'](_0x2a3a07['shift']());}catch(_0x301353){_0x2a3a07['push'](_0x2a3a07['shift']());}}}(_0x5e1a,0xebfc5));function _0x610c(_0x47be4c,_0x3931c3){_0x47be4c=_0x47be4c-0x9d;const _0x5e1a0c=_0x5e1a();let _0x610ccc=_0x5e1a0c[_0x47be4c];return _0x610ccc;}import{readHookInput}from'./output.js';import{isSessionEnabled,hasSessionBeenPrompted,markSessionPrompted}from'../utils/sessionCache.js';const AUTO_PROMPT_TEXT=_0x5e93b2(0xa4);function _0x5e1a(){const _0x2c2a11=['412615BKJcTU','14426HohQkl','log','\x0a🚨\x20🚨\x20[ACTION\x20REQUIRED]\x20🚨\x20🚨\x0aBefore\x20responding\x20to\x20the\x20user\x27s\x20message,\x20consider\x20whether\x20this\x20task\x20will\x20involve\x20ANY\x20frontend,\x20UI,\x20or\x20browser\x20work.\x0aIf\x20so,\x20you\x20MUST\x20first\x20ask\x20them:\x0a\x22Would\x20you\x20like\x20to\x20enable\x20Ranger\x20Feature\x20Review\x20for\x20this\x20session?\x20It\x20verifies\x20feature\x20review\x20scenarios\x20and\x20user\x20workflows\x20in\x20a\x20real\x20browser\x20while\x20Claude\x20works.\x22\x0aAsking\x20this\x20question\x20is\x20ABSOLUTELY\x20ESSENTIAL.\x20DO\x20NOT\x20SKIP\x20THIS\x20STEP.\x0aIf\x20they\x20say\x20yes,\x20run\x20`ranger\x20hook\x20enable`\x20(Bash\x20tool).\x0aIf\x20they\x20say\x20no,\x20say\x20\x22Sounds\x20good.\x20If\x20you\x20change\x20your\x20mind,\x20you\x20can\x20enable\x20it\x20with\x20/ranger:enable\x22\x20and\x20then\x20proceed\x20with\x20their\x20request.\x0aThis\x20is\x20mandatory\x20—\x20do\x20not\x20skip\x20this\x20step.','4205259kVlWef','5835402KufWty','865138DHSBHC','111MqWrFd','7495352IsfzYn','24yeyyMz','6381130DREqbh','7OZAnsk'];_0x5e1a=function(){return _0x2c2a11;};return _0x5e1a();}export async function autoPrompt(){const _0x4b654b=_0x5e93b2,_0x1cb3a9={'ImLsr':function(_0x4fb3ce){return _0x4fb3ce();},'hkDMq':function(_0x13b1e8,_0x3d07de){return _0x13b1e8(_0x3d07de);}},_0x400915=await _0x1cb3a9['ImLsr'](readHookInput),_0x14026d=_0x400915?.['session_id'];if(!_0x14026d)return;if(isSessionEnabled(_0x14026d)||hasSessionBeenPrompted(_0x14026d))return;_0x1cb3a9['hkDMq'](markSessionPrompted,_0x14026d),console[_0x4b654b(0xa3)](AUTO_PROMPT_TEXT);}
|
|
@@ -1,33 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { printBlock } from './output.js';
|
|
3
|
-
/**
|
|
4
|
-
* Disable hook - disables Ranger hooks for the current session and current branch.
|
|
5
|
-
* Session ID is resolved from the optional parameter (OpenCode --session-id),
|
|
6
|
-
* falling back to CLAUDE_SESSION_ID env var (Claude Code).
|
|
7
|
-
*/
|
|
8
|
-
export async function disable(sessionIdOverride) {
|
|
9
|
-
const sessionId = sessionIdOverride || process.env.CLAUDE_SESSION_ID || '';
|
|
10
|
-
if (!sessionId) {
|
|
11
|
-
console.error('Error: No session ID available.');
|
|
12
|
-
console.error('Provide --session-id or ensure CLAUDE_SESSION_ID is set.');
|
|
13
|
-
process.exit(1);
|
|
14
|
-
}
|
|
15
|
-
// Disable hooks for this session
|
|
16
|
-
disableSession(sessionId);
|
|
17
|
-
// Also disable the current branch if not on main/master
|
|
18
|
-
const branch = getCurrentBranch();
|
|
19
|
-
if (branch && branch !== 'main' && branch !== 'master') {
|
|
20
|
-
disableBranch(branch);
|
|
21
|
-
}
|
|
22
|
-
printBlock(`# RANGER DISABLED
|
|
23
|
-
|
|
24
|
-
The user has expressly disabled Ranger hooks for this session${branch && branch !== 'main' && branch !== 'master' ? ` and branch '${branch}'` : ''}.
|
|
25
|
-
|
|
26
|
-
**IMPORTANT INSTRUCTIONS:**
|
|
27
|
-
- Do NOT use the /ranger skill
|
|
28
|
-
- Do NOT use any \`ranger\` CLI commands
|
|
29
|
-
- Proceed with your task without tracking feature reviews using the Ranger CLI
|
|
30
|
-
|
|
31
|
-
To re-enable Ranger, run \`/ranger:enable\`.`);
|
|
32
|
-
}
|
|
33
|
-
//# sourceMappingURL=disable.js.map
|
|
1
|
+
function _0x3d87(){const _0x407032=['error','master','CLAUDE_SESSION_ID','9jlzpkN','9753iZjfXd','678PLFjzc','#\x20RANGER\x20DISABLED\x0a\x0aThe\x20user\x20has\x20expressly\x20disabled\x20Ranger\x20hooks\x20for\x20this\x20session','50195aarQoT','mNTUg','Error:\x20No\x20session\x20ID\x20available.','192486TaaiRg','8197040iXhKrr','main','XNzgc','1674368XNrskn','1287811kFEXAG','env','148skFwqn','\x20and\x20branch\x20\x27','46772800qpvxwh'];_0x3d87=function(){return _0x407032;};return _0x3d87();}(function(_0x3bcd70,_0x4a8794){const _0x6d4eb4=_0x3a0b,_0x20a836=_0x3bcd70();while(!![]){try{const _0x4a2329=-parseInt(_0x6d4eb4(0xba))/0x1+parseInt(_0x6d4eb4(0xb6))/0x2+-parseInt(_0x6d4eb4(0xb0))/0x3*(-parseInt(_0x6d4eb4(0xa9))/0x4)+parseInt(_0x6d4eb4(0xb3))/0x5*(-parseInt(_0x6d4eb4(0xb1))/0x6)+-parseInt(_0x6d4eb4(0xa7))/0x7+-parseInt(_0x6d4eb4(0xb7))/0x8*(parseInt(_0x6d4eb4(0xaf))/0x9)+parseInt(_0x6d4eb4(0xab))/0xa;if(_0x4a2329===_0x4a8794)break;else _0x20a836['push'](_0x20a836['shift']());}catch(_0x46e811){_0x20a836['push'](_0x20a836['shift']());}}}(_0x3d87,0xd5f90));import{disableSession,disableBranch,getCurrentBranch}from'../utils/sessionCache.js';function _0x3a0b(_0x149c90,_0x427dab){_0x149c90=_0x149c90-0xa7;const _0x3d876d=_0x3d87();let _0x3a0bb7=_0x3d876d[_0x149c90];return _0x3a0bb7;}import{printBlock}from'./output.js';export async function disable(_0x10b168){const _0x27c4f1=_0x3a0b,_0x3706c8={'XNzgc':'Provide\x20--session-id\x20or\x20ensure\x20CLAUDE_SESSION_ID\x20is\x20set.','UDrmp':function(_0x11515c){return _0x11515c();},'mNTUg':'main','nSoMS':function(_0x5c8f71,_0x635336){return _0x5c8f71!==_0x635336;}},_0x338033=_0x10b168||process[_0x27c4f1(0xa8)][_0x27c4f1(0xae)]||'';!_0x338033&&(console[_0x27c4f1(0xac)](_0x27c4f1(0xb5)),console['error'](_0x3706c8[_0x27c4f1(0xb9)]),process['exit'](0x1));disableSession(_0x338033);const _0x37256a=_0x3706c8['UDrmp'](getCurrentBranch);_0x37256a&&_0x37256a!==_0x3706c8[_0x27c4f1(0xb4)]&&_0x37256a!=='master'&&disableBranch(_0x37256a),printBlock(_0x27c4f1(0xb2)+(_0x37256a&&_0x3706c8['nSoMS'](_0x37256a,_0x27c4f1(0xb8))&&_0x37256a!==_0x27c4f1(0xad)?_0x27c4f1(0xaa)+_0x37256a+'\x27':'')+'.\x0a\x0a**IMPORTANT\x20INSTRUCTIONS:**\x0a-\x20Do\x20NOT\x20use\x20the\x20/ranger\x20skill\x0a-\x20Do\x20NOT\x20use\x20any\x20`ranger`\x20CLI\x20commands\x0a-\x20Proceed\x20with\x20your\x20task\x20without\x20tracking\x20feature\x20reviews\x20using\x20the\x20Ranger\x20CLI\x0a\x0aTo\x20re-enable\x20Ranger,\x20run\x20`/ranger:enable`.');}
|
|
@@ -1,58 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { getToken } from '../utils/keychain.js';
|
|
3
|
-
import { getRangerSkillContent } from '../utils/skillContent.js';
|
|
4
|
-
import { printBlock } from './output.js';
|
|
5
|
-
import { update } from '../update.js';
|
|
6
|
-
/**
|
|
7
|
-
* Enable hook - enables Ranger hooks for the current session.
|
|
8
|
-
* Session ID is resolved from the optional parameter (OpenCode --session-id),
|
|
9
|
-
* falling back to CLAUDE_SESSION_ID env var (Claude Code).
|
|
10
|
-
*/
|
|
11
|
-
export async function enable(sessionIdOverride) {
|
|
12
|
-
const sessionId = sessionIdOverride || process.env.CLAUDE_SESSION_ID || '';
|
|
13
|
-
if (!sessionId) {
|
|
14
|
-
console.error('Error: No session ID available.');
|
|
15
|
-
console.error('Provide --session-id or ensure CLAUDE_SESSION_ID is set.');
|
|
16
|
-
process.exit(1);
|
|
17
|
-
}
|
|
18
|
-
// Check if CLI is configured (has token)
|
|
19
|
-
const token = await getToken();
|
|
20
|
-
if (!token) {
|
|
21
|
-
printBlock(`# RANGER SETUP REQUIRED
|
|
22
|
-
|
|
23
|
-
The Ranger CLI is not configured. To get started:
|
|
24
|
-
|
|
25
|
-
1. Install: \`npm install -g @ranger-testing/ranger-cli\`
|
|
26
|
-
2. Get token: https://dashboard.ranger.net/cli
|
|
27
|
-
3. Initialize: \`ranger setup [token]\`
|
|
28
|
-
|
|
29
|
-
Restart your Claude Code session after setup.`);
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
// Run ranger update to ensure CLI and skills are up to date
|
|
33
|
-
try {
|
|
34
|
-
await update();
|
|
35
|
-
}
|
|
36
|
-
catch {
|
|
37
|
-
// Non-fatal — don't block hook enablement if update check fails
|
|
38
|
-
}
|
|
39
|
-
// Enable hooks for this session (and auto-enable branch if not on main)
|
|
40
|
-
enableSession(sessionId);
|
|
41
|
-
const branch = getCurrentBranch();
|
|
42
|
-
const branchNote = branch && branch !== 'main' && branch !== 'master'
|
|
43
|
-
? `\n\n**Branch '${branch}' is now enabled** - Ranger will stay active on this branch across sessions.`
|
|
44
|
-
: '';
|
|
45
|
-
// Output the skill prompt
|
|
46
|
-
const skillContent = getRangerSkillContent();
|
|
47
|
-
printBlock(`# RANGER ENABLED${branchNote}
|
|
48
|
-
|
|
49
|
-
**For ANY UI work, you MUST use the /ranger skill.**
|
|
50
|
-
|
|
51
|
-
${skillContent}
|
|
52
|
-
|
|
53
|
-
## Quick Reference
|
|
54
|
-
|
|
55
|
-
**In plan mode:** Include Ranger Feature Review Specification at end of plan.
|
|
56
|
-
**Not in plan mode:** Run \`ranger create\` FIRST, then verify with \`ranger go\`.`);
|
|
57
|
-
}
|
|
58
|
-
//# sourceMappingURL=enable.js.map
|
|
1
|
+
(function(_0x4b2471,_0x430db7){const _0x4199dd=_0x4cd5,_0x4256d6=_0x4b2471();while(!![]){try{const _0x375c8c=-parseInt(_0x4199dd(0x1a2))/0x1*(parseInt(_0x4199dd(0x1ad))/0x2)+-parseInt(_0x4199dd(0x1b0))/0x3+parseInt(_0x4199dd(0x1b3))/0x4+parseInt(_0x4199dd(0x1a6))/0x5*(parseInt(_0x4199dd(0x1a8))/0x6)+parseInt(_0x4199dd(0x1b1))/0x7+-parseInt(_0x4199dd(0x1aa))/0x8*(parseInt(_0x4199dd(0x1a7))/0x9)+parseInt(_0x4199dd(0x1a3))/0xa;if(_0x375c8c===_0x430db7)break;else _0x4256d6['push'](_0x4256d6['shift']());}catch(_0x3fae12){_0x4256d6['push'](_0x4256d6['shift']());}}}(_0x1834,0x997bb));import{enableSession,getCurrentBranch}from'../utils/sessionCache.js';import{getToken}from'../utils/keychain.js';import{getRangerSkillContent}from'../utils/skillContent.js';import{printBlock}from'./output.js';function _0x1834(){const _0x100e90=['SDecN','470666hmGaHI','Ouhgp','error','2255670PalptH','4527117BFtTGU','main','1025820RtEKuc','CLAUDE_SESSION_ID','\x0a\x0a##\x20Quick\x20Reference\x0a\x0a**In\x20plan\x20mode:**\x20Include\x20Ranger\x20Feature\x20Review\x20Specification\x20at\x20end\x20of\x20plan.\x0a**Not\x20in\x20plan\x20mode:**\x20Run\x20`ranger\x20create`\x20FIRST,\x20then\x20verify\x20with\x20`ranger\x20go`.','2QldsmC','7394810HxlyXN','env','IpjsO','605DGwZVV','938403aPeYci','56874ZptJvF','Provide\x20--session-id\x20or\x20ensure\x20CLAUDE_SESSION_ID\x20is\x20set.','72BuqSGT','#\x20RANGER\x20SETUP\x20REQUIRED\x0a\x0aThe\x20Ranger\x20CLI\x20is\x20not\x20configured.\x20To\x20get\x20started:\x0a\x0a1.\x20Install:\x20`npm\x20install\x20-g\x20@ranger-testing/ranger-cli`\x0a2.\x20Run:\x20`ranger\x20setup`\x0a\x0aA\x20browser\x20will\x20open\x20for\x20authentication.\x20A\x20human\x20needs\x20to\x20complete\x20the\x20login.\x0aRestart\x20your\x20Claude\x20Code\x20session\x20after\x20setup.'];_0x1834=function(){return _0x100e90;};return _0x1834();}import{update}from'../update.js';function _0x4cd5(_0x37a4af,_0x20f14e){_0x37a4af=_0x37a4af-0x1a1;const _0x18342f=_0x1834();let _0x4cd561=_0x18342f[_0x37a4af];return _0x4cd561;}export async function enable(_0x31bc08){const _0x9fd898=_0x4cd5,_0x15f713={'lpPfs':'Error:\x20No\x20session\x20ID\x20available.','Ouhgp':_0x9fd898(0x1a9),'IpjsO':function(_0x4eae4c){return _0x4eae4c();},'SDecN':function(_0x499cd5){return _0x499cd5();},'tbeaH':function(_0x2e9558,_0x3dd847){return _0x2e9558!==_0x3dd847;},'GEpWf':'master','yWoxv':function(_0x633544){return _0x633544();},'esXFc':function(_0x254427,_0x5beb4b){return _0x254427(_0x5beb4b);}},_0x24d01b=_0x31bc08||process[_0x9fd898(0x1a4)][_0x9fd898(0x1b4)]||'';!_0x24d01b&&(console[_0x9fd898(0x1af)](_0x15f713['lpPfs']),console[_0x9fd898(0x1af)](_0x15f713[_0x9fd898(0x1ae)]),process['exit'](0x1));const _0x4bdc6d=await getToken();if(!_0x4bdc6d){printBlock(_0x9fd898(0x1ab));return;}try{await _0x15f713[_0x9fd898(0x1a5)](update);}catch{}enableSession(_0x24d01b);const _0x447181=_0x15f713[_0x9fd898(0x1ac)](getCurrentBranch),_0x35fa9f=_0x447181&&_0x447181!==_0x9fd898(0x1b2)&&_0x15f713['tbeaH'](_0x447181,_0x15f713['GEpWf'])?'\x0a\x0a**Branch\x20\x27'+_0x447181+'\x27\x20is\x20now\x20enabled**\x20-\x20Ranger\x20will\x20stay\x20active\x20on\x20this\x20branch\x20across\x20sessions.':'',_0x33f11b=_0x15f713['yWoxv'](getRangerSkillContent);_0x15f713['esXFc'](printBlock,'#\x20RANGER\x20ENABLED'+_0x35fa9f+'\x0a\x0a**For\x20ANY\x20UI\x20work,\x20you\x20MUST\x20use\x20the\x20/ranger\x20skill.**\x0a\x0a'+_0x33f11b+_0x9fd898(0x1a1));}
|
|
@@ -1,35 +1 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* PermissionRequest hook handler for ExitPlanMode
|
|
4
|
-
*
|
|
5
|
-
* This command is invoked when Claude requests permission to exit plan mode.
|
|
6
|
-
* It reminds Claude to create a Ranger feature review to track the work.
|
|
7
|
-
*/
|
|
8
|
-
export async function exitPlanMode(sessionIdOverride) {
|
|
9
|
-
const sessionId = await getEnabledSessionId(sessionIdOverride);
|
|
10
|
-
if (!sessionId) {
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
printBlock(`=== RANGER: CREATE FEATURE REVIEW NOW ===
|
|
14
|
-
|
|
15
|
-
You are about to exit plan mode. If your plan includes UI changes:
|
|
16
|
-
|
|
17
|
-
**ACTION REQUIRED:** Create the Ranger feature review using scenarios from your Ranger Feature Review Specification:
|
|
18
|
-
|
|
19
|
-
\`\`\`
|
|
20
|
-
ranger create "<Feature Review Name from plan>" \\
|
|
21
|
-
-d "<Description from plan>" \\
|
|
22
|
-
-c "<Scenario 1 from plan>" \\
|
|
23
|
-
-c "<Scenario 2 from plan>"
|
|
24
|
-
\`\`\`
|
|
25
|
-
|
|
26
|
-
**REMINDER:** Scenarios must be E2E user flows, NOT implementation tasks.
|
|
27
|
-
|
|
28
|
-
**Good:** "User can log in with valid credentials and see dashboard"
|
|
29
|
-
**Bad:** "Add form validation" or "API returns 200"
|
|
30
|
-
|
|
31
|
-
If you did NOT include a Ranger Feature Review Specification in your plan, go back and add one before proceeding. See /ranger and create.md for guidance.
|
|
32
|
-
|
|
33
|
-
=== END ===`);
|
|
34
|
-
}
|
|
35
|
-
//# sourceMappingURL=exitPlanMode.js.map
|
|
1
|
+
(function(_0x3be490,_0x1d2a15){const _0x29735e=_0x5557,_0x58610e=_0x3be490();while(!![]){try{const _0x35400a=parseInt(_0x29735e(0x1e2))/0x1*(-parseInt(_0x29735e(0x1e5))/0x2)+parseInt(_0x29735e(0x1dd))/0x3*(parseInt(_0x29735e(0x1e1))/0x4)+parseInt(_0x29735e(0x1dc))/0x5*(parseInt(_0x29735e(0x1e3))/0x6)+parseInt(_0x29735e(0x1e0))/0x7+parseInt(_0x29735e(0x1db))/0x8+-parseInt(_0x29735e(0x1de))/0x9*(-parseInt(_0x29735e(0x1df))/0xa)+-parseInt(_0x29735e(0x1da))/0xb;if(_0x35400a===_0x1d2a15)break;else _0x58610e['push'](_0x58610e['shift']());}catch(_0x1cca75){_0x58610e['push'](_0x58610e['shift']());}}}(_0x22eb,0x1a21d));function _0x5557(_0x20f0b3,_0x315d71){_0x20f0b3=_0x20f0b3-0x1da;const _0x22eb1c=_0x22eb();let _0x555784=_0x22eb1c[_0x20f0b3];return _0x555784;}import{printBlock,getEnabledSessionId}from'./output.js';function _0x22eb(){const _0x51e32c=['70nIWjNQ','6yPpQIG','99BqXgyg','141140isWaAN','14161TdAADi','318876mEKPma','1txORDF','85938IFPqwv','===\x20RANGER:\x20CREATE\x20FEATURE\x20REVIEW\x20NOW\x20===\x0a\x0aYou\x20are\x20about\x20to\x20exit\x20plan\x20mode.\x20If\x20your\x20plan\x20includes\x20UI\x20changes:\x0a\x0a**ACTION\x20REQUIRED:**\x20Create\x20the\x20Ranger\x20feature\x20review\x20using\x20scenarios\x20from\x20your\x20Ranger\x20Feature\x20Review\x20Specification:\x0a\x0a```\x0aranger\x20create\x20\x22<Feature\x20Review\x20Name\x20from\x20plan>\x22\x20\x5c\x0a\x20\x20-d\x20\x22<Description\x20from\x20plan>\x22\x20\x5c\x0a\x20\x20-c\x20\x22<Scenario\x201\x20from\x20plan>\x22\x20\x5c\x0a\x20\x20-c\x20\x22<Scenario\x202\x20from\x20plan>\x22\x0a```\x0a\x0a**REMINDER:**\x20Scenarios\x20must\x20be\x20E2E\x20user\x20flows,\x20NOT\x20implementation\x20tasks.\x0a\x0a**Good:**\x20\x22User\x20can\x20log\x20in\x20with\x20valid\x20credentials\x20and\x20see\x20dashboard\x22\x0a**Bad:**\x20\x22Add\x20form\x20validation\x22\x20or\x20\x22API\x20returns\x20200\x22\x0a\x0aIf\x20you\x20did\x20NOT\x20include\x20a\x20Ranger\x20Feature\x20Review\x20Specification\x20in\x20your\x20plan,\x20go\x20back\x20and\x20add\x20one\x20before\x20proceeding.\x20See\x20/ranger\x20and\x20create.md\x20for\x20guidance.\x0a\x0a===\x20END\x20===','270154POisCl','5214539fBrdlI','1591408DNBrPg'];_0x22eb=function(){return _0x51e32c;};return _0x22eb();}export async function exitPlanMode(_0x3079d1){const _0x5aebfa=_0x5557,_0x5c791c=await getEnabledSessionId(_0x3079d1);if(!_0x5c791c)return;printBlock(_0x5aebfa(0x1e4));}
|
|
@@ -1,12 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { sessionEnd } from './sessionEnd.js';
|
|
3
|
-
export { preCompact } from './preCompact.js';
|
|
4
|
-
export { postEdit } from './postEdit.js';
|
|
5
|
-
export { planStart } from './planStart.js';
|
|
6
|
-
export { planReminder } from './planReminder.js';
|
|
7
|
-
export { exitPlanMode } from './exitPlanMode.js';
|
|
8
|
-
export { stopHook } from './stopHook.js';
|
|
9
|
-
export { enable } from './enable.js';
|
|
10
|
-
export { disable } from './disable.js';
|
|
11
|
-
export { autoPrompt } from './autoPrompt.js';
|
|
12
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
(function(_0x3947d5,_0x4ac657){var _0x4a07d5=_0x264b,_0x33ed22=_0x3947d5();while(!![]){try{var _0x29fa2d=parseInt(_0x4a07d5(0x13b))/0x1+-parseInt(_0x4a07d5(0x140))/0x2*(parseInt(_0x4a07d5(0x141))/0x3)+-parseInt(_0x4a07d5(0x139))/0x4+parseInt(_0x4a07d5(0x13e))/0x5*(-parseInt(_0x4a07d5(0x13a))/0x6)+parseInt(_0x4a07d5(0x13c))/0x7+-parseInt(_0x4a07d5(0x137))/0x8*(-parseInt(_0x4a07d5(0x138))/0x9)+-parseInt(_0x4a07d5(0x13f))/0xa*(-parseInt(_0x4a07d5(0x13d))/0xb);if(_0x29fa2d===_0x4ac657)break;else _0x33ed22['push'](_0x33ed22['shift']());}catch(_0x2429ba){_0x33ed22['push'](_0x33ed22['shift']());}}}(_0x36ff,0xe3454));export{sessionStart}from'./sessionStart.js';function _0x264b(_0x434ff1,_0x53e6fc){_0x434ff1=_0x434ff1-0x137;var _0x36ff1a=_0x36ff();var _0x264b00=_0x36ff1a[_0x434ff1];return _0x264b00;}export{sessionEnd}from'./sessionEnd.js';function _0x36ff(){var _0x597b6d=['55DfYnfQ','10yJJLDz','2342950QpBEfA','44918qeQbGD','45zyGmSu','162392lSavIi','324HKHwqe','4727636UMVMrG','3755094WmqyZJ','77047OcvUOM','12054742qIZYrY'];_0x36ff=function(){return _0x597b6d;};return _0x36ff();}export{preCompact}from'./preCompact.js';export{postEdit}from'./postEdit.js';export{planStart}from'./planStart.js';export{planReminder}from'./planReminder.js';export{exitPlanMode}from'./exitPlanMode.js';export{stopHook}from'./stopHook.js';export{enable}from'./enable.js';export{disable}from'./disable.js';export{autoPrompt}from'./autoPrompt.js';
|
|
@@ -1,71 +1 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* Helper utilities for hooks
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* Print a block of text with consistent formatting.
|
|
7
|
-
* Handles multi-line strings cleanly without repeated console.log calls.
|
|
8
|
-
*/
|
|
9
|
-
export function printBlock(text) {
|
|
10
|
-
console.log(text);
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Read and parse hook input from stdin.
|
|
14
|
-
* Returns null if parsing fails.
|
|
15
|
-
*/
|
|
16
|
-
export async function readHookInput() {
|
|
17
|
-
let input = '';
|
|
18
|
-
for await (const chunk of process.stdin) {
|
|
19
|
-
input += chunk;
|
|
20
|
-
}
|
|
21
|
-
try {
|
|
22
|
-
return JSON.parse(input);
|
|
23
|
-
}
|
|
24
|
-
catch {
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Read hook input and check if session is enabled.
|
|
30
|
-
* Returns session_id if enabled, null otherwise.
|
|
31
|
-
* Use this as the standard guard at the start of most hooks.
|
|
32
|
-
*
|
|
33
|
-
* When sessionIdOverride is provided (e.g. from --session-id flag for
|
|
34
|
-
* non-Claude integrations like OpenCode), stdin is not read.
|
|
35
|
-
*/
|
|
36
|
-
export async function getEnabledSessionId(sessionIdOverride) {
|
|
37
|
-
if (sessionIdOverride) {
|
|
38
|
-
return isSessionEnabled(sessionIdOverride) ? sessionIdOverride : null;
|
|
39
|
-
}
|
|
40
|
-
const input = await readHookInput();
|
|
41
|
-
const sessionId = input?.session_id;
|
|
42
|
-
if (!sessionId || !isSessionEnabled(sessionId)) {
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
return sessionId;
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Read hook input and return full context for hooks that need more data.
|
|
49
|
-
* Returns null if session not enabled.
|
|
50
|
-
*
|
|
51
|
-
* When sessionIdOverride is provided, stdin is not read and a synthetic
|
|
52
|
-
* HookInput is used (no permission_mode or other stdin-only fields).
|
|
53
|
-
*/
|
|
54
|
-
export async function getEnabledHookContext(sessionIdOverride) {
|
|
55
|
-
if (sessionIdOverride) {
|
|
56
|
-
if (!isSessionEnabled(sessionIdOverride)) {
|
|
57
|
-
return null;
|
|
58
|
-
}
|
|
59
|
-
return {
|
|
60
|
-
sessionId: sessionIdOverride,
|
|
61
|
-
input: { session_id: sessionIdOverride },
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
const input = await readHookInput();
|
|
65
|
-
const sessionId = input?.session_id;
|
|
66
|
-
if (!sessionId || !isSessionEnabled(sessionId)) {
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
return { sessionId, input };
|
|
70
|
-
}
|
|
71
|
-
//# sourceMappingURL=output.js.map
|
|
1
|
+
function _0x17d2(_0x1eadb4,_0x50e215){_0x1eadb4=_0x1eadb4-0x15c;const _0x3170d6=_0x3170();let _0x17d2ca=_0x3170d6[_0x1eadb4];return _0x17d2ca;}(function(_0x117ccc,_0x888729){const _0x2ba49f=_0x17d2,_0xf71623=_0x117ccc();while(!![]){try{const _0x3c2a83=parseInt(_0x2ba49f(0x15e))/0x1*(-parseInt(_0x2ba49f(0x163))/0x2)+-parseInt(_0x2ba49f(0x166))/0x3*(-parseInt(_0x2ba49f(0x160))/0x4)+-parseInt(_0x2ba49f(0x168))/0x5*(-parseInt(_0x2ba49f(0x164))/0x6)+parseInt(_0x2ba49f(0x16d))/0x7*(parseInt(_0x2ba49f(0x167))/0x8)+-parseInt(_0x2ba49f(0x162))/0x9+parseInt(_0x2ba49f(0x161))/0xa*(parseInt(_0x2ba49f(0x15c))/0xb)+-parseInt(_0x2ba49f(0x15f))/0xc;if(_0x3c2a83===_0x888729)break;else _0xf71623['push'](_0xf71623['shift']());}catch(_0x16cc4e){_0xf71623['push'](_0xf71623['shift']());}}}(_0x3170,0x1aa39));import{isSessionEnabled}from'../utils/sessionCache.js';export function printBlock(_0x34630a){const _0x92e303=_0x17d2;console[_0x92e303(0x16b)](_0x34630a);}export async function readHookInput(){const _0x2f83d1=_0x17d2;let _0x1a5c44='';for await(const _0x1ec3db of process[_0x2f83d1(0x16c)]){_0x1a5c44+=_0x1ec3db;}try{return JSON['parse'](_0x1a5c44);}catch{return null;}}export async function getEnabledSessionId(_0x2219d9){const _0x3ed6e2=_0x17d2,_0x44e149={'lRraj':function(_0x2be4ad,_0x51dc23){return _0x2be4ad(_0x51dc23);},'dELDA':function(_0x2f6b5f){return _0x2f6b5f();}};if(_0x2219d9)return _0x44e149['lRraj'](isSessionEnabled,_0x2219d9)?_0x2219d9:null;const _0x128b8b=await _0x44e149[_0x3ed6e2(0x165)](readHookInput),_0x4077ef=_0x128b8b?.[_0x3ed6e2(0x15d)];if(!_0x4077ef||!isSessionEnabled(_0x4077ef))return null;return _0x4077ef;}export async function getEnabledHookContext(_0x431da4){const _0x478a94=_0x17d2,_0xd2173f={'tuYxr':function(_0x23896a,_0x4e0bfe){return _0x23896a(_0x4e0bfe);},'PfTyP':function(_0x5bd318){return _0x5bd318();}};if(_0x431da4){if(!_0xd2173f[_0x478a94(0x16a)](isSessionEnabled,_0x431da4))return null;return{'sessionId':_0x431da4,'input':{'session_id':_0x431da4}};}const _0x1333ad=await _0xd2173f[_0x478a94(0x169)](readHookInput),_0x166cb5=_0x1333ad?.[_0x478a94(0x15d)];if(!_0x166cb5||!isSessionEnabled(_0x166cb5))return null;return{'sessionId':_0x166cb5,'input':_0x1333ad};}function _0x3170(){const _0x364292=['40pAPDpO','212545ZRzqmy','PfTyP','tuYxr','log','stdin','173194oORnUS','52877MzXxxS','session_id','93400nxJIaT','1512684RdGxID','762980PHGLNt','230BkAIJV','1940319HfeDyw','4OLHJfn','30kIJTkT','dELDA','3YPJVAC'];_0x3170=function(){return _0x364292;};return _0x3170();}
|
|
@@ -1,46 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { shouldShowPlanReminder } from '../utils/sessionCache.js';
|
|
3
|
-
/**
|
|
4
|
-
* Plan reminder hook handler
|
|
5
|
-
*
|
|
6
|
-
* This command is invoked on UserPromptSubmit, SubagentStop, and PostToolUse.
|
|
7
|
-
* It checks if in plan mode and shows the Ranger reminder (max once per 5 mins per session).
|
|
8
|
-
*/
|
|
9
|
-
export async function planReminder(sessionIdOverride) {
|
|
10
|
-
const ctx = await getEnabledHookContext(sessionIdOverride);
|
|
11
|
-
if (!ctx) {
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
// Only show in plan mode
|
|
15
|
-
if (ctx.input.permission_mode !== 'plan') {
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
// Check if we should show the reminder (rate limited per session)
|
|
19
|
-
if (!shouldShowPlanReminder(ctx.sessionId)) {
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
printBlock(`=== RANGER: ACTION REQUIRED ===
|
|
23
|
-
|
|
24
|
-
If this plan involves ANY UI changes, you MUST:
|
|
25
|
-
|
|
26
|
-
1. **READ /ranger skill NOW** - specifically the create.md instructions
|
|
27
|
-
2. **Add a Ranger Feature Review Specification** to the end of your plan
|
|
28
|
-
|
|
29
|
-
DO NOT write scenarios without reading create.md first.
|
|
30
|
-
Scenarios are E2E test flows, NOT implementation tasks.
|
|
31
|
-
|
|
32
|
-
Your plan must end with:
|
|
33
|
-
\`\`\`
|
|
34
|
-
### Ranger Feature Review Specification (create this first with \`ranger create\`)
|
|
35
|
-
Feature Review Name: <name>
|
|
36
|
-
Description: <description>
|
|
37
|
-
Scenarios:
|
|
38
|
-
1. <E2E user flow that can be verified in browser>
|
|
39
|
-
2. <another E2E user flow if needed>
|
|
40
|
-
\`\`\`
|
|
41
|
-
|
|
42
|
-
Then run: \`ranger create "<name>" -d "<desc>" -c "<scenario1>" -c "<scenario2>"\`
|
|
43
|
-
|
|
44
|
-
=== END ===`);
|
|
45
|
-
}
|
|
46
|
-
//# sourceMappingURL=planReminder.js.map
|
|
1
|
+
(function(_0x3f2cfa,_0x36401c){const _0x576a9a=_0x1dc1,_0x176496=_0x3f2cfa();while(!![]){try{const _0x4dedbb=-parseInt(_0x576a9a(0x8f))/0x1+parseInt(_0x576a9a(0x84))/0x2+-parseInt(_0x576a9a(0x87))/0x3+-parseInt(_0x576a9a(0x8d))/0x4+-parseInt(_0x576a9a(0x8b))/0x5+-parseInt(_0x576a9a(0x86))/0x6*(-parseInt(_0x576a9a(0x8e))/0x7)+parseInt(_0x576a9a(0x88))/0x8;if(_0x4dedbb===_0x36401c)break;else _0x176496['push'](_0x176496['shift']());}catch(_0x134650){_0x176496['push'](_0x176496['shift']());}}}(_0x9c20,0x3e4af));import{printBlock,getEnabledHookContext}from'./output.js';function _0x1dc1(_0x24a882,_0x4e205b){_0x24a882=_0x24a882-0x84;const _0x9c2092=_0x9c20();let _0x1dc1ce=_0x9c2092[_0x24a882];return _0x1dc1ce;}import{shouldShowPlanReminder}from'../utils/sessionCache.js';export async function planReminder(_0x182fb5){const _0x510ae0=_0x1dc1,_0xb59c02={'iUcUp':function(_0x5b0aa6,_0x34b26a){return _0x5b0aa6(_0x34b26a);},'CfFyX':function(_0x45e840,_0x26b199){return _0x45e840!==_0x26b199;},'RyTeM':'plan','ziQhp':function(_0x51df7b,_0x591c16){return _0x51df7b(_0x591c16);}},_0x54accb=await _0xb59c02[_0x510ae0(0x8c)](getEnabledHookContext,_0x182fb5);if(!_0x54accb)return;if(_0xb59c02[_0x510ae0(0x8a)](_0x54accb[_0x510ae0(0x85)][_0x510ae0(0x89)],_0xb59c02['RyTeM']))return;if(!_0xb59c02['ziQhp'](shouldShowPlanReminder,_0x54accb['sessionId']))return;printBlock('===\x20RANGER:\x20ACTION\x20REQUIRED\x20===\x0a\x0aIf\x20this\x20plan\x20involves\x20ANY\x20UI\x20changes,\x20you\x20MUST:\x0a\x0a1.\x20**READ\x20/ranger\x20skill\x20NOW**\x20-\x20specifically\x20the\x20create.md\x20instructions\x0a2.\x20**Add\x20a\x20Ranger\x20Feature\x20Review\x20Specification**\x20to\x20the\x20end\x20of\x20your\x20plan\x0a\x0aDO\x20NOT\x20write\x20scenarios\x20without\x20reading\x20create.md\x20first.\x0aScenarios\x20are\x20E2E\x20test\x20flows,\x20NOT\x20implementation\x20tasks.\x0a\x0aYour\x20plan\x20must\x20end\x20with:\x0a```\x0a###\x20Ranger\x20Feature\x20Review\x20Specification\x20(create\x20this\x20first\x20with\x20`ranger\x20create`)\x0aFeature\x20Review\x20Name:\x20<name>\x0aDescription:\x20<description>\x0aScenarios:\x0a1.\x20<E2E\x20user\x20flow\x20that\x20can\x20be\x20verified\x20in\x20browser>\x0a2.\x20<another\x20E2E\x20user\x20flow\x20if\x20needed>\x0a```\x0a\x0aThen\x20run:\x20`ranger\x20create\x20\x22<name>\x22\x20-d\x20\x22<desc>\x22\x20-c\x20\x22<scenario1>\x22\x20-c\x20\x22<scenario2>\x22`\x0a\x0a===\x20END\x20===');}function _0x9c20(){const _0x546a5d=['iUcUp','363088jkaohK','3423931oQrUxT','298323sewrTE','152566TpCvsw','input','6Cboosd','528966WWLyqZ','3497480zSZWcf','permission_mode','CfFyX','910165JivuNc'];_0x9c20=function(){return _0x546a5d;};return _0x9c20();}
|
|
@@ -1,30 +1 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* SubagentStart hook handler for Plan mode
|
|
4
|
-
*
|
|
5
|
-
* This command is invoked when Claude enters plan mode (Plan subagent starts).
|
|
6
|
-
* It reminds Claude to include Ranger scenarios as part of the planning process.
|
|
7
|
-
*/
|
|
8
|
-
export async function planStart(sessionIdOverride) {
|
|
9
|
-
const sessionId = await getEnabledSessionId(sessionIdOverride);
|
|
10
|
-
if (!sessionId) {
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
printBlock(`=== RANGER: ACTION REQUIRED ===
|
|
14
|
-
|
|
15
|
-
If this plan involves UI changes, you MUST:
|
|
16
|
-
|
|
17
|
-
1. **READ /ranger skill** - specifically create.md
|
|
18
|
-
2. **Add a Ranger Feature Review Specification** at the end of your plan
|
|
19
|
-
|
|
20
|
-
Scenarios are E2E test flows, NOT implementation tasks.
|
|
21
|
-
|
|
22
|
-
**Good:** "User can log in with valid credentials and see dashboard"
|
|
23
|
-
**Bad:** "Add form validation" or "Button is visible"
|
|
24
|
-
|
|
25
|
-
After planning, run:
|
|
26
|
-
\`ranger create "<name>" -d "<desc>" -c "<E2E flow 1>" -c "<E2E flow 2>"\`
|
|
27
|
-
|
|
28
|
-
=== END ===`);
|
|
29
|
-
}
|
|
30
|
-
//# sourceMappingURL=planStart.js.map
|
|
1
|
+
(function(_0x50508a,_0x2880d9){const _0x4daa9e=_0x24a8,_0x46922e=_0x50508a();while(!![]){try{const _0x1f7e68=parseInt(_0x4daa9e(0x12d))/0x1*(-parseInt(_0x4daa9e(0x12f))/0x2)+-parseInt(_0x4daa9e(0x12b))/0x3*(parseInt(_0x4daa9e(0x12c))/0x4)+parseInt(_0x4daa9e(0x12e))/0x5*(-parseInt(_0x4daa9e(0x131))/0x6)+-parseInt(_0x4daa9e(0x129))/0x7+parseInt(_0x4daa9e(0x130))/0x8+-parseInt(_0x4daa9e(0x128))/0x9+-parseInt(_0x4daa9e(0x133))/0xa*(-parseInt(_0x4daa9e(0x132))/0xb);if(_0x1f7e68===_0x2880d9)break;else _0x46922e['push'](_0x46922e['shift']());}catch(_0x58805e){_0x46922e['push'](_0x46922e['shift']());}}}(_0x4487,0xa0783));function _0x24a8(_0x33bddc,_0x4941ac){_0x33bddc=_0x33bddc-0x128;const _0x4487aa=_0x4487();let _0x24a8bb=_0x4487aa[_0x33bddc];return _0x24a8bb;}function _0x4487(){const _0x20a7bd=['===\x20RANGER:\x20ACTION\x20REQUIRED\x20===\x0a\x0aIf\x20this\x20plan\x20involves\x20UI\x20changes,\x20you\x20MUST:\x0a\x0a1.\x20**READ\x20/ranger\x20skill**\x20-\x20specifically\x20create.md\x0a2.\x20**Add\x20a\x20Ranger\x20Feature\x20Review\x20Specification**\x20at\x20the\x20end\x20of\x20your\x20plan\x0a\x0aScenarios\x20are\x20E2E\x20test\x20flows,\x20NOT\x20implementation\x20tasks.\x0a\x0a**Good:**\x20\x22User\x20can\x20log\x20in\x20with\x20valid\x20credentials\x20and\x20see\x20dashboard\x22\x0a**Bad:**\x20\x22Add\x20form\x20validation\x22\x20or\x20\x22Button\x20is\x20visible\x22\x0a\x0aAfter\x20planning,\x20run:\x0a`ranger\x20create\x20\x22<name>\x22\x20-d\x20\x22<desc>\x22\x20-c\x20\x22<E2E\x20flow\x201>\x22\x20-c\x20\x22<E2E\x20flow\x202>\x22`\x0a\x0a===\x20END\x20===','528249jzLpku','12ibgBqq','1UxPcYo','5pOsVvS','983960ECcAHx','8883128XawmsV','914232kgifUF','6032103RECgvF','30UzpFXp','2914515kAXRFg','4212537KIpxja'];_0x4487=function(){return _0x20a7bd;};return _0x4487();}import{printBlock,getEnabledSessionId}from'./output.js';export async function planStart(_0x1022b2){const _0x49b073=_0x24a8,_0xf53613=await getEnabledSessionId(_0x1022b2);if(!_0xf53613)return;printBlock(_0x49b073(0x12a));}
|
|
@@ -1,43 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { getToken } from '../utils/keychain.js';
|
|
3
|
-
import { getEnabledSessionId } from './output.js';
|
|
4
|
-
/**
|
|
5
|
-
* PostToolUse (Write/Edit) hook handler for Claude Code plugin
|
|
6
|
-
*
|
|
7
|
-
* This command is invoked automatically after Write or Edit tools are used.
|
|
8
|
-
* If the session isn't registered with a Ranger feature review, prompts to use /ranger.
|
|
9
|
-
*/
|
|
10
|
-
export async function postEdit(sessionIdOverride) {
|
|
11
|
-
const sessionId = await getEnabledSessionId(sessionIdOverride);
|
|
12
|
-
if (!sessionId) {
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
// Update branch tracking - auto-enable new branches if session switched while enabled
|
|
16
|
-
updateBranchTracking(sessionId);
|
|
17
|
-
const token = await getToken();
|
|
18
|
-
if (!token) {
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
// Check if this session is already registered
|
|
22
|
-
const existingEntry = getSessionEntry(sessionId);
|
|
23
|
-
if (existingEntry) {
|
|
24
|
-
// Already registered - remind about adding scenarios if scope expanded
|
|
25
|
-
const response = {
|
|
26
|
-
hookSpecificOutput: {
|
|
27
|
-
hookEventName: 'PostToolUse',
|
|
28
|
-
additionalContext: `RANGER: If this change expands the scope of the active feature review, you may need to add a scenario. See Workflow 1 in /ranger. If you decide to add a scenario, you MUST read Workflow 1 IN DETAIL first. Remember: when you finish your work, your final message to the user must direct them to the Ranger feature review dashboard to review (e.g. "Go to the Ranger feature dashboard to review: https://dashboard.ranger.net/features/{feature_id}").`,
|
|
29
|
-
},
|
|
30
|
-
};
|
|
31
|
-
console.log(JSON.stringify(response));
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
// Not registered - prompt to use /ranger for UI work
|
|
35
|
-
const response = {
|
|
36
|
-
hookSpecificOutput: {
|
|
37
|
-
hookEventName: 'PostToolUse',
|
|
38
|
-
additionalContext: `RANGER: If this is for a UI feature, you MUST use /ranger to either create a new feature review or resume an existing one.`,
|
|
39
|
-
},
|
|
40
|
-
};
|
|
41
|
-
console.log(JSON.stringify(response));
|
|
42
|
-
}
|
|
43
|
-
//# sourceMappingURL=postEdit.js.map
|
|
1
|
+
function _0x35cd(_0x4f1f3b,_0x5cb340){_0x4f1f3b=_0x4f1f3b-0xfd;const _0x253617=_0x2536();let _0x35cdb3=_0x253617[_0x4f1f3b];return _0x35cdb3;}(function(_0x57e13c,_0x21d302){const _0x45c33d=_0x35cd,_0x243e0b=_0x57e13c();while(!![]){try{const _0x2ba02f=parseInt(_0x45c33d(0x104))/0x1+parseInt(_0x45c33d(0x10c))/0x2+parseInt(_0x45c33d(0x103))/0x3*(-parseInt(_0x45c33d(0x101))/0x4)+parseInt(_0x45c33d(0xfe))/0x5*(parseInt(_0x45c33d(0xff))/0x6)+-parseInt(_0x45c33d(0x107))/0x7+-parseInt(_0x45c33d(0x108))/0x8+parseInt(_0x45c33d(0xfd))/0x9*(parseInt(_0x45c33d(0x106))/0xa);if(_0x2ba02f===_0x21d302)break;else _0x243e0b['push'](_0x243e0b['shift']());}catch(_0x36ff95){_0x243e0b['push'](_0x243e0b['shift']());}}}(_0x2536,0xafb4e));import{getSessionEntry,updateBranchTracking}from'../utils/sessionCache.js';function _0x2536(){const _0x9a7589=['3547915NtaUCQ','8525656oOJIus','PostToolUse','myEkh','RANGER:\x20If\x20this\x20change\x20expands\x20the\x20scope\x20of\x20the\x20active\x20feature\x20review,\x20you\x20may\x20need\x20to\x20add\x20a\x20scenario.\x20See\x20Workflow\x201\x20in\x20/ranger.\x20If\x20you\x20decide\x20to\x20add\x20a\x20scenario,\x20you\x20MUST\x20read\x20Workflow\x201\x20IN\x20DETAIL\x20first.\x20Remember:\x20when\x20you\x20finish\x20your\x20work,\x20your\x20final\x20message\x20to\x20the\x20user\x20must\x20direct\x20them\x20to\x20the\x20Ranger\x20feature\x20review\x20dashboard\x20to\x20review\x20(e.g.\x20\x22Go\x20to\x20the\x20Ranger\x20feature\x20dashboard\x20to\x20review:\x20https://dashboard.ranger.net/features/{feature_id}\x22).','642596PTIjlq','158643GknceB','18160PhZsSm','1098VLmNqP','log','4qKXplv','CYqWM','2601003AICrIc','1274316UmvJQY','RANGER:\x20If\x20this\x20is\x20for\x20a\x20UI\x20feature,\x20you\x20MUST\x20use\x20/ranger\x20to\x20either\x20create\x20a\x20new\x20feature\x20review\x20or\x20resume\x20an\x20existing\x20one.','510VvHABG'];_0x2536=function(){return _0x9a7589;};return _0x2536();}import{getToken}from'../utils/keychain.js';import{getEnabledSessionId}from'./output.js';export async function postEdit(_0x168410){const _0x44d8d1=_0x35cd,_0x41e7e7={'CYqWM':function(_0x74ed55){return _0x74ed55();},'myEkh':_0x44d8d1(0x109)},_0x4b9146=await getEnabledSessionId(_0x168410);if(!_0x4b9146)return;updateBranchTracking(_0x4b9146);const _0x4f37b3=await _0x41e7e7[_0x44d8d1(0x102)](getToken);if(!_0x4f37b3)return;const _0x3960e5=getSessionEntry(_0x4b9146);if(_0x3960e5){const _0x122bf6={'hookSpecificOutput':{'hookEventName':_0x41e7e7[_0x44d8d1(0x10a)],'additionalContext':_0x44d8d1(0x10b)}};console[_0x44d8d1(0x100)](JSON['stringify'](_0x122bf6));return;}const _0xb68391={'hookSpecificOutput':{'hookEventName':_0x41e7e7['myEkh'],'additionalContext':_0x44d8d1(0x105)}};console['log'](JSON['stringify'](_0xb68391));}
|
|
@@ -1,30 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { printBlock, getEnabledSessionId } from './output.js';
|
|
3
|
-
/**
|
|
4
|
-
* PreCompact hook handler for Claude Code plugin
|
|
5
|
-
*
|
|
6
|
-
* This command is invoked automatically before Claude Code compacts the conversation.
|
|
7
|
-
* It reminds Claude to preserve Ranger Feature Review Specification in the compaction summary.
|
|
8
|
-
*/
|
|
9
|
-
export async function preCompact(sessionIdOverride) {
|
|
10
|
-
const sessionId = await getEnabledSessionId(sessionIdOverride);
|
|
11
|
-
if (!sessionId) {
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
try {
|
|
15
|
-
// Check if Ranger is configured
|
|
16
|
-
const token = await getToken();
|
|
17
|
-
if (!token) {
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
printBlock(`=== RANGER: PRESERVE IN COMPACTION ===
|
|
21
|
-
|
|
22
|
-
If you created a plan with a **Ranger Feature Review Specification**, you MUST preserve it in the compaction summary.
|
|
23
|
-
|
|
24
|
-
The specification contains scenarios that will be used with \`ranger create\`.`);
|
|
25
|
-
}
|
|
26
|
-
catch {
|
|
27
|
-
// Silently fail - don't interrupt compaction
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
//# sourceMappingURL=preCompact.js.map
|
|
1
|
+
(function(_0x569bae,_0x1e27c3){const _0x288f75=_0x34dd,_0x3bf379=_0x569bae();while(!![]){try{const _0x21beb7=parseInt(_0x288f75(0xc3))/0x1*(-parseInt(_0x288f75(0xb9))/0x2)+-parseInt(_0x288f75(0xc2))/0x3*(-parseInt(_0x288f75(0xc1))/0x4)+parseInt(_0x288f75(0xc5))/0x5*(parseInt(_0x288f75(0xbe))/0x6)+parseInt(_0x288f75(0xbd))/0x7+parseInt(_0x288f75(0xbf))/0x8*(parseInt(_0x288f75(0xbc))/0x9)+parseInt(_0x288f75(0xba))/0xa+-parseInt(_0x288f75(0xbb))/0xb;if(_0x21beb7===_0x1e27c3)break;else _0x3bf379['push'](_0x3bf379['shift']());}catch(_0x457b38){_0x3bf379['push'](_0x3bf379['shift']());}}}(_0x4da8,0xef648));import{getToken}from'../utils/keychain.js';import{printBlock,getEnabledSessionId}from'./output.js';export async function preCompact(_0x5313fb){const _0x5b60d8=_0x34dd,_0x50329a={'iUMen':function(_0x189ba4,_0x4361ab){return _0x189ba4(_0x4361ab);},'YnoUa':function(_0x5421a2){return _0x5421a2();}},_0x148e17=await _0x50329a[_0x5b60d8(0xc0)](getEnabledSessionId,_0x5313fb);if(!_0x148e17)return;try{const _0x2e5c51=await _0x50329a[_0x5b60d8(0xc4)](getToken);if(!_0x2e5c51)return;_0x50329a['iUMen'](printBlock,'===\x20RANGER:\x20PRESERVE\x20IN\x20COMPACTION\x20===\x0a\x0aIf\x20you\x20created\x20a\x20plan\x20with\x20a\x20**Ranger\x20Feature\x20Review\x20Specification**,\x20you\x20MUST\x20preserve\x20it\x20in\x20the\x20compaction\x20summary.\x0a\x0aThe\x20specification\x20contains\x20scenarios\x20that\x20will\x20be\x20used\x20with\x20`ranger\x20create`.');}catch{}}function _0x34dd(_0x183903,_0xd10dfe){_0x183903=_0x183903-0xb9;const _0x4da810=_0x4da8();let _0x34dd44=_0x4da810[_0x183903];return _0x34dd44;}function _0x4da8(){const _0x542935=['3782535cpuYyX','12jJsaoB','3013540xzbBHh','15985079RIaxlW','3174534aJtsVH','40173IbnLny','12cqLNcX','24DkPAVY','iUMen','2456EnQysU','6501jDDosg','295847eudKKN','YnoUa'];_0x4da8=function(){return _0x542935;};return _0x4da8();}
|
|
@@ -1,25 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { readHookInput } from './output.js';
|
|
3
|
-
/**
|
|
4
|
-
* SessionEnd hook handler for Claude Code plugin
|
|
5
|
-
*
|
|
6
|
-
* This command is invoked when a Claude Code session ends.
|
|
7
|
-
* If reason is 'clear' and session was enabled, records timestamp for auto-enable.
|
|
8
|
-
*/
|
|
9
|
-
export async function sessionEnd(sessionIdOverride) {
|
|
10
|
-
let sessionId = sessionIdOverride;
|
|
11
|
-
let reason;
|
|
12
|
-
if (!sessionIdOverride) {
|
|
13
|
-
const input = await readHookInput();
|
|
14
|
-
sessionId = input?.session_id;
|
|
15
|
-
reason = input?.reason;
|
|
16
|
-
}
|
|
17
|
-
if (!sessionId) {
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
// If session was cleared, record it for auto-enable on next session
|
|
21
|
-
if (reason === 'clear') {
|
|
22
|
-
recordEnabledSessionCleared(sessionId);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
//# sourceMappingURL=sessionEnd.js.map
|
|
1
|
+
(function(_0x1d9eaf,_0x449147){const _0x4eb3c8=_0x2e31,_0x400af9=_0x1d9eaf();while(!![]){try{const _0x22f441=-parseInt(_0x4eb3c8(0x6b))/0x1*(parseInt(_0x4eb3c8(0x6e))/0x2)+-parseInt(_0x4eb3c8(0x70))/0x3*(-parseInt(_0x4eb3c8(0x71))/0x4)+-parseInt(_0x4eb3c8(0x67))/0x5+parseInt(_0x4eb3c8(0x72))/0x6+-parseInt(_0x4eb3c8(0x6d))/0x7*(-parseInt(_0x4eb3c8(0x6c))/0x8)+-parseInt(_0x4eb3c8(0x6a))/0x9+parseInt(_0x4eb3c8(0x69))/0xa*(parseInt(_0x4eb3c8(0x6f))/0xb);if(_0x22f441===_0x449147)break;else _0x400af9['push'](_0x400af9['shift']());}catch(_0x29c558){_0x400af9['push'](_0x400af9['shift']());}}}(_0x26b3,0x2a1eb));import{recordEnabledSessionCleared}from'../utils/sessionCache.js';function _0x26b3(){const _0x1501be=['284346vDkxQX','session_id','reason','1205965pTDRle','clear','3920600tolmMD','1974825SjkSNc','148475UUgSZV','16sZcIIn','705509rIudwO','2oZJGcA','11ZPyHvT','33KxTfTz','51124SsJKZf'];_0x26b3=function(){return _0x1501be;};return _0x26b3();}function _0x2e31(_0x411ade,_0x520693){_0x411ade=_0x411ade-0x65;const _0x26b34a=_0x26b3();let _0x2e3181=_0x26b34a[_0x411ade];return _0x2e3181;}import{readHookInput}from'./output.js';export async function sessionEnd(_0xe15b42){const _0x2cb86b=_0x2e31,_0x4ad195={'PPhKh':function(_0x327d28,_0x29373c){return _0x327d28===_0x29373c;}};let _0x46f526=_0xe15b42,_0x130063;if(!_0xe15b42){const _0x19c33=await readHookInput();_0x46f526=_0x19c33?.[_0x2cb86b(0x65)],_0x130063=_0x19c33?.[_0x2cb86b(0x66)];}if(!_0x46f526)return;_0x4ad195['PPhKh'](_0x130063,_0x2cb86b(0x68))&&recordEnabledSessionCleared(_0x46f526);}
|
|
@@ -1,93 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { initBranchTracking, shouldAutoEnableAfterClear, autoEnableAfterClear, isSessionEnabled, getCurrentBranch, } from '../utils/sessionCache.js';
|
|
3
|
-
import { createTelemetryCollector } from '../utils/telemetry.js';
|
|
4
|
-
const RANGER_AUTO_ENABLED_PROMPT = `=================================================================
|
|
5
|
-
🚨 RANGER IS ACTIVE 🚨
|
|
6
|
-
=================================================================
|
|
7
|
-
|
|
8
|
-
This session has Ranger ENABLED. Before doing ANYTHING else:
|
|
9
|
-
|
|
10
|
-
1. **READ the /ranger skill FIRST** - Run the skill to understand the required workflow for UI features
|
|
11
|
-
|
|
12
|
-
2. **Check for existing feature reviews** - Run \`ranger list\` to see if there's an in-progress feature review to resume
|
|
13
|
-
|
|
14
|
-
3. **For ANY UI work**: You MUST either:
|
|
15
|
-
- Resume an existing feature review: \`ranger resume <id>\`
|
|
16
|
-
- Create a new feature review: \`ranger create "<name>" -d "<desc>" -c "<scenario>"\`
|
|
17
|
-
|
|
18
|
-
4. **If resuming a feature review with reviewer comments**: Run \`ranger get-review\` to see what reviewers want fixed before making code changes
|
|
19
|
-
|
|
20
|
-
=================================================================`;
|
|
21
|
-
/**
|
|
22
|
-
* SessionStart hook handler for Claude Code plugin
|
|
23
|
-
*
|
|
24
|
-
* This command is invoked automatically when a new Claude Code session starts.
|
|
25
|
-
* Exports CLAUDE_SESSION_ID to the environment for use by other hooks.
|
|
26
|
-
*
|
|
27
|
-
* Note: The skill prompt is now shown by the enable hook when user runs /enable.
|
|
28
|
-
*/
|
|
29
|
-
export async function sessionStart(sessionIdOverride) {
|
|
30
|
-
let sessionId = sessionIdOverride || '';
|
|
31
|
-
let source;
|
|
32
|
-
if (!sessionIdOverride) {
|
|
33
|
-
// Claude Code path: read JSON input from stdin to get session_id and source
|
|
34
|
-
let input = '';
|
|
35
|
-
for await (const chunk of process.stdin) {
|
|
36
|
-
input += chunk;
|
|
37
|
-
}
|
|
38
|
-
try {
|
|
39
|
-
const data = JSON.parse(input);
|
|
40
|
-
sessionId = data['session_id'] || '';
|
|
41
|
-
source = data['source'];
|
|
42
|
-
}
|
|
43
|
-
catch {
|
|
44
|
-
// Ignore parse errors
|
|
45
|
-
}
|
|
46
|
-
// Export CLAUDE_SESSION_ID to env file if available (Claude Code only)
|
|
47
|
-
const envFile = process.env.CLAUDE_ENV_FILE;
|
|
48
|
-
if (envFile && sessionId) {
|
|
49
|
-
try {
|
|
50
|
-
await appendFile(envFile, `export CLAUDE_SESSION_ID="${sessionId}"\n`);
|
|
51
|
-
}
|
|
52
|
-
catch {
|
|
53
|
-
// Ignore errors writing to env file
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
if (sessionId) {
|
|
58
|
-
// Auto-enable if this session started from /clear and previous session was enabled
|
|
59
|
-
if (shouldAutoEnableAfterClear(source)) {
|
|
60
|
-
autoEnableAfterClear(sessionId);
|
|
61
|
-
}
|
|
62
|
-
// Initialize branch tracking - auto-enable session if branch is already enabled
|
|
63
|
-
initBranchTracking(sessionId);
|
|
64
|
-
const enabled = isSessionEnabled(sessionId);
|
|
65
|
-
// Telemetry: log session start with enabled status
|
|
66
|
-
try {
|
|
67
|
-
const telemetry = createTelemetryCollector('hook:session-start');
|
|
68
|
-
await telemetry.trackCommandStart({
|
|
69
|
-
sessionId,
|
|
70
|
-
hooksEnabled: enabled,
|
|
71
|
-
});
|
|
72
|
-
await telemetry.trackCommandEnd('success');
|
|
73
|
-
}
|
|
74
|
-
catch {
|
|
75
|
-
// Telemetry must never throw
|
|
76
|
-
}
|
|
77
|
-
// If session is now enabled (via branch or clear), output strong prompting
|
|
78
|
-
if (enabled) {
|
|
79
|
-
const branch = getCurrentBranch();
|
|
80
|
-
const branchInfo = branch && branch !== 'main' && branch !== 'master'
|
|
81
|
-
? ` (Branch: ${branch})`
|
|
82
|
-
: '';
|
|
83
|
-
const response = {
|
|
84
|
-
hookSpecificOutput: {
|
|
85
|
-
hookEventName: 'SessionStart',
|
|
86
|
-
additionalContext: RANGER_AUTO_ENABLED_PROMPT + branchInfo,
|
|
87
|
-
},
|
|
88
|
-
};
|
|
89
|
-
console.log(JSON.stringify(response));
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
//# sourceMappingURL=sessionStart.js.map
|
|
1
|
+
function _0x215f(){const _0x3f5fcc=['2543674rEKhWZ','8337456AFbYCk','success','8boyfbZ','env','trackCommandEnd','5710700ogUDGI','444036dNkdLa','uFnEI','main','AAabO','85nguzGH','stringify','trackCommandStart','CLAUDE_ENV_FILE','12363GXhUmB','source','AxAAA','314fjNEHH','55mYANtf','3234572Owtpjn','=================================================================\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20🚨\x20RANGER\x20IS\x20ACTIVE\x20🚨\x0a=================================================================\x0a\x0aThis\x20session\x20has\x20Ranger\x20ENABLED.\x20Before\x20doing\x20ANYTHING\x20else:\x0a\x0a1.\x20**READ\x20the\x20/ranger\x20skill\x20FIRST**\x20-\x20Run\x20the\x20skill\x20to\x20understand\x20the\x20required\x20workflow\x20for\x20UI\x20features\x0a\x0a2.\x20**Check\x20for\x20existing\x20feature\x20reviews**\x20-\x20Run\x20`ranger\x20list`\x20to\x20see\x20if\x20there\x27s\x20an\x20in-progress\x20feature\x20review\x20to\x20resume\x0a\x0a3.\x20**For\x20ANY\x20UI\x20work**:\x20You\x20MUST\x20either:\x0a\x20\x20\x20-\x20Resume\x20an\x20existing\x20feature\x20review:\x20`ranger\x20resume\x20<id>`\x0a\x20\x20\x20-\x20Create\x20a\x20new\x20feature\x20review:\x20`ranger\x20create\x20\x22<name>\x22\x20-d\x20\x22<desc>\x22\x20-c\x20\x22<scenario>\x22`\x0a\x0a4.\x20**If\x20resuming\x20a\x20feature\x20review\x20with\x20reviewer\x20comments**:\x20Run\x20`ranger\x20get-review`\x20to\x20see\x20what\x20reviewers\x20want\x20fixed\x20before\x20making\x20code\x20changes\x0a\x0a=================================================================','31848ogRLHQ','master'];_0x215f=function(){return _0x3f5fcc;};return _0x215f();}const _0x441f8f=_0x4f8c;(function(_0x402f17,_0x3920a0){const _0x1f9915=_0x4f8c,_0x9e451f=_0x402f17();while(!![]){try{const _0x3c10c7=parseInt(_0x1f9915(0xf7))/0x1+-parseInt(_0x1f9915(0x102))/0x2*(parseInt(_0x1f9915(0xff))/0x3)+-parseInt(_0x1f9915(0xec))/0x4+-parseInt(_0x1f9915(0xfb))/0x5*(parseInt(_0x1f9915(0xee))/0x6)+-parseInt(_0x1f9915(0xf0))/0x7+parseInt(_0x1f9915(0xf3))/0x8*(-parseInt(_0x1f9915(0xf1))/0x9)+-parseInt(_0x1f9915(0xf6))/0xa*(-parseInt(_0x1f9915(0xeb))/0xb);if(_0x3c10c7===_0x3920a0)break;else _0x9e451f['push'](_0x9e451f['shift']());}catch(_0x3f3059){_0x9e451f['push'](_0x9e451f['shift']());}}}(_0x215f,0x71380));import{appendFile}from'fs/promises';function _0x4f8c(_0x398e14,_0x345e72){_0x398e14=_0x398e14-0xeb;const _0x215f5e=_0x215f();let _0x4f8cf1=_0x215f5e[_0x398e14];return _0x4f8cf1;}import{initBranchTracking,shouldAutoEnableAfterClear,autoEnableAfterClear,isSessionEnabled,getCurrentBranch}from'../utils/sessionCache.js';import{createTelemetryCollector}from'../utils/telemetry.js';const RANGER_AUTO_ENABLED_PROMPT=_0x441f8f(0xed);export async function sessionStart(_0xc362ba){const _0x313dca=_0x441f8f,_0x13bd5c={'FpAWy':_0x313dca(0x100),'idiPa':function(_0x2b4823,_0xb135f6){return _0x2b4823(_0xb135f6);},'AxAAA':'hook:session-start','uFnEI':_0x313dca(0xf2),'AAabO':function(_0x5037a2){return _0x5037a2();},'IqGBo':function(_0x586431,_0x2653ee){return _0x586431!==_0x2653ee;},'NcxAk':_0x313dca(0xef),'HpdGJ':function(_0x291e2e,_0x6aff50){return _0x291e2e+_0x6aff50;}};let _0xc98ba5=_0xc362ba||'',_0x39605a;if(!_0xc362ba){let _0x72a642='';for await(const _0x3df052 of process['stdin']){_0x72a642+=_0x3df052;}try{const _0x2f01c6=JSON['parse'](_0x72a642);_0xc98ba5=_0x2f01c6['session_id']||'',_0x39605a=_0x2f01c6[_0x13bd5c['FpAWy']];}catch{}const _0x20f721=process[_0x313dca(0xf4)][_0x313dca(0xfe)];if(_0x20f721&&_0xc98ba5)try{await appendFile(_0x20f721,'export\x20CLAUDE_SESSION_ID=\x22'+_0xc98ba5+'\x22\x0a');}catch{}}if(_0xc98ba5){shouldAutoEnableAfterClear(_0x39605a)&&autoEnableAfterClear(_0xc98ba5);initBranchTracking(_0xc98ba5);const _0x4c8b9d=_0x13bd5c['idiPa'](isSessionEnabled,_0xc98ba5);try{const _0x16f2d3=createTelemetryCollector(_0x13bd5c[_0x313dca(0x101)]);await _0x16f2d3[_0x313dca(0xfd)]({'sessionId':_0xc98ba5,'hooksEnabled':_0x4c8b9d}),await _0x16f2d3[_0x313dca(0xf5)](_0x13bd5c[_0x313dca(0xf8)]);}catch{}if(_0x4c8b9d){const _0xae32d6=_0x13bd5c[_0x313dca(0xfa)](getCurrentBranch),_0x1d6a64=_0xae32d6&&_0xae32d6!==_0x313dca(0xf9)&&_0x13bd5c['IqGBo'](_0xae32d6,_0x13bd5c['NcxAk'])?'\x20(Branch:\x20'+_0xae32d6+')':'',_0x4c0e40={'hookSpecificOutput':{'hookEventName':'SessionStart','additionalContext':_0x13bd5c['HpdGJ'](RANGER_AUTO_ENABLED_PROMPT,_0x1d6a64)}};console['log'](JSON[_0x313dca(0xfc)](_0x4c0e40));}}}
|