@ranger-testing/ranger-cli 2.0.4 → 2.0.6

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.
Files changed (115) hide show
  1. package/build/cli.js +1 -914
  2. package/build/commands/addEnv.js +1 -1
  3. package/build/commands/authEncrypt.js +1 -36
  4. package/build/commands/clean.js +1 -1
  5. package/build/commands/config.js +1 -93
  6. package/build/commands/env.js +1 -98
  7. package/build/commands/feature.js +1 -653
  8. package/build/commands/hook.js +1 -33
  9. package/build/commands/hooks/autoPrompt.js +1 -32
  10. package/build/commands/hooks/disable.js +1 -33
  11. package/build/commands/hooks/enable.js +1 -58
  12. package/build/commands/hooks/exitPlanMode.js +1 -35
  13. package/build/commands/hooks/index.js +1 -12
  14. package/build/commands/hooks/output.js +1 -71
  15. package/build/commands/hooks/planReminder.js +1 -46
  16. package/build/commands/hooks/planStart.js +1 -30
  17. package/build/commands/hooks/postEdit.js +1 -43
  18. package/build/commands/hooks/preCompact.js +1 -30
  19. package/build/commands/hooks/sessionEnd.js +1 -25
  20. package/build/commands/hooks/sessionStart.js +1 -93
  21. package/build/commands/hooks/stopHook.js +1 -155
  22. package/build/commands/index.js +1 -12
  23. package/build/commands/login.js +1 -26
  24. package/build/commands/setupCi.js +1 -189
  25. package/build/commands/skillup.js +1 -80
  26. package/build/commands/start.js +1 -1
  27. package/build/commands/status.js +1 -198
  28. package/build/commands/update.js +1 -182
  29. package/build/commands/updateEnv.js +1 -1
  30. package/build/commands/useEnv.js +1 -1
  31. package/build/commands/utils/activeProfile.js +1 -76
  32. package/build/commands/utils/browserSessionsApi.js +1 -1
  33. package/build/commands/utils/claudeConfig.js +1 -73
  34. package/build/commands/utils/claudePlugin.js +1 -85
  35. package/build/commands/utils/crypto.js +1 -42
  36. package/build/commands/utils/desirePathLog.js +1 -139
  37. package/build/commands/utils/deviceAuth.js +1 -232
  38. package/build/commands/utils/environment.js +1 -65
  39. package/build/commands/utils/featureApi.js +1 -371
  40. package/build/commands/utils/featureReportGenerator.js +1 -204
  41. package/build/commands/utils/git.js +1 -44
  42. package/build/commands/utils/keychain.js +1 -1
  43. package/build/commands/utils/localAgentInstallationsApi.js +1 -1
  44. package/build/commands/utils/profileMessages.js +1 -8
  45. package/build/commands/utils/profileSetupBanner.js +1 -167
  46. package/build/commands/utils/rangerRoot.js +1 -60
  47. package/build/commands/utils/reportGenerator.js +1 -130
  48. package/build/commands/utils/retry.js +1 -25
  49. package/build/commands/utils/sessionCache.js +1 -299
  50. package/build/commands/utils/settings.js +1 -313
  51. package/build/commands/utils/skillContent.js +1 -28
  52. package/build/commands/utils/skills.js +1 -1
  53. package/build/commands/utils/telemetry.js +1 -254
  54. package/build/commands/utils/userApi.js +1 -32
  55. package/build/commands/utils/version.js +1 -62
  56. package/build/commands/verifyFeature.js +1 -1343
  57. package/build/commands/verifyInBrowser.js +1 -1
  58. package/package.json +1 -1
  59. package/build/cli.js.map +0 -1
  60. package/build/commands/addEnv.js.map +0 -1
  61. package/build/commands/authEncrypt.js.map +0 -1
  62. package/build/commands/clean.js.map +0 -1
  63. package/build/commands/config.js.map +0 -1
  64. package/build/commands/env.js.map +0 -1
  65. package/build/commands/feature.js.map +0 -1
  66. package/build/commands/hook.js.map +0 -1
  67. package/build/commands/hooks/autoPrompt.js.map +0 -1
  68. package/build/commands/hooks/disable.js.map +0 -1
  69. package/build/commands/hooks/enable.js.map +0 -1
  70. package/build/commands/hooks/exitPlanMode.js.map +0 -1
  71. package/build/commands/hooks/index.js.map +0 -1
  72. package/build/commands/hooks/output.js.map +0 -1
  73. package/build/commands/hooks/planReminder.js.map +0 -1
  74. package/build/commands/hooks/planStart.js.map +0 -1
  75. package/build/commands/hooks/postEdit.js.map +0 -1
  76. package/build/commands/hooks/preCompact.js.map +0 -1
  77. package/build/commands/hooks/sessionEnd.js.map +0 -1
  78. package/build/commands/hooks/sessionStart.js.map +0 -1
  79. package/build/commands/hooks/stopHook.js.map +0 -1
  80. package/build/commands/index.js.map +0 -1
  81. package/build/commands/login.js.map +0 -1
  82. package/build/commands/setupCi.js.map +0 -1
  83. package/build/commands/skillup.js.map +0 -1
  84. package/build/commands/start.js.map +0 -1
  85. package/build/commands/status.js.map +0 -1
  86. package/build/commands/update.js.map +0 -1
  87. package/build/commands/updateEnv.js.map +0 -1
  88. package/build/commands/useEnv.js.map +0 -1
  89. package/build/commands/utils/activeProfile.js.map +0 -1
  90. package/build/commands/utils/browserSessionsApi.js.map +0 -1
  91. package/build/commands/utils/claudeConfig.js.map +0 -1
  92. package/build/commands/utils/claudePlugin.js.map +0 -1
  93. package/build/commands/utils/crypto.js.map +0 -1
  94. package/build/commands/utils/desirePathLog.js.map +0 -1
  95. package/build/commands/utils/deviceAuth.js.map +0 -1
  96. package/build/commands/utils/environment.js.map +0 -1
  97. package/build/commands/utils/featureApi.js.map +0 -1
  98. package/build/commands/utils/featureReportGenerator.js.map +0 -1
  99. package/build/commands/utils/git.js.map +0 -1
  100. package/build/commands/utils/keychain.js.map +0 -1
  101. package/build/commands/utils/localAgentInstallationsApi.js.map +0 -1
  102. package/build/commands/utils/profileMessages.js.map +0 -1
  103. package/build/commands/utils/profileSetupBanner.js.map +0 -1
  104. package/build/commands/utils/rangerRoot.js.map +0 -1
  105. package/build/commands/utils/reportGenerator.js.map +0 -1
  106. package/build/commands/utils/retry.js.map +0 -1
  107. package/build/commands/utils/sessionCache.js.map +0 -1
  108. package/build/commands/utils/settings.js.map +0 -1
  109. package/build/commands/utils/skillContent.js.map +0 -1
  110. package/build/commands/utils/skills.js.map +0 -1
  111. package/build/commands/utils/telemetry.js.map +0 -1
  112. package/build/commands/utils/userApi.js.map +0 -1
  113. package/build/commands/utils/version.js.map +0 -1
  114. package/build/commands/verifyFeature.js.map +0 -1
  115. package/build/commands/verifyInBrowser.js.map +0 -1
@@ -1,33 +1 @@
1
- import { sessionStart, sessionEnd, preCompact, postEdit, planStart, planReminder, exitPlanMode, stopHook, enable, disable, autoPrompt, } from './hooks/index.js';
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(_0xa1d194,_0x1c073f){const _0x4522ce=_0x589f,_0x297241=_0xa1d194();while(!![]){try{const _0x4124b6=-parseInt(_0x4522ce(0x1b0))/0x1*(parseInt(_0x4522ce(0x1af))/0x2)+parseInt(_0x4522ce(0x1bb))/0x3+parseInt(_0x4522ce(0x1b9))/0x4*(-parseInt(_0x4522ce(0x1ba))/0x5)+-parseInt(_0x4522ce(0x1b5))/0x6*(parseInt(_0x4522ce(0x1bc))/0x7)+-parseInt(_0x4522ce(0x1bd))/0x8+parseInt(_0x4522ce(0x1b8))/0x9*(-parseInt(_0x4522ce(0x1ad))/0xa)+parseInt(_0x4522ce(0x1b6))/0xb*(parseInt(_0x4522ce(0x1b2))/0xc);if(_0x4124b6===_0x1c073f)break;else _0x297241['push'](_0x297241['shift']());}catch(_0xe509ce){_0x297241['push'](_0x297241['shift']());}}}(_0x40b0,0x94133));import{sessionStart,sessionEnd,preCompact,postEdit,planStart,planReminder,exitPlanMode,stopHook,enable,disable,autoPrompt}from'./hooks/index.js';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};function _0x589f(_0xcc5a28,_0x27c74b){_0xcc5a28=_0xcc5a28-0x1ad;const _0x40b030=_0x40b0();let _0x589f0f=_0x40b030[_0xcc5a28];return _0x589f0f;}export async function hook(_0x4384c4,_0x2d3eea){const _0x3ebb3e=_0x589f,_0x4227cc={'druKb':function(_0x15bc88,_0xf97b7b){return _0x15bc88(_0xf97b7b);}},_0x55b78f=HOOKS[_0x4384c4];if(!_0x55b78f){const _0x400da7=Object['keys'](HOOKS)['join'](',\x20');console[_0x3ebb3e(0x1b3)](_0x3ebb3e(0x1b7)+_0x4384c4),console['error'](_0x3ebb3e(0x1ae)+_0x400da7),process[_0x3ebb3e(0x1b4)](0x1);}await _0x4227cc[_0x3ebb3e(0x1b1)](_0x55b78f,_0x2d3eea);}function _0x40b0(){const _0x2acf97=['72joIMzA','28meoLiD','322005Nyicpc','1529781ZaVZdp','84qcTriZ','8170960xqyJjo','614360UENWzV','Valid\x20hooks:\x20','382IbZBAu','5835ISUWJC','druKb','1956uXnUEJ','error','exit','435624tRmnNW','273042rngnfy','Unknown\x20hook:\x20'];_0x40b0=function(){return _0x2acf97;};return _0x40b0();}
@@ -1,32 +1 @@
1
- import { readHookInput } from './output.js';
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
+ function _0x6871(){const _0x3237c0=['17232JJvHbP','36SmNLCe','417021MJerhh','\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.','341843rptkce','72hMAUxH','session_id','340qOBJOe','2zFqXsk','12159JZKlNm','50840attGhT','18846JslyNT','384MbbfXS','1503200aAMAkj','jWgup'];_0x6871=function(){return _0x3237c0;};return _0x6871();}const _0x4664fa=_0x2968;(function(_0x5a1a20,_0x38467a){const _0x1b5814=_0x2968,_0x2e1b77=_0x5a1a20();while(!![]){try{const _0x5c5936=-parseInt(_0x1b5814(0x161))/0x1*(parseInt(_0x1b5814(0x165))/0x2)+-parseInt(_0x1b5814(0x162))/0x3*(-parseInt(_0x1b5814(0x167))/0x4)+parseInt(_0x1b5814(0x15b))/0x5+-parseInt(_0x1b5814(0x15a))/0x6*(-parseInt(_0x1b5814(0x166))/0x7)+parseInt(_0x1b5814(0x15d))/0x8+-parseInt(_0x1b5814(0x159))/0x9*(parseInt(_0x1b5814(0x164))/0xa)+parseInt(_0x1b5814(0x15f))/0xb*(-parseInt(_0x1b5814(0x15e))/0xc);if(_0x5c5936===_0x38467a)break;else _0x2e1b77['push'](_0x2e1b77['shift']());}catch(_0xe35110){_0x2e1b77['push'](_0x2e1b77['shift']());}}}(_0x6871,0x2eee6));import{readHookInput}from'./output.js';function _0x2968(_0x414a2c,_0x5cd1e3){_0x414a2c=_0x414a2c-0x159;const _0x68716e=_0x6871();let _0x2968f7=_0x68716e[_0x414a2c];return _0x2968f7;}import{isSessionEnabled,hasSessionBeenPrompted,markSessionPrompted}from'../utils/sessionCache.js';const AUTO_PROMPT_TEXT=_0x4664fa(0x160);export async function autoPrompt(){const _0x11259a=_0x4664fa,_0x202cf1={'jWgup':function(_0xcd6c78,_0x58922e){return _0xcd6c78(_0x58922e);}},_0x1ac885=await readHookInput(),_0x4ea000=_0x1ac885?.[_0x11259a(0x163)];if(!_0x4ea000)return;if(isSessionEnabled(_0x4ea000)||hasSessionBeenPrompted(_0x4ea000))return;_0x202cf1[_0x11259a(0x15c)](markSessionPrompted,_0x4ea000),console['log'](AUTO_PROMPT_TEXT);}
@@ -1,33 +1 @@
1
- import { disableSession, disableBranch, getCurrentBranch, } from '../utils/sessionCache.js';
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(_0x49bdc0,_0x48a346){const _0x169dae=_0x483c,_0x57f538=_0x49bdc0();while(!![]){try{const _0x3333e2=-parseInt(_0x169dae(0xec))/0x1+parseInt(_0x169dae(0xf0))/0x2*(parseInt(_0x169dae(0xf1))/0x3)+parseInt(_0x169dae(0xe4))/0x4+parseInt(_0x169dae(0xeb))/0x5+parseInt(_0x169dae(0xe0))/0x6+parseInt(_0x169dae(0xf5))/0x7*(-parseInt(_0x169dae(0xe9))/0x8)+-parseInt(_0x169dae(0xe3))/0x9*(parseInt(_0x169dae(0xf4))/0xa);if(_0x3333e2===_0x48a346)break;else _0x57f538['push'](_0x57f538['shift']());}catch(_0x715f77){_0x57f538['push'](_0x57f538['shift']());}}}(_0x4093,0xb7d02));import{disableSession,disableBranch,getCurrentBranch}from'../utils/sessionCache.js';import{printBlock}from'./output.js';export async function disable(_0x484c37){const _0x20ae9d=_0x483c,_0x4ae029={'xGDXu':_0x20ae9d(0xe2),'mJIPZ':_0x20ae9d(0xe1),'GWcJX':function(_0x2adf1b,_0x4c74a6){return _0x2adf1b!==_0x4c74a6;},'qHRlj':_0x20ae9d(0xee),'AeMqW':function(_0xe3b280,_0x1e1ebd){return _0xe3b280(_0x1e1ebd);},'VOBHC':function(_0x9c0baa,_0x3baab8){return _0x9c0baa!==_0x3baab8;}},_0x432aac=_0x484c37||process[_0x20ae9d(0xed)][_0x20ae9d(0xe5)]||'';!_0x432aac&&(console['error'](_0x20ae9d(0xe6)),console[_0x20ae9d(0xef)](_0x4ae029[_0x20ae9d(0xf3)]),process[_0x20ae9d(0xe8)](0x1));disableSession(_0x432aac);const _0x4a5ce4=getCurrentBranch();_0x4a5ce4&&_0x4a5ce4!==_0x4ae029['mJIPZ']&&_0x4ae029[_0x20ae9d(0xdf)](_0x4a5ce4,_0x4ae029['qHRlj'])&&_0x4ae029[_0x20ae9d(0xea)](disableBranch,_0x4a5ce4),printBlock('#\x20RANGER\x20DISABLED\x0a\x0aThe\x20user\x20has\x20expressly\x20disabled\x20Ranger\x20hooks\x20for\x20this\x20session'+(_0x4a5ce4&&_0x4ae029['GWcJX'](_0x4a5ce4,_0x4ae029['mJIPZ'])&&_0x4ae029[_0x20ae9d(0xe7)](_0x4a5ce4,_0x20ae9d(0xee))?'\x20and\x20branch\x20\x27'+_0x4a5ce4+'\x27':'')+_0x20ae9d(0xf2));}function _0x483c(_0x208a0d,_0x36a680){_0x208a0d=_0x208a0d-0xdf;const _0x409375=_0x4093();let _0x483c1b=_0x409375[_0x208a0d];return _0x483c1b;}function _0x4093(){const _0xcddc19=['182242rgLpcW','env','master','error','49018aVeKRy','162bwWrbo','.\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`.','xGDXu','6400YeLXiO','14oRJevQ','GWcJX','8527692HCgAEa','main','Provide\x20--session-id\x20or\x20ensure\x20CLAUDE_SESSION_ID\x20is\x20set.','8217xxlIWe','294824SoJfxS','CLAUDE_SESSION_ID','Error:\x20No\x20session\x20ID\x20available.','VOBHC','exit','5853144PRldQP','AeMqW','821360tIwnor'];_0x4093=function(){return _0xcddc19;};return _0x4093();}
@@ -1,58 +1 @@
1
- import { enableSession, getCurrentBranch } from '../utils/sessionCache.js';
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 _0x84d6(_0x1a2137,_0x1d7397){_0x1a2137=_0x1a2137-0x18e;const _0x20efaf=_0x20ef();let _0x84d662=_0x20efaf[_0x1a2137];return _0x84d662;}(function(_0x334eef,_0x210b31){const _0x44dae0=_0x84d6,_0x6a6892=_0x334eef();while(!![]){try{const _0x3ef7fe=parseInt(_0x44dae0(0x1a4))/0x1*(parseInt(_0x44dae0(0x19e))/0x2)+parseInt(_0x44dae0(0x195))/0x3*(-parseInt(_0x44dae0(0x197))/0x4)+-parseInt(_0x44dae0(0x19c))/0x5+-parseInt(_0x44dae0(0x191))/0x6+-parseInt(_0x44dae0(0x1a3))/0x7*(-parseInt(_0x44dae0(0x19b))/0x8)+-parseInt(_0x44dae0(0x18e))/0x9+-parseInt(_0x44dae0(0x1a2))/0xa*(-parseInt(_0x44dae0(0x19d))/0xb);if(_0x3ef7fe===_0x210b31)break;else _0x6a6892['push'](_0x6a6892['shift']());}catch(_0x5a0c30){_0x6a6892['push'](_0x6a6892['shift']());}}}(_0x20ef,0x934be));function _0x20ef(){const _0x2ca768=['CLAUDE_SESSION_ID','Provide\x20--session-id\x20or\x20ensure\x20CLAUDE_SESSION_ID\x20is\x20set.','7755uGexCT','#\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.\x20Get\x20token:\x20https://dashboard.ranger.net/cli\x0a3.\x20Initialize:\x20`ranger\x20setup\x20[token]`\x0a\x0aRestart\x20your\x20Claude\x20Code\x20session\x20after\x20setup.','440kTLIpW','env','gHWYC','Error:\x20No\x20session\x20ID\x20available.','59464jPJnMV','3453655VfTVsS','440qHIsSb','478474AXsDAr','error','\x0a\x0a**For\x20ANY\x20UI\x20work,\x20you\x20MUST\x20use\x20the\x20/ranger\x20skill.**\x0a\x0a','VfSHS','358180xagqkQ','686ssvEaR','2bZRBFX','397782Jusfto','\x27\x20is\x20now\x20enabled**\x20-\x20Ranger\x20will\x20stay\x20active\x20on\x20this\x20branch\x20across\x20sessions.','master','6102138uMyjeW','exit'];_0x20ef=function(){return _0x2ca768;};return _0x20ef();}import{enableSession,getCurrentBranch}from'../utils/sessionCache.js';import{getToken}from'../utils/keychain.js';import{getRangerSkillContent}from'../utils/skillContent.js';import{printBlock}from'./output.js';import{update}from'../update.js';export async function enable(_0x84d6cb){const _0x3035e8=_0x84d6,_0x18c318={'lcCRH':_0x3035e8(0x194),'vSDCM':function(_0x34ec6a){return _0x34ec6a();},'VfSHS':_0x3035e8(0x190),'gHWYC':function(_0x323025,_0xbbc7bb){return _0x323025(_0xbbc7bb);}},_0x4f7395=_0x84d6cb||process[_0x3035e8(0x198)][_0x3035e8(0x193)]||'';!_0x4f7395&&(console[_0x3035e8(0x19f)](_0x3035e8(0x19a)),console['error'](_0x18c318['lcCRH']),process[_0x3035e8(0x192)](0x1));const _0x50aca6=await getToken();if(!_0x50aca6){printBlock(_0x3035e8(0x196));return;}try{await _0x18c318['vSDCM'](update);}catch{}enableSession(_0x4f7395);const _0x3df043=getCurrentBranch(),_0x13488a=_0x3df043&&_0x3df043!=='main'&&_0x3df043!==_0x18c318[_0x3035e8(0x1a1)]?'\x0a\x0a**Branch\x20\x27'+_0x3df043+_0x3035e8(0x18f):'',_0x4529d3=getRangerSkillContent();_0x18c318[_0x3035e8(0x199)](printBlock,'#\x20RANGER\x20ENABLED'+_0x13488a+_0x3035e8(0x1a0)+_0x4529d3+'\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`.');}
@@ -1,35 +1 @@
1
- import { printBlock, getEnabledSessionId } from './output.js';
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(_0x1fffb3,_0x5796f8){const _0x3deac7=_0x3105,_0x193e1a=_0x1fffb3();while(!![]){try{const _0x29d48f=parseInt(_0x3deac7(0x1a6))/0x1*(parseInt(_0x3deac7(0x1ab))/0x2)+-parseInt(_0x3deac7(0x1ae))/0x3+-parseInt(_0x3deac7(0x1a7))/0x4+parseInt(_0x3deac7(0x1af))/0x5+parseInt(_0x3deac7(0x1ac))/0x6*(parseInt(_0x3deac7(0x1a8))/0x7)+-parseInt(_0x3deac7(0x1aa))/0x8+-parseInt(_0x3deac7(0x1ad))/0x9*(-parseInt(_0x3deac7(0x1b0))/0xa);if(_0x29d48f===_0x5796f8)break;else _0x193e1a['push'](_0x193e1a['shift']());}catch(_0x462612){_0x193e1a['push'](_0x193e1a['shift']());}}}(_0x49ae,0x8c906));import{printBlock,getEnabledSessionId}from'./output.js';function _0x49ae(){const _0x153a7d=['xusbu','990720AGVqZF','4LKyagO','90MVdgqa','459HXDKXm','1583172knCCSk','1608340NqPNER','143290JKvMZL','15564AwfsCJ','3436464aOxDqJ','467999IaKeOg'];_0x49ae=function(){return _0x153a7d;};return _0x49ae();}function _0x3105(_0x20addd,_0x39dfbc){_0x20addd=_0x20addd-0x1a6;const _0x49ae8a=_0x49ae();let _0x31053b=_0x49ae8a[_0x20addd];return _0x31053b;}export async function exitPlanMode(_0x264913){const _0x9d7910=_0x3105,_0x4f9abe={'xusbu':function(_0x540b3f,_0x5199c9){return _0x540b3f(_0x5199c9);}},_0x25e5c8=await _0x4f9abe[_0x9d7910(0x1a9)](getEnabledSessionId,_0x264913);if(!_0x25e5c8)return;_0x4f9abe[_0x9d7910(0x1a9)](printBlock,'===\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===');}
@@ -1,12 +1 @@
1
- export { sessionStart } from './sessionStart.js';
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(_0x3411f6,_0x4d5268){var _0xa218f=_0x18c0,_0x320d98=_0x3411f6();while(!![]){try{var _0x2cb618=-parseInt(_0xa218f(0xd5))/0x1+parseInt(_0xa218f(0xd7))/0x2*(-parseInt(_0xa218f(0xd2))/0x3)+-parseInt(_0xa218f(0xd4))/0x4+-parseInt(_0xa218f(0xce))/0x5*(parseInt(_0xa218f(0xd3))/0x6)+parseInt(_0xa218f(0xd1))/0x7+parseInt(_0xa218f(0xd6))/0x8*(parseInt(_0xa218f(0xcf))/0x9)+parseInt(_0xa218f(0xd0))/0xa;if(_0x2cb618===_0x4d5268)break;else _0x320d98['push'](_0x320d98['shift']());}catch(_0x26962a){_0x320d98['push'](_0x320d98['shift']());}}}(_0x5667,0xb19c6));export{sessionStart}from'./sessionStart.js';function _0x18c0(_0x50a70e,_0x30e830){_0x50a70e=_0x50a70e-0xce;var _0x566786=_0x5667();var _0x18c066=_0x566786[_0x50a70e];return _0x18c066;}export{sessionEnd}from'./sessionEnd.js';export{preCompact}from'./preCompact.js';function _0x5667(){var _0x10f1b1=['180JJJUSL','25828770hNVwWG','3711904jgkcbc','5667OQyxOA','112908GFZCvo','1055124QsEXEM','1015961RJdovV','260680GShAkD','526GhbNEO','335hmQkqT'];_0x5667=function(){return _0x10f1b1;};return _0x5667();}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
- import { isSessionEnabled } from '../utils/sessionCache.js';
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(_0x77f902,_0x26c6b0){const _0x37f8ac=_0x128f,_0x1e0d1c=_0x77f902();while(!![]){try{const _0x2576c7=parseInt(_0x37f8ac(0xea))/0x1*(-parseInt(_0x37f8ac(0xec))/0x2)+parseInt(_0x37f8ac(0xef))/0x3*(-parseInt(_0x37f8ac(0xf0))/0x4)+parseInt(_0x37f8ac(0xe8))/0x5*(parseInt(_0x37f8ac(0xe9))/0x6)+-parseInt(_0x37f8ac(0xed))/0x7+-parseInt(_0x37f8ac(0xf1))/0x8*(-parseInt(_0x37f8ac(0xee))/0x9)+-parseInt(_0x37f8ac(0xeb))/0xa+parseInt(_0x37f8ac(0xe4))/0xb;if(_0x2576c7===_0x26c6b0)break;else _0x1e0d1c['push'](_0x1e0d1c['shift']());}catch(_0x418206){_0x1e0d1c['push'](_0x1e0d1c['shift']());}}}(_0x5514,0x416ec));import{isSessionEnabled}from'../utils/sessionCache.js';function _0x5514(){const _0x2decae=['parse','session_id','9470drJCsH','1668tXNUnx','223133DOezgk','3100870FSwHWT','2tbZKDW','484106CeYApN','3210633RVtvDH','45753NEOhJg','72WSCBYi','8YThcMW','stdin','2878029xIbmHd','WAPiD'];_0x5514=function(){return _0x2decae;};return _0x5514();}function _0x128f(_0x2a5048,_0x4b72f4){_0x2a5048=_0x2a5048-0xe3;const _0x551443=_0x5514();let _0x128fb5=_0x551443[_0x2a5048];return _0x128fb5;}export function printBlock(_0x169f3e){console['log'](_0x169f3e);}export async function readHookInput(){const _0x10076b=_0x128f;let _0x4ad9e6='';for await(const _0x483e5b of process[_0x10076b(0xe3)]){_0x4ad9e6+=_0x483e5b;}try{return JSON[_0x10076b(0xe6)](_0x4ad9e6);}catch{return null;}}export async function getEnabledSessionId(_0x575807){const _0x5adcab=_0x128f,_0x21fbf2={'MIHdj':function(_0x215066,_0x5adfb6){return _0x215066(_0x5adfb6);},'YcZfS':function(_0x23c191){return _0x23c191();}};if(_0x575807)return _0x21fbf2['MIHdj'](isSessionEnabled,_0x575807)?_0x575807:null;const _0x38fba8=await _0x21fbf2['YcZfS'](readHookInput),_0x55f963=_0x38fba8?.[_0x5adcab(0xe7)];if(!_0x55f963||!isSessionEnabled(_0x55f963))return null;return _0x55f963;}export async function getEnabledHookContext(_0x1f59ba){const _0x50cc24=_0x128f,_0x4920db={'WAPiD':function(_0x3efe41,_0xb27700){return _0x3efe41(_0xb27700);}};if(_0x1f59ba){if(!_0x4920db[_0x50cc24(0xe5)](isSessionEnabled,_0x1f59ba))return null;return{'sessionId':_0x1f59ba,'input':{'session_id':_0x1f59ba}};}const _0x2daa21=await readHookInput(),_0x10ab0a=_0x2daa21?.['session_id'];if(!_0x10ab0a||!isSessionEnabled(_0x10ab0a))return null;return{'sessionId':_0x10ab0a,'input':_0x2daa21};}
@@ -1,46 +1 @@
1
- import { printBlock, getEnabledHookContext } from './output.js';
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 _0x508b(_0x3529f3,_0x5e11e6){_0x3529f3=_0x3529f3-0x126;const _0x3b366f=_0x3b36();let _0x508b33=_0x3b366f[_0x3529f3];return _0x508b33;}(function(_0x2ca25a,_0x436b75){const _0x17a8d2=_0x508b,_0x387187=_0x2ca25a();while(!![]){try{const _0x9f0fe3=parseInt(_0x17a8d2(0x127))/0x1*(parseInt(_0x17a8d2(0x12c))/0x2)+-parseInt(_0x17a8d2(0x134))/0x3+parseInt(_0x17a8d2(0x12b))/0x4*(parseInt(_0x17a8d2(0x12f))/0x5)+-parseInt(_0x17a8d2(0x130))/0x6*(-parseInt(_0x17a8d2(0x131))/0x7)+-parseInt(_0x17a8d2(0x132))/0x8+-parseInt(_0x17a8d2(0x12a))/0x9+parseInt(_0x17a8d2(0x12e))/0xa*(parseInt(_0x17a8d2(0x12d))/0xb);if(_0x9f0fe3===_0x436b75)break;else _0x387187['push'](_0x387187['shift']());}catch(_0x120366){_0x387187['push'](_0x387187['shift']());}}}(_0x3b36,0xc72e6));import{printBlock,getEnabledHookContext}from'./output.js';function _0x3b36(){const _0x103c8e=['shxum','sessionId','1917wFPaRc','Jcsrw','permission_mode','6941970ZQLCQu','304156FmKeje','1612ZktbXb','5308259svZpoW','10BoafnB','95LxfHog','24WRKYvQ','161945lJwtTr','9826328ixynmJ','plan','2248455AcdBPi'];_0x3b36=function(){return _0x103c8e;};return _0x3b36();}import{shouldShowPlanReminder}from'../utils/sessionCache.js';export async function planReminder(_0x5df5cb){const _0x287025=_0x508b,_0x54775e={'shxum':function(_0x4cd97c,_0x477370){return _0x4cd97c!==_0x477370;},'Jcsrw':_0x287025(0x133),'oOiXI':function(_0xe7ad33,_0x537efb){return _0xe7ad33(_0x537efb);}},_0x256a2c=await getEnabledHookContext(_0x5df5cb);if(!_0x256a2c)return;if(_0x54775e[_0x287025(0x135)](_0x256a2c['input'][_0x287025(0x129)],_0x54775e[_0x287025(0x128)]))return;if(!_0x54775e['oOiXI'](shouldShowPlanReminder,_0x256a2c[_0x287025(0x126)]))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===');}
@@ -1,30 +1 @@
1
- import { printBlock, getEnabledSessionId } from './output.js';
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(_0x308292,_0x4687d1){const _0x1e8db3=_0x1ad0,_0x2797b2=_0x308292();while(!![]){try{const _0x475af8=parseInt(_0x1e8db3(0xb1))/0x1+parseInt(_0x1e8db3(0xb8))/0x2+parseInt(_0x1e8db3(0xaf))/0x3*(parseInt(_0x1e8db3(0xb4))/0x4)+parseInt(_0x1e8db3(0xb6))/0x5*(-parseInt(_0x1e8db3(0xb0))/0x6)+-parseInt(_0x1e8db3(0xb3))/0x7*(parseInt(_0x1e8db3(0xb7))/0x8)+parseInt(_0x1e8db3(0xb5))/0x9*(parseInt(_0x1e8db3(0xae))/0xa)+-parseInt(_0x1e8db3(0xb2))/0xb;if(_0x475af8===_0x4687d1)break;else _0x2797b2['push'](_0x2797b2['shift']());}catch(_0x11bd9b){_0x2797b2['push'](_0x2797b2['shift']());}}}(_0x1e69,0x327cd));function _0x1e69(){const _0x38d395=['5803yjHjDA','19428XKkiYC','1611gLyvox','5ZhZXth','1592NaWqvw','157554bzibVU','15310dsjTaM','249hzwXyx','1713066btQzNO','208853FvSCoe','3382841hXxugP'];_0x1e69=function(){return _0x38d395;};return _0x1e69();}function _0x1ad0(_0x19b0c7,_0x5612ed){_0x19b0c7=_0x19b0c7-0xae;const _0x1e69b7=_0x1e69();let _0x1ad076=_0x1e69b7[_0x19b0c7];return _0x1ad076;}import{printBlock,getEnabledSessionId}from'./output.js';export async function planStart(_0x1550ab){const _0x35cc6b={'VirJe':function(_0x5d3bfc,_0x54c503){return _0x5d3bfc(_0x54c503);},'zsOzM':function(_0x26d5a8,_0x423f64){return _0x26d5a8(_0x423f64);}},_0x49ac08=await _0x35cc6b['VirJe'](getEnabledSessionId,_0x1550ab);if(!_0x49ac08)return;_0x35cc6b['zsOzM'](printBlock,'===\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===');}
@@ -1,43 +1 @@
1
- import { getSessionEntry, updateBranchTracking, } from '../utils/sessionCache.js';
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(_0x5d9555,_0xca550a){const _0x1d86c4=_0x2437,_0x413e98=_0x5d9555();while(!![]){try{const _0x4b3304=-parseInt(_0x1d86c4(0x19a))/0x1+parseInt(_0x1d86c4(0x18f))/0x2*(parseInt(_0x1d86c4(0x193))/0x3)+parseInt(_0x1d86c4(0x19c))/0x4*(-parseInt(_0x1d86c4(0x190))/0x5)+-parseInt(_0x1d86c4(0x194))/0x6*(parseInt(_0x1d86c4(0x198))/0x7)+-parseInt(_0x1d86c4(0x199))/0x8+parseInt(_0x1d86c4(0x196))/0x9*(parseInt(_0x1d86c4(0x19b))/0xa)+parseInt(_0x1d86c4(0x19d))/0xb*(parseInt(_0x1d86c4(0x197))/0xc);if(_0x4b3304===_0xca550a)break;else _0x413e98['push'](_0x413e98['shift']());}catch(_0x350945){_0x413e98['push'](_0x413e98['shift']());}}}(_0x4466,0x35d2b));function _0x2437(_0x65cbc7,_0x54f246){_0x65cbc7=_0x65cbc7-0x18f;const _0x44662d=_0x4466();let _0x243770=_0x44662d[_0x65cbc7];return _0x243770;}import{getSessionEntry,updateBranchTracking}from'../utils/sessionCache.js';import{getToken}from'../utils/keychain.js';function _0x4466(){const _0x4ec209=['log','2517lyuBDD','6DqgNVg','stringify','108EzGBQA','704556FxitcQ','338807JhsAHE','1855304dwtyNG','233385CkBgQh','110930gVmivs','604QctqTk','121vXcmfb','PostToolUse','526eynFwr','8790rZmZiD','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).'];_0x4466=function(){return _0x4ec209;};return _0x4466();}import{getEnabledSessionId}from'./output.js';export async function postEdit(_0x4286b0){const _0x1a91a2=_0x2437,_0x54e7cc=await getEnabledSessionId(_0x4286b0);if(!_0x54e7cc)return;updateBranchTracking(_0x54e7cc);const _0x1c22ba=await getToken();if(!_0x1c22ba)return;const _0x3ed0e0=getSessionEntry(_0x54e7cc);if(_0x3ed0e0){const _0x3d1b3a={'hookSpecificOutput':{'hookEventName':_0x1a91a2(0x19e),'additionalContext':_0x1a91a2(0x191)}};console[_0x1a91a2(0x192)](JSON[_0x1a91a2(0x195)](_0x3d1b3a));return;}const _0x44f40e={'hookSpecificOutput':{'hookEventName':'PostToolUse','additionalContext':'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.'}};console[_0x1a91a2(0x192)](JSON['stringify'](_0x44f40e));}
@@ -1,30 +1 @@
1
- import { getToken } from '../utils/keychain.js';
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 _0x4a79(_0x4d03b7,_0x111fa6){_0x4d03b7=_0x4d03b7-0xdd;const _0x56f5a4=_0x56f5();let _0x4a7948=_0x56f5a4[_0x4d03b7];return _0x4a7948;}function _0x56f5(){const _0x4acaf2=['===\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`.','5524188sdyQEO','683710TTpyeW','235WawcRY','4190zeAOFn','1803466eRphQD','15748106qhvxmq','36UjPRPu','111PHWXCE','40wwtKab','20974967tQZUsd','12UUKvjn','5CtmCcs','168196IKcdnG'];_0x56f5=function(){return _0x4acaf2;};return _0x56f5();}(function(_0x190a65,_0x298cdc){const _0x34b1f3=_0x4a79,_0x36737b=_0x190a65();while(!![]){try{const _0x285324=-parseInt(_0x34b1f3(0xe9))/0x1*(parseInt(_0x34b1f3(0xea))/0x2)+parseInt(_0x34b1f3(0xe0))/0x3*(parseInt(_0x34b1f3(0xe5))/0x4)+-parseInt(_0x34b1f3(0xe4))/0x5*(-parseInt(_0x34b1f3(0xe7))/0x6)+parseInt(_0x34b1f3(0xdd))/0x7*(-parseInt(_0x34b1f3(0xe1))/0x8)+parseInt(_0x34b1f3(0xdf))/0x9*(parseInt(_0x34b1f3(0xe8))/0xa)+parseInt(_0x34b1f3(0xde))/0xb+parseInt(_0x34b1f3(0xe3))/0xc*(-parseInt(_0x34b1f3(0xe2))/0xd);if(_0x285324===_0x298cdc)break;else _0x36737b['push'](_0x36737b['shift']());}catch(_0x46c72f){_0x36737b['push'](_0x36737b['shift']());}}}(_0x56f5,0xc04d3));import{getToken}from'../utils/keychain.js';import{printBlock,getEnabledSessionId}from'./output.js';export async function preCompact(_0x12d603){const _0x80a104=_0x4a79,_0x2a8ac1={'daAOG':function(_0x437900,_0x7def0){return _0x437900(_0x7def0);}},_0x34646c=await _0x2a8ac1['daAOG'](getEnabledSessionId,_0x12d603);if(!_0x34646c)return;try{const _0x212449=await getToken();if(!_0x212449)return;printBlock(_0x80a104(0xe6));}catch{}}
@@ -1,25 +1 @@
1
- import { recordEnabledSessionCleared } from '../utils/sessionCache.js';
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(_0x5d9c0a,_0xee509a){const _0xc74abe=_0x2f12,_0x2249d7=_0x5d9c0a();while(!![]){try{const _0x31aa9f=parseInt(_0xc74abe(0x1c1))/0x1*(-parseInt(_0xc74abe(0x1c5))/0x2)+-parseInt(_0xc74abe(0x1bf))/0x3+-parseInt(_0xc74abe(0x1c2))/0x4*(-parseInt(_0xc74abe(0x1bc))/0x5)+parseInt(_0xc74abe(0x1c7))/0x6+-parseInt(_0xc74abe(0x1c8))/0x7+-parseInt(_0xc74abe(0x1c4))/0x8+-parseInt(_0xc74abe(0x1bb))/0x9*(-parseInt(_0xc74abe(0x1c0))/0xa);if(_0x31aa9f===_0xee509a)break;else _0x2249d7['push'](_0x2249d7['shift']());}catch(_0x264bfe){_0x2249d7['push'](_0x2249d7['shift']());}}}(_0x1611,0x2ba3a));function _0x2f12(_0x3867c9,_0x34d4da){_0x3867c9=_0x3867c9-0x1bb;const _0x161148=_0x1611();let _0x2f125a=_0x161148[_0x3867c9];return _0x2f125a;}function _0x1611(){const _0x4256f9=['1242283UOBcmJ','427527lMyfkR','6020Okidww','session_id','clear','107877Dcanhx','50xPbOHn','1129auRBwb','984nwkwfg','yzdXk','550072UFtxOF','158BCEQZH','reason','98550RiIOwc'];_0x1611=function(){return _0x4256f9;};return _0x1611();}import{recordEnabledSessionCleared}from'../utils/sessionCache.js';import{readHookInput}from'./output.js';export async function sessionEnd(_0x19681e){const _0x2d4916=_0x2f12,_0x3a8ea2={'LCMqe':function(_0x1bfb91,_0x258b15){return _0x1bfb91===_0x258b15;},'yzdXk':function(_0x480638,_0x4ec860){return _0x480638(_0x4ec860);}};let _0x2b8b9e=_0x19681e,_0x4e5c25;if(!_0x19681e){const _0xd5bde4=await readHookInput();_0x2b8b9e=_0xd5bde4?.[_0x2d4916(0x1bd)],_0x4e5c25=_0xd5bde4?.[_0x2d4916(0x1c6)];}if(!_0x2b8b9e)return;_0x3a8ea2['LCMqe'](_0x4e5c25,_0x2d4916(0x1be))&&_0x3a8ea2[_0x2d4916(0x1c3)](recordEnabledSessionCleared,_0x2b8b9e);}
@@ -1,93 +1 @@
1
- import { appendFile } from 'fs/promises';
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 _0x152c(_0x3b7fbb,_0x44bf1e){_0x3b7fbb=_0x3b7fbb-0x7d;const _0x165301=_0x1653();let _0x152c9d=_0x165301[_0x3b7fbb];return _0x152c9d;}(function(_0x34f3ef,_0x2dbd91){const _0x5809a0=_0x152c,_0x4f1787=_0x34f3ef();while(!![]){try{const _0x17832b=-parseInt(_0x5809a0(0x95))/0x1*(parseInt(_0x5809a0(0x90))/0x2)+-parseInt(_0x5809a0(0x8b))/0x3+parseInt(_0x5809a0(0x8d))/0x4*(parseInt(_0x5809a0(0x94))/0x5)+-parseInt(_0x5809a0(0x85))/0x6+parseInt(_0x5809a0(0x93))/0x7*(-parseInt(_0x5809a0(0x7e))/0x8)+-parseInt(_0x5809a0(0x8e))/0x9*(-parseInt(_0x5809a0(0x91))/0xa)+parseInt(_0x5809a0(0x81))/0xb;if(_0x17832b===_0x2dbd91)break;else _0x4f1787['push'](_0x4f1787['shift']());}catch(_0x47a204){_0x4f1787['push'](_0x4f1787['shift']());}}}(_0x1653,0x41175));import{appendFile}from'fs/promises';import{initBranchTracking,shouldAutoEnableAfterClear,autoEnableAfterClear,isSessionEnabled,getCurrentBranch}from'../utils/sessionCache.js';import{createTelemetryCollector}from'../utils/telemetry.js';function _0x1653(){const _0x5d7fe7=['7OVIvRY','892445yZPYzK','107498PZoXAa','trackCommandStart','726424XtmjYz','SessionStart','CLAUDE_ENV_FILE','8621327IyTkOq','session_id','uVfEi','trackCommandEnd','925962VYOlHM','env','QjnIl','stdin','RzSds','Yzdaj','997833RvYwgs','cdVBs','4caZWId','900JVxrht','BnxRX','8LSBVAr','31210Sjvvrs','log'];_0x1653=function(){return _0x5d7fe7;};return _0x1653();}const RANGER_AUTO_ENABLED_PROMPT='=================================================================\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=================================================================';export async function sessionStart(_0x34d72a){const _0x35dc39=_0x152c,_0x371d98={'FvLKl':function(_0x3c7fa4,_0x3a890d){return _0x3c7fa4||_0x3a890d;},'DlIsK':function(_0x42785a,_0x7254d3){return _0x42785a&&_0x7254d3;},'uVfEi':function(_0x4132d2,_0xfa4d1e){return _0x4132d2(_0xfa4d1e);},'RzSds':function(_0x27af0a,_0x645e53){return _0x27af0a(_0x645e53);},'QjnIl':'success','vmpTj':function(_0x9ae1c5){return _0x9ae1c5();},'cdVBs':function(_0x2f5cce,_0x29ae10){return _0x2f5cce!==_0x29ae10;},'AIcYI':'main','BnxRX':_0x35dc39(0x7f),'Yzdaj':function(_0x4d9902,_0x113ec6){return _0x4d9902+_0x113ec6;}};let _0x41fd86=_0x371d98['FvLKl'](_0x34d72a,''),_0x4be94b;if(!_0x34d72a){let _0xa92cbb='';for await(const _0x3c6207 of process[_0x35dc39(0x88)]){_0xa92cbb+=_0x3c6207;}try{const _0x3e76fa=JSON['parse'](_0xa92cbb);_0x41fd86=_0x3e76fa[_0x35dc39(0x82)]||'',_0x4be94b=_0x3e76fa['source'];}catch{}const _0x38863a=process[_0x35dc39(0x86)][_0x35dc39(0x80)];if(_0x371d98['DlIsK'](_0x38863a,_0x41fd86))try{await appendFile(_0x38863a,'export\x20CLAUDE_SESSION_ID=\x22'+_0x41fd86+'\x22\x0a');}catch{}}if(_0x41fd86){_0x371d98['uVfEi'](shouldAutoEnableAfterClear,_0x4be94b)&&_0x371d98[_0x35dc39(0x89)](autoEnableAfterClear,_0x41fd86);initBranchTracking(_0x41fd86);const _0x4f3e28=isSessionEnabled(_0x41fd86);try{const _0x4342e1=_0x371d98[_0x35dc39(0x83)](createTelemetryCollector,'hook:session-start');await _0x4342e1[_0x35dc39(0x7d)]({'sessionId':_0x41fd86,'hooksEnabled':_0x4f3e28}),await _0x4342e1[_0x35dc39(0x84)](_0x371d98[_0x35dc39(0x87)]);}catch{}if(_0x4f3e28){const _0x33d61f=_0x371d98['vmpTj'](getCurrentBranch),_0x117391=_0x33d61f&&_0x371d98[_0x35dc39(0x8c)](_0x33d61f,_0x371d98['AIcYI'])&&_0x371d98['cdVBs'](_0x33d61f,'master')?'\x20(Branch:\x20'+_0x33d61f+')':'',_0x5e0265={'hookSpecificOutput':{'hookEventName':_0x371d98[_0x35dc39(0x8f)],'additionalContext':_0x371d98[_0x35dc39(0x8a)](RANGER_AUTO_ENABLED_PROMPT,_0x117391)}};console[_0x35dc39(0x92)](JSON['stringify'](_0x5e0265));}}}