superclawd 0.1.0 β†’ 0.1.2

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/README.md CHANGED
@@ -6,7 +6,7 @@ One command. Your standards, every session.
6
6
 
7
7
  ```bash
8
8
  npm install -g superclawd
9
- superclawd configure # connect your workspace (one time)
9
+ superclawd login # connect this machine in your browser (one time)
10
10
  superclawd # launch Claude Code, supercharged
11
11
  ```
12
12
 
@@ -17,7 +17,9 @@ superclawd # launch Claude Code, supercharged
17
17
  - 🧠 **Your skills, on tap** β€” workspace skills and instructions load into every session and apply automatically when they're relevant.
18
18
  - πŸ€– **Your agents** β€” the specialized agents you've defined are available as Claude Code subagents.
19
19
  - ⚑ **Commands & workflows** β€” your reusable commands and processes, ready to run.
20
+ - πŸ”Œ **Your team's MCP servers** β€” MCP servers your workspace curates (with their secrets) are injected into every session automatically; no per-machine `.mcp.json` to maintain.
20
21
  - πŸ“ **Always‑on rules** β€” your foundational standards stay in effect for the whole session, even after `/clear` or a compaction.
22
+ - πŸ›‘οΈ **Guardrails** β€” your workspace's enforced rules intercept risky tool calls _before_ they run (block, require approval, or warn) β€” applied to every session automatically, even under `--dangerously-skip-permissions`.
21
23
  - πŸ”” **Notifications** β€” get pinged the moment Claude needs your input or finishes a task, so you can step away and come back at the right time.
22
24
 
23
25
  You manage all of it from your dashboard at **[superclawd.com](https://superclawd.com)** β€” update a skill once and every teammate's next session picks it up.
@@ -38,18 +40,15 @@ npm install -g superclawd
38
40
 
39
41
  ## Set up (one time)
40
42
 
41
- Grab your credentials from the dashboard under **Settings β†’ Credentials** (a key ID, a secret, and your workspace slug), then run:
43
+ Connect this machine to your account in the browser β€” no copy‑pasting:
42
44
 
43
45
  ```bash
44
- superclawd configure
46
+ superclawd login
45
47
  ```
46
48
 
47
- It walks you through connecting your workspace and saves your credentials securely on your machine, so you only do this once.
49
+ This opens your browser. Approve the request under **Settings β†’ Devices**, and the CLI receives a credential for this machine automatically. You only do this once per machine.
48
50
 
49
- ```bash
50
- superclawd configure --show # show your current configuration
51
- superclawd configure --reset # clear it and start over
52
- ```
51
+ Manage or revoke your connected machines any time under **Settings β†’ Devices** in the dashboard. Re‑running `superclawd login` rotates this machine's credential.
53
52
 
54
53
  ## Use it
55
54
 
@@ -63,17 +62,53 @@ That launches Claude Code with your workspace's skills, agents, commands, workfl
63
62
 
64
63
  > Prefer plain Claude Code for a one‑off? Just run `claude` directly. `superclawd` is the supercharged way in.
65
64
 
66
- ## Your default workspace
65
+ ### Non‑interactive (print) mode
67
66
 
68
- On more than one team or project? A single set of credentials works across **all** your workspaces. `superclawd switch` sets your **default workspace** β€” the one each `superclawd` launch boots into:
67
+ Run a single prompt and print the result β€” handy for scripts or testing how your workspace config behaves:
69
68
 
70
69
  ```bash
71
- superclawd switch
70
+ superclawd -p "review this diff and apply our code standards"
72
71
  ```
73
72
 
74
- Pick from your workspaces and you're set; your next `superclawd` launch uses it. No need to reconfigure.
73
+ This boots the same plugin (skills/agents/teams/workflows/MCP) and runs the prompt via `claude -p`, then exits. It never prompts for a workspace β€” it resolves one in order: `--workspace <id>` flag β†’ `SUPERCLAWD_MCP_WORKSPACE` env var β†’ your stored default. In non-interactive mode (`-p`, `--pipelines`, or no TTY) with none of those set, the CLI prints a clear error and exits β€” it never prompts or hangs. Add `--no-capture` to skip writing learned memories for the run.
74
+
75
+ ## Your default workspace
76
+
77
+ On more than one team or project? A connected machine works across **all** your workspaces. Your **default workspace** is the one future `superclawd` launches boot into, and you set it right from the startup picker.
78
+
79
+ When you run `superclawd` interactively, a workspace picker appears:
80
+
81
+ - **↑/↓** β€” highlight a workspace
82
+ - **Enter** β€” launch into the highlighted workspace for this session
83
+ - **`d`** β€” mark the highlighted workspace as your **default** (shown with a β˜…)
75
84
 
76
- Prefer to choose per launch? Turn on **Choose workspace at startup** in `superclawd config` β€” then every `superclawd` shows the picker first and boots into whatever you pick (just for that session; your default stays put).
85
+ For a given run, the workspace is resolved in this order: `--workspace <id>` flag β†’ `SUPERCLAWD_MCP_WORKSPACE` env var β†’ your stored default β†’ (interactive only) the startup picker.
86
+
87
+ By default, every `superclawd` shows the picker first and boots into whatever you highlight and Enter (just for that session; your default β€” the β˜… β€” stays put unless you press `d`). Prefer to skip the picker and boot straight into your stored default? Turn off **Choose workspace at startup** in `superclawd config`. If your stored default ever becomes inaccessible (you're removed from it, it's deleted, or its slug changes), the CLI clears it automatically and shows the picker on the next launch.
88
+
89
+ ---
90
+
91
+ ## Memory
92
+
93
+ SuperClawd carries durable context across sessions through four memory tiers. The CLI participates in all of them:
94
+
95
+ | Tier | Scope | Source | How it's surfaced |
96
+ | ----------- | ----------- | ----------------------- | ------------------------------------------------------ |
97
+ | **Team** | `workspace` | Human-authored | Injected at SessionStart for everyone in the workspace |
98
+ | **Repo** | `repo` | AI-captured | Scoped to the current repo (git-remote fingerprint) |
99
+ | **Agent** | `agent` | AI-captured | Scoped to the active agent |
100
+ | **Private** | `private` | AI-captured or self-authored, per-member | Account-scoped β€” injected for the author only, across every workspace they belong to |
101
+
102
+ When a tier is enabled for your workspace, the CLI registers the memory MCP tools so Claude can curate it in-session:
103
+
104
+ - `record_memory` β€” capture a new memory
105
+ - `list_memories` β€” list existing memories
106
+ - `update_memory` β€” refine an existing memory
107
+ - `remove_memory` β€” delete a memory
108
+ - `search_memories` β€” hybrid recall (semantic + keyword) across the visible tiers; returns index hits (titles + ids)
109
+ - `get_memories` β€” fetch the full bodies for index ids on demand
110
+
111
+ AI-tier memories are served at SessionStart as a small **CORE** (full bodies) plus a compact **INDEX** (titles + ids) whose bodies are pulled on demand, plus mid-session auto-retrieve via the `UserPromptSubmit` / `PreToolUse:Read` hooks (disable with `SUPERCLAWD_AUTO_RETRIEVE=0`).
77
112
 
78
113
  ---
79
114
 
@@ -83,7 +118,10 @@ Run `superclawd config` for an interactive menu (↑/↓ to move, **Space/Enter*
83
118
 
84
119
  - **Notifications** β€” your default for new sessions: get pinged when Claude needs you or finishes.
85
120
  - **Dangerously skip permissions** β€” launch Claude Code without approval prompts. Off by default; turn it on only if you understand the trade‑off.
86
- - **Choose workspace at startup** β€” show the workspace picker each time you run `superclawd` and boot into the one you choose (per session; doesn't change your default). Off by default.
121
+ - **Choose workspace at startup** β€” show the workspace picker each time you run `superclawd`. Highlight with ↑/↓ and press **Enter** to boot into a workspace for that session (doesn't change your default), or press **`d`** to make the highlighted workspace your default (β˜…). On by default; turn it off to boot straight into your stored default workspace. A stored default that becomes inaccessible self-heals β€” the CLI clears it and shows the picker again.
122
+ - **Private Memory** β€” let the AI remember your personal preferences across all your sessions (private to you, never shared). On by default; turn it off and no private memories are captured or injected for you.
123
+ - **Experimental mode** β€” serve the **live draft** of any entity flagged experimental (skills **and** agents), instead of its stable release. Off by default; only entities explicitly marked experimental are affected (everything else still serves its stable release).
124
+ - **Keep Awake** β€” prevent your computer from sleeping while a session is running. Off by default.
87
125
 
88
126
  ### Notifications
89
127
 
@@ -97,15 +135,19 @@ Your default lives in `superclawd config`. Inside a session you can flip notific
97
135
 
98
136
  Once Claude Code is running, these slash commands are always available:
99
137
 
100
- | Command | What it does |
101
- | --- | --- |
102
- | `/superclawd:notifications` | Toggle notifications for the current session |
103
- | `/superclawd:status` | Show service status, your workspace, and credit balance |
104
- | `/superclawd:audit-work` | Check the work so far against your active standards |
105
- | `/superclawd:ultrathink` | Apply maximum extended thinking to the task at hand |
138
+ | Command | What it does |
139
+ | --------------------------- | ------------------------------------------------------- |
140
+ | `/superclawd:notifications` | Toggle notifications for the current session |
141
+ | `/superclawd:status` | Show service status, your workspace, and credit balance |
142
+ | `/superclawd:audit-work` | Check the work so far against your active standards |
143
+ | `/superclawd:ultrathink` | Apply maximum extended thinking to the task at hand |
144
+
145
+ > The plugin's slash commands are namespaced as `/superclawd:<command>` β€” the bare form (e.g. `/status`) is unavailable.
106
146
 
107
147
  ## Keep it up to date
108
148
 
149
+ `superclawd` checks for a newer version on launch and updates itself automatically before starting, so you're never on an outdated CLI. To update manually any time:
150
+
109
151
  ```bash
110
152
  superclawd update
111
153
  ```
@@ -114,15 +156,15 @@ superclawd update
114
156
 
115
157
  ## Command reference
116
158
 
117
- | Command | Description |
118
- | --- | --- |
119
- | `superclawd` | Launch Claude Code with your workspace loaded |
120
- | `superclawd configure` | Connect your workspace (interactive); `--show`, `--reset` |
121
- | `superclawd switch` | Set your default workspace (pick from yours) |
122
- | `superclawd config` | Toggle notifications + launch options |
123
- | `superclawd update` | Update to the latest version |
124
- | `superclawd version` | Print the installed version |
125
- | `superclawd help` | Show help |
159
+ | Command | Description |
160
+ | ---------------------------------- | ------------------------------------------------------------------------------------- |
161
+ | `superclawd` | Launch Claude Code with your workspace loaded |
162
+ | `superclawd --resume [session-id]` | Resume a prior Claude Code conversation (alias `-r`; omit the id to pick from a list) |
163
+ | `superclawd login` | Connect this machine in your browser (one time per machine) |
164
+ | `superclawd config` | Toggle notifications + launch options |
165
+ | `superclawd update` | Update to the latest version |
166
+ | `superclawd version` | Print the installed version |
167
+ | `superclawd help` | Show help |
126
168
 
127
169
  ---
128
170
 
@@ -1,5 +1,5 @@
1
1
  import { createRequire as __cr } from 'module'; const require = __cr(import.meta.url);
2
- import{readFileSync as m,writeFileSync as $,existsSync as F}from"node:fs";import{basename as Y}from"node:path";import{randomUUID as B}from"node:crypto";import{spawn as b}from"node:child_process";var R=`SUPERCLAWD \u2014 operating manual (always in effect):
2
+ import{readFileSync as y,writeFileSync as K,appendFileSync as Ue,existsSync as L,readdirSync as $e,statSync as X,unlinkSync as We}from"node:fs";import{basename as Ye}from"node:path";import{homedir as Je}from"node:os";import{pathToFileURL as je}from"node:url";var Q=["You maintain the durable memory for ONE repository. You review a FINISHED coding session and RECONCILE what it taught against the memories ALREADY SAVED (shown below with ids), keeping the set accurate, current, and non-redundant for the NEXT session. ","SAVE or UPDATE a fact when it would save a newcomer real time or prevent a wrong turn \u2014 for example: the build/test/run command (especially anything non-default, e.g. a subdirectory or required env flags); where key code or config lives when the layout is non-obvious (e.g. the app is in a subdirectory, or content is data-driven from one file); a setup step or arrangement needed to make things work (e.g. ESM-only deps must be mocked for tests to run); a correction to a reasonable wrong assumption (e.g. the repo uses npm despite a pnpm convention); or a non-obvious gotcha and its fix. A fact STILL qualifies even if it 'could be figured out by reading the files'. ","NEVER save: secrets or credentials; code dumps; transient state (a test that merely happened to pass or fail this run); one-off task details; or truly trivial facts (e.g. 'this is a React project', or that a file exists). ","NEVER bake VOLATILE SuperClawd identifiers into a fact: a workflow/skill/command/agent SLUG or id, or a tool-invocation recipe like 'call get_workflow with <slug>'. These break the moment the entity is renamed. Refer to an entity by its human NAME (e.g. the 'Code Review Process' workflow), or omit the identifier entirely. ","CRITICAL \u2014 the ALREADY-SAVED list is the ONLY knowledge future sessions have. If it is NONE, this repo has ZERO saved knowledge: nobody knows the build command, the package manager, or where the app lives \u2014 so the session's basic orientation facts (build/test command, package manager, where the app actually lives, key setup steps) are exactly what the first memories should record. Never call a fact 'already known' or 'standard' \u2014 judge only against the literal list. ","Emit OPERATIONS against the existing set: ",'\u2022 "create" \u2014 a genuinely NEW fact not represented by any existing memory. ','\u2022 "update" \u2014 the session REFINES, SHARPENS, or CORRECTS an existing memory: cite its id and rewrite its COMPLETE body to the now-correct version. Prefer update over create whenever an existing memory is about the same thing (the package manager, the app location, the build command, \u2026), even if the wording differs. A correction (e.g. the app moved from apps/web to apps/app) is an UPDATE to that memory, NOT a new one. When you correct a fact, also UPDATE any OTHER memory that still references the now-stale version. ',"\u2022 Omit any fact already captured accurately (no op). ","A memory tagged [LOCKED] is read-only: never update it; you may only create a complementary fact. ","Keep the set MINIMAL and CURRENT: never leave two memories about the same thing, and never leave an outdated fact beside its correction. ",'CRITICAL \u2014 within THIS single response, every fact must end up in EXACTLY ONE memory: never emit a "create" whose content is already covered by (or overlaps) a memory you keep or "update" in the same response. If the session adds a fact related to an existing memory, FOLD it into that memory with ONE "update" \u2014 do NOT also create a separate memory for the same fact. ',"This is a ONE-SHOT reconciliation of an already-finished session \u2014 do NOT continue the work, ask questions, or take any action. ",`Every op MUST include a "title": a distilled, human one-line SUMMARY of its body (<=120 chars) \u2014 a real summary, NOT the body's first words copied verbatim. `,'Respond with ONLY a strict JSON object {"ops":[ ... ],"reason":"<short overall why>"} and nothing else. Each op is {"op":"create","title":"<=120-char summary","body":"<self-contained 1-4 sentence note with concrete commands/paths + the gotcha & its fix>"} or {"op":"update","id":"<existing id>","title":"<=120-char summary","body":"<rewritten complete note>"}. If the session taught nothing durable, return {"ops":[],"reason":"..."}.'].join(""),ee=["You review a FINISHED coding session and RECONCILE what it taught against the memories ALREADY SAVED (shown below with ids), keeping each memory set accurate, current, and non-redundant for the NEXT session. You maintain TWO memory sets and route every op to the correct one: ",'\u2022 "repo" \u2014 durable knowledge about THIS repository, SHARED with the whole team: the build/test/run command (especially non-default ones, e.g. a subdirectory or required env flags); where key code/config lives when non-obvious; a required setup step (e.g. an ESM-only dep must be mocked for tests); a correction to a wrong assumption; or a non-obvious gotcha and its fix. A rule about the codebase, the product, or how the TEAM works is "repo" EVEN IF the user phrases it as "I want\u2026", "always\u2026", or "going forward\u2026". A fact STILL qualifies even if it could be figured out by reading the files. ',`\u2022 "private" \u2014 a preference PRIVATE to THIS individual user about how THEY themselves want to work or be treated: tone/verbosity, what to call them, their experience level, editor/workflow habits, how the assistant should behave toward them specifically. NEVER shared with the team. ONLY for preferences about the person themselves \u2014 never about the code or the team's process. `,'Route each fact by what it is ABOUT \u2014 the WORK/team (repo) or the PERSON (private). Do NOT require the user to label something "private"; infer it. When genuinely unsure whether a stated preference is a team convention or a private one, treat it as "repo" (shared): never leak a team rule into a private memory, and never put a genuinely private preference into the shared repo set. ',"NEVER save (either set): secrets or credentials; code dumps; transient state (a test that merely passed/failed this run); one-off task details; trivia. ","NEVER bake VOLATILE SuperClawd identifiers into a fact: a workflow/skill/command/agent SLUG or id, or a tool-invocation recipe like 'call get_workflow with <slug>'. These break the moment the entity is renamed. Refer to an entity by its human NAME, or omit the identifier entirely. ","CRITICAL \u2014 the ALREADY-SAVED lists are the ONLY knowledge future sessions have. If a set is NONE it has ZERO saved knowledge (nobody knows the build command, package manager, or where the app lives), so the session's basic orientation facts are exactly what its first memories should record. Judge 'already known' only against the literal lists, never against what is 'standard'. ","Emit OPERATIONS, each tagged with its scope: ",'\u2022 {"op":"create","scope":"repo"|"private","body":"<self-contained note>"} \u2014 a genuinely NEW fact/preference not represented by any existing memory in that set. ','\u2022 {"op":"update","scope":"repo","id":"<existing repo id>","body":"<rewritten COMPLETE body>"} \u2014 the session REFINES, SHARPENS, or CORRECTS an existing REPO memory: prefer update over create whenever an existing repo memory is about the same thing (the package manager, the app location, \u2026); a correction (e.g. the app moved from apps/web to apps/app) is an UPDATE, not a new memory; also update any other repo memory that still references a now-stale fact. UPDATE applies to the repo set ONLY. ','\u2022 For the PRIVATE set, emit ONLY "create" for a genuinely new preference \u2014 never update or restate one already saved (the user curates their private memories themselves); omit (no op) any private preference already captured. ',"\u2022 Omit any fact already captured accurately (no op). ","A memory tagged [LOCKED] is read-only: never update it; you may only create a complementary fact. ","Keep each set MINIMAL and CURRENT: never leave two memories about the same thing, and never leave an outdated fact beside its correction. ",'CRITICAL \u2014 within THIS single response, every fact must end up in EXACTLY ONE memory of its set: never emit a "create" whose content is already covered by (or overlaps) a memory you keep or "update" in the same response. If the session adds a fact related to an existing memory, FOLD it into that memory with ONE "update" \u2014 do NOT also create a separate memory for the same fact. ',"This is a ONE-SHOT reconciliation of an already-finished session \u2014 do NOT continue the work, ask questions, or take any action. ",`Every op MUST include a "title": a distilled, human one-line SUMMARY of its body (<=120 chars) \u2014 a real summary, NOT the body's first words copied verbatim. `,'Respond with ONLY a strict JSON object {"ops":[ ... ],"reason":"<short overall why>"} and nothing else. Each op is {"op":"create","scope":"repo"|"private","title":"<=120-char summary","body":"..."} or {"op":"update","scope":"repo","id":"<existing id>","title":"<=120-char summary","body":"..."}. If the session taught nothing durable, return {"ops":[],"reason":"..."}.'].join(""),te=["You maintain the durable lessons for a single reusable AGENT (a specialist invoked to do a job). You review a FINISHED run and RECONCILE what it learned about HOW TO PERFORM ITS ROLE against the lessons ALREADY SAVED (shown below with ids), keeping the set accurate, current, and non-redundant for the agent's NEXT invocation (in ANY repository). ","SAVE or UPDATE a lesson when it would make this agent do its job better next time: a standing preference or convention the user/team established for its work, a correction to how it should operate, or a recurring gotcha in its domain and how to handle it. Lessons are about the ROLE, not a codebase \u2014 they qualify regardless of which repo this run happened in. ","NEVER save: secrets or credentials; code dumps; one-off task details specific only to THIS single run; transient state; or truly trivial facts. ","NEVER record a lesson about TOOL AVAILABILITY \u2014 e.g. that a tool 'does not exist', 'is unavailable', 'is not in the toolset', or that a call failed because the tool wasn't callable. Which tools a run can call is an environment/config detail set per-invocation (this agent runs with a RESTRICTED toolset that omits tools the main session has), NOT a durable fact about the role: the tool may well exist and be available in another context, so such a lesson is misleading and goes stale. Treat a 'no such tool' / 'tool not found' error as a transient environment artifact, never a lesson. ","The ALREADY-SAVED list is the ONLY knowledge the agent carries between runs \u2014 treat anything NOT listed as new; never claim a lesson is 'already known' unless it literally appears. ","IMPORTANT \u2014 the agent runs under workspace SKILLS, instructions, and guardrails that you CANNOT see in this transcript. So: do NOT treat an asserted convention, rule, or guideline as fabricated or 'hallucinated' merely because the transcript shows no basis for it \u2014 it may come from the agent's hidden instructions. NEVER record a lesson that tells the agent to stop asserting conventions, to second-guess its guidance, or that is based on YOUR OWN judgment that the agent made a mistake this run. Capture a lesson ONLY when the run itself shows the USER establishing or correcting a standing preference, or a concrete reproducible domain gotcha the agent itself confirmed. ","Emit OPERATIONS against the existing set: ",'\u2022 "create" \u2014 a genuinely NEW lesson not represented by any existing one. ','\u2022 "update" \u2014 the run REFINES or CORRECTS an existing lesson: cite its id and rewrite its COMPLETE body. Prefer update over create whenever an existing lesson is about the same thing, even if the wording differs. ',"\u2022 Omit any lesson already captured accurately (no op). ","A lesson tagged [LOCKED] is read-only: never update it; you may only create a complementary lesson. ","Keep the set MINIMAL and CURRENT: never leave two lessons about the same thing, and never leave an outdated lesson beside its correction. ",'CRITICAL \u2014 within THIS single response, every lesson must end up exactly ONCE: never emit a "create" whose content is already covered by (or overlaps) a lesson you keep or "update" in the same response. If the run adds something related to an existing lesson, FOLD it in with ONE "update" \u2014 do NOT also create a separate lesson for the same thing. ',"This is a ONE-SHOT reconciliation of an already-finished run \u2014 do NOT continue the work, ask questions, or take any action. ",`Every op MUST include a "title": a distilled, human one-line SUMMARY of its lesson (<=120 chars) \u2014 a real summary, NOT the lesson's first words copied verbatim. `,'Respond with ONLY a strict JSON object {"ops":[ ... ],"reason":"<short overall why>"} and nothing else. Each op is {"op":"create","title":"<=120-char summary","body":"<self-contained instruction the agent can apply next time>"} or {"op":"update","id":"<existing id>","title":"<=120-char summary","body":"<rewritten complete lesson>"}. If the run taught nothing durable, return {"ops":[],"reason":"..."}.'].join("");var ne=["You decide whether a code change makes a remembered lesson STALE (no longer true).",'Respond ONLY strict JSON {"verdict":"stale"|"valid","reason":"<one line>","confidence":<0..1>}.'].join(" ");import{randomUUID as ge}from"node:crypto";import{spawn as x,execSync as D}from"node:child_process";var Re=`SUPERCLAWD \u2014 operating manual (always in effect):
3
3
  - The ALWAYS rules below are ALREADY LOADED and active for this entire session.
4
4
  Apply them directly to all work. Do NOT call any tool to fetch them \u2014 you
5
5
  already have them in full.
@@ -8,8 +8,65 @@ import{readFileSync as m,writeFileSync as $,existsSync as F}from"node:fs";import
8
8
  the \`get_directives\` tool with that file's skillId (a UUID) BEFORE acting,
9
9
  and apply what it returns. Those skill files are pointers, not the rules.
10
10
  - Only call \`get_directives\` with a UUID skillId taken from an activated skill
11
- file. Never call it for the ALWAYS rules, and never pass a skill name.`;function D(t){let e=R,n=(t||"").trim();return n&&(e+=`
11
+ file. Never call it for the ALWAYS rules, and never pass a skill name.
12
+ - MEMORY: when the user states something durable \u2014 a fact, preference, or standing
13
+ rule, ESPECIALLY phrased as "remember\u2026", "from now on", "always", or "going
14
+ forward" \u2014 call \`record_memory\` RIGHT AWAY to persist it (silently; it picks the
15
+ scope on its own: the user's PRIVATE memory, the TEAM's, or the REPO's). Acknowledging
16
+ a durable instruction is NOT persisting it \u2014 you must actually record it. But do NOT
17
+ record one-off chit-chat or personal trivia that won't shape future work (e.g. "I love
18
+ candies") \u2014 just acknowledge those and move on. Still NEVER
19
+ ask where to store it, present a "how should I remember this?" menu, or offer to edit
20
+ an agent definition to save a preference \u2014 just record it silently. Be ACCURATE about
21
+ what you saved: only say something is saved/remembered AFTER you've actually called
22
+ \`record_memory\` for it; never claim a preference is "already" a saved convention, or
23
+ that it "will persist", unless you just recorded it (or confirmed it via
24
+ \`list_memories\`). A background pass also captures durable facts at session end as a
25
+ backstop \u2014 but never rely on it for an explicit request; record that now.`;function be(n){let e=Re,t=(n||"").trim();return t&&(e+=`
12
26
 
13
27
  ALWAYS \u2014 foundational rules (already loaded & active for this whole session; apply directly, never fetch):
14
- ${n}`),e}function k(t,e){return JSON.stringify({hookSpecificOutput:{hookEventName:t,additionalContext:D(e)}})}import{homedir as I}from"node:os";import{join as f}from"node:path";import{readFileSync as P,writeFileSync as re,mkdirSync as ie,chmodSync as ce,existsSync as ae}from"node:fs";var fe=(process.env.SUPERCLAWD_BACKEND||"real").toLowerCase();var pe=process.env.SUPERCLAWD_MCP_API_URL||"https://mcp-api.superclawd.com",_=process.env.SUPERCLAWD_HOME||f(I(),".superclawd"),W=f(_,"sessions"),L=f(_,"config.json");function T(t){if(!t||typeof t!="object")return{};let e=t,n=e.credentials??{...typeof e.keyId=="string"?{keyId:e.keyId}:{},...typeof e.secret=="string"?{secret:e.secret}:{},...typeof e.workspace=="string"?{workspace:e.workspace}:{}},o=e.preferences??{...typeof e.skipPermissions=="boolean"?{skipPermissions:e.skipPermissions}:{},...typeof e.notifications=="boolean"?{notifications:e.notifications}:{},...typeof e.chooseWorkspaceAtStartup=="boolean"?{chooseWorkspaceAtStartup:e.chooseWorkspaceAtStartup}:{}},s={};return Object.keys(n).length&&(s.credentials=n),Object.keys(o).length&&(s.preferences=o),s}function U(){try{return T(JSON.parse(P(L,"utf8")))}catch{return null}}function M(){return U()?.preferences?.notifications===!0}function j(t){return f(W,t)}function K(t){return f(t,"config.json")}function J(t){try{return JSON.parse(P(K(t),"utf8"))}catch{return null}}function d(t){let e=t?J(j(t)):null;return e&&typeof e.notifications=="boolean"?e.notifications:M()}var ue=1e3*60*60*24*3;var y=process.env.SUPERCLAWD_MCP_API_URL||"https://mcp-api.superclawd.com",S=(process.env.SUPERCLAWD_BACKEND||"real").toLowerCase(),p=process.env.MCP_KEY_ID||"",u=process.env.MCP_SECRET||"",l=process.env.MCP_WORKSPACE||"";function v(){return{"content-type":"application/json","x-mcp-key-id":p,"x-mcp-secret":u,"x-workspace-slug":l,"x-request-id":B()}}async function O(t,e){let n=new AbortController,o=setTimeout(()=>n.abort(),e);try{return await fetch(t,{headers:v(),signal:n.signal})}finally{clearTimeout(o)}}async function q(t,e="SessionStart"){let n="";if(t)try{n=m(t,"utf8")}catch{}if(S!=="mock"&&p&&u&&l)try{let o=await O(`${y}/api/prompt/foundational`,3e3);if(o.ok){let s=await o.json();typeof s.text=="string"&&(n=s.text)}}catch{}process.stdout.write(k(e,n))}async function G(){let t=()=>process.stdout.write(JSON.stringify({hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}})),e=()=>process.stdout.write(JSON.stringify({hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:"SuperClawd: out of credits. Top up at app.superclawd.com to load directives."}}));if(S==="mock"||!p||!u||!l)return void t();try{let n=await O(`${y}/api/prompt/balance`,2e3);if(!n.ok)return void t();let s=(await n.json()).content,r=(Array.isArray(s)?s.map(i=>i.text??"").join(""):"").match(/<current_balance>([\d.]+)<\/current_balance>/);return r&&Number(r[1])<=0?void e():void t()}catch{return void t()}}function g(){return new Promise(t=>{let e="";try{process.stdin.setEncoding("utf8"),process.stdin.on("data",n=>e+=n),process.stdin.on("end",()=>t(e)),process.stdin.on("error",()=>t(e)),setTimeout(()=>t(e),1500)}catch{t(e)}})}function H(t){if(!t||!F(t))return"";try{let e=m(t,"utf8").trim().split(`
15
- `).filter(Boolean);for(let n=e.length-1;n>=0;n--){let o=JSON.parse(e[n]),s=o.message??o;if((s.role??o.type)==="assistant"){let r=s.content,i=Array.isArray(r)?r.map(c=>c.text??"").join(" "):typeof r=="string"?r:"";if(i.trim())return i.trim().slice(0,300)}}}catch{}return""}function z(t,e,n){if(!(!d(e??"")||S==="mock"||!p||!u||!l))try{let o=process.argv[1];if(!o)return;let s=Buffer.from(n,"utf8").toString("base64");b(process.execPath,[o,"notify-bg",t,e??"",s],{detached:!0,stdio:"ignore"}).unref()}catch{}}async function V(t,e,n){if(!d(e??"")||S==="mock"||!p||!u||!l)return;let o={};try{o=JSON.parse(n)}catch{}let s=Y(process.cwd()),a=t==="attention",r=a?o.message||"Claude needs your input":H(o.transcript_path)||"Session finished",i=`[${s}] ${r}`.slice(0,500),c=e||process.env.SUPERCLAWD_SESSION_ID||"",N={type:a?"attention_needed":"completion",summary:i,sms_summary:i.slice(0,110),x_session_request_id:c},w=()=>x(`${y}/api/prompt/notify-checkpoint`,4e3,{method:"POST",headers:{...v(),"x-session-request-id":c},body:JSON.stringify(N)});try{let h=await w();h.status===404&&c&&(await x(`${y}/api/prompt/inspector`,4e3,{method:"POST",headers:{...v(),"x-session-request-id":c},body:JSON.stringify({ide:!0,platform:"claude-code",llm_model:"claude",x_session_request_id:c,notify_on_checkpoint:!0,enable_session_files:!1})}).catch(()=>{}),h=await w())}catch{}}async function x(t,e,n){let o=new AbortController,s=setTimeout(()=>o.abort(),e);try{return await fetch(t,{...n,signal:o.signal})}finally{clearTimeout(s)}}function E(t,e,n){try{b(t,e,{detached:!0,stdio:"ignore",env:n??process.env}).unref()}catch{}}function A(t,e,n){if(process.platform==="darwin"){let o=n?`display notification m with title ${C(t)} subtitle ${C(n)} sound name "Glass"`:`display notification m with title ${C(t)} sound name "Glass"`;E("osascript",["-e","on run {m}","-e",o,"-e","end run",e]);return}process.platform!=="win32"&&E("notify-send",[t,e])}function C(t){return`"${t.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`}function X(t,e,n){if(d(n??"")){if(t==="attention"){let o="";try{o=JSON.parse(e).message??""}catch{}if(o.includes("waiting for your input"))return;A("Claude Code",o||"Claude needs you","Needs you");return}A("Claude Code","Done \u2014 your turn.")}}function Q(t,e){let n=Number(process.env.SUPERCLAWD_REMIND_EVERY??8);if(!Number.isFinite(n)||n<=0||!t||!e)return;let o=0;try{o=parseInt(m(e,"utf8").trim(),10)||0}catch{}o+=1;try{$(e,String(o))}catch{}if(o%n!==0)return;let s="";try{s=m(t,"utf8")}catch{return}s&&process.stdout.write(JSON.stringify({hookSpecificOutput:{hookEventName:"PostToolUse",additionalContext:s}}))}async function Z(){let t=process.argv[2];if(t==="gate")return await g(),G();if(t==="notify"){let e=process.argv[3],n=process.argv[4],o=await g();z(e,n,o);return}if(t==="notify-bg"){let e=process.argv[3],n=process.argv[4]||void 0,o=Buffer.from(process.argv[5]||"","base64").toString("utf8");return V(e,n,o)}if(t==="notify-local"){let e=process.argv[3],n=process.argv[4]||void 0,o=await g();X(e,o,n);return}if(t==="remind"){Q(process.argv[3],process.argv[4]);return}return await g(),q(process.argv[3],process.argv[4]||"SessionStart")}var ee=new Set(["gate","notify","notify-bg","notify-local","remind"]);Z().catch(()=>{let t=process.argv[2];ee.has(t)||process.stdout.write(k(process.argv[4]||"SessionStart",""))});
28
+ ${t}`),e}function U(n,e){return JSON.stringify({hookSpecificOutput:{hookEventName:n,additionalContext:be(e)}})}var re="superclawd",Ae="core",ke=`mcp__plugin_${re}_${Ae}__`;var _t=`${ke}*`,oe=`${re}:`;import{homedir as Oe}from"node:os";import{join as k}from"node:path";import{readFileSync as se,writeFileSync as Mt,mkdirSync as Ut,chmodSync as $t,existsSync as Wt}from"node:fs";var Yt=(process.env.SUPERCLAWD_BACKEND||"real").toLowerCase();var Jt=process.env.SUPERCLAWD_MCP_API_URL||"https://mcp-api.superclawd.com",jt=process.env.SUPERCLAWD_API_URL||"https://api.superclawd.com",ie=process.env.SUPERCLAWD_HOME||k(Oe(),".superclawd"),Pe=k(ie,"sessions"),Ce=k(ie,"config.json");function Ne(n){if(!n||typeof n!="object")return{};let e=n,t=e.credentials??{...typeof e.keyId=="string"?{keyId:e.keyId}:{},...typeof e.secret=="string"?{secret:e.secret}:{},...typeof e.workspace=="string"?{workspace:e.workspace}:{}},r=e.preferences??{...typeof e.skipPermissions=="boolean"?{skipPermissions:e.skipPermissions}:{},...typeof e.notifications=="boolean"?{notifications:e.notifications}:{},...typeof e.chooseWorkspaceAtStartup=="boolean"?{chooseWorkspaceAtStartup:e.chooseWorkspaceAtStartup}:{},...typeof e.experimental=="boolean"?{experimental:e.experimental}:{}},o={};return Object.keys(t).length&&(o.credentials=t),Object.keys(r).length&&(o.preferences=r),typeof e.machineId=="string"&&(o.machineId=e.machineId),o}function $(){try{return Ne(JSON.parse(se(Ce,"utf8")))}catch{return null}}function Te(){return $()?.preferences?.notifications===!0}function P(n){return k(Pe,n)}function _e(n){return k(n,"config.json")}function W(n){try{return JSON.parse(se(_e(n),"utf8"))}catch{return null}}function C(n){let e=n?W(P(n)):null;return e&&typeof e.notifications=="boolean"?e.notifications:Te()}var Ft=1e3*60*60*24*3;import{existsSync as Y}from"node:fs";import{homedir as Ie}from"node:os";import{spawn as Le,execSync as xe}from"node:child_process";var N="sonnet",De=2e4;function O(){let n=process.env.SUPERCLAWD_CLAUDE_BIN;if(n&&Y(n))return n;try{let t=process.platform==="win32"?"where claude":"command -v claude",r=xe(t,{encoding:"utf8"}).trim().split(`
29
+ `)[0];if(r&&Y(r))return r}catch{}let e=[`${Ie()}/.local/bin/claude`,"/opt/homebrew/bin/claude","/usr/local/bin/claude","/usr/bin/claude"];for(let t of e)if(Y(t))return t;return null}function ae(n){let e=n.indexOf("{"),t=n.lastIndexOf("}");return e>=0&&t>e?n.slice(e,t+1):n}function Me(n){try{let e=n;try{let r=JSON.parse(n);typeof r.result=="string"&&(e=r.result)}catch{}let t=JSON.parse(ae(e));return typeof t.verdict!="string"||!t.verdict?null:{verdict:t.verdict,reason:typeof t.reason=="string"?t.reason:"",confidence:typeof t.confidence=="number"?t.confidence:1}}catch{return null}}function ce(n){let{system:e,user:t}=n,r=n.model||N,o=n.timeoutMs??De,i=O();return i?new Promise(s=>{let a="",c=!1,u=f=>{c||(c=!0,s(f))},l;try{l=Le(i,["-p","--model",r,"--output-format","json","--strict-mcp-config","--setting-sources","user","--tools","","--append-system-prompt",e],{stdio:["pipe","pipe","ignore"],env:{...process.env,SUPERCLAWD_POLICY_JUDGE:"1"}})}catch{return u(null)}let p=setTimeout(()=>{try{l.kill("SIGKILL")}catch{}u(null)},o);l.stdout?.on("data",f=>a+=f),l.on("error",()=>{clearTimeout(p),u(null)}),l.on("close",()=>{if(clearTimeout(p),n.onRaw)try{n.onRaw(a)}catch{}u(a)});try{l.stdin?.write(t),l.stdin?.end()}catch{}}):Promise.resolve(null)}function J(n){return ce(n).then(e=>e?Me(e):null)}function j(n){return ce(n).then(e=>{if(!e)return null;try{let t=e;try{let r=JSON.parse(e);typeof r.result=="string"&&(t=r.result)}catch{}return JSON.parse(ae(t))}catch{return null}})}var m=process.env.SUPERCLAWD_MCP_API_URL||"https://mcp-api.superclawd.com",h=(process.env.SUPERCLAWD_BACKEND||"real").toLowerCase(),S=process.env.SUPERCLAWD_MCP_KEY||"",w=process.env.SUPERCLAWD_MCP_SECRET||"",R=process.env.SUPERCLAWD_MCP_WORKSPACE||"";function _(){let n={"content-type":"application/json","x-mcp-key-id":S,"x-mcp-secret":w,"x-workspace-slug":R,"x-request-id":ge()};return process.env.SUPERCLAWD_EXPERIMENTAL==="true"&&(n["x-experimental"]="true"),process.env.SUPERCLAWD_PRIVATE_MEMORY==="0"&&(n["x-private-memory"]="false"),n}async function M(n,e){let t=new AbortController,r=setTimeout(()=>t.abort(),e);try{return await fetch(n,{headers:_(),signal:t.signal})}finally{clearTimeout(r)}}async function Fe(n,e="SessionStart"){let t="";if(n)try{t=y(n,"utf8")}catch{}if(h!=="mock"&&S&&w&&R)try{let r=process.env.SUPERCLAWD_REPO_FINGERPRINT,o=`${m}/api/prompt/foundational`+(r?`?repoFingerprint=${encodeURIComponent(r)}`:""),i=await M(o,3e3);if(i.ok){let s=await i.json();typeof s.text=="string"&&(t=s.text)}}catch{}process.stdout.write(U(e,t))}async function Ge(){let n=()=>process.stdout.write(JSON.stringify({hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}})),e=()=>process.stdout.write(JSON.stringify({hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:"SuperClawd: out of credits. Top up at app.superclawd.com to load directives."}}));if(h==="mock"||!S||!w||!R)return void n();try{let t=await M(`${m}/api/prompt/balance`,2e3);if(!t.ok)return void n();let o=(await t.json()).content,s=(Array.isArray(o)?o.map(a=>a.text??"").join(""):"").match(/<current_balance>([\d.]+)<\/current_balance>/);return s&&Number(s[1])<=0?void e():void n()}catch{return void n()}}var Ke=process.env.SUPERCLAWD_POLICY_MODEL||N,Ve=Number(process.env.SUPERCLAWD_POLICY_TIMEOUT_MS||6e4),le=6e4,He=4,Be=["You are a code-policy judge. Decide whether a staged git diff VIOLATES a single team rule.","Reason briefly about control flow, indirection, and scope \u2014 judge whether the rule is actually","broken, not whether the diff merely touches a related area. If the rule does not apply to this",'diff, the verdict is "ok".','Respond with ONLY strict JSON: {"verdict":"violation"|"ok","reason":"<one line>","confidence":<0..1>}.',"Output nothing else."].join(" ");function qe(n,e){let t=(e.evaluation.examples??[]).map((r,o)=>`Example ${o+1} (verdict: ${r.verdict}):
30
+ ${r.diff}`).join(`
31
+
32
+ `);return[`RULE: ${e.rule}`,`CRITERIA: ${e.evaluation.criteria}`,t?`
33
+ LABELED EXAMPLES:
34
+ ${t}
35
+ `:"","STAGED DIFF:",n].join(`
36
+ `)}async function Xe(n,e){let t=await J({system:Be,user:qe(n,e),model:Ke,timeoutMs:Ve});return!t||t.verdict!=="violation"&&t.verdict!=="ok"?null:{verdict:t.verdict,reason:t.reason,confidence:t.confidence}}async function ze(n,e){let t=Math.max(1,Math.min(5,e.evaluation.voteN??1)),r=(await Promise.all(Array.from({length:t},()=>Xe(n,e)))).filter(a=>a!==null);if(r.length===0)return null;let o=r.filter(a=>a.verdict==="violation");if(o.length<=r.length/2)return null;let i=o.reduce((a,c)=>a+c.confidence,0)/o.length,s=e.action;return s==="deny"&&i<.66&&(s="ask"),{name:e.name,action:s,reason:o[0].reason}}var I=60,Ze=new Set([".git","node_modules","dist","build",".next","coverage",".turbo","vendor"]);function me(n,e){if(e.includes("\0"))return"";let t=e.split(`
37
+ `).map(r=>`+${r}`).join(`
38
+ `);return`diff --git a/${n} b/${n}
39
+ new file
40
+ --- /dev/null
41
+ +++ b/${n}
42
+ ${t}`}function Qe(n){let e=n.match(/(?:^|&&|;)\s*cd\s+(?:"([^"]+)"|'([^']+)'|(\S+))/),t=e?e[1]||e[2]||e[3]:"";if(!t)return process.cwd();let r=t.startsWith("/")?t:`${process.cwd()}/${t}`;try{return L(r)?r:process.cwd()}catch{return process.cwd()}}function et(n){let e=[],t=(r,o)=>{if(e.length>=I)return;let i;try{i=$e(r)}catch{return}for(let s of i){if(e.length>=I)return;if(s.startsWith("."))continue;let a=`${r}/${s}`,c=o?`${o}/${s}`:s,u=!1;try{u=X(a).isDirectory()}catch{continue}u?Ze.has(s)||t(a,c):e.push(c)}};return t(n,""),e}function tt(n,e){let t=n.match(/git\s+add\s+([^&;|]+)/),r=[],o=!1;if(t)for(let a of t[1].trim().split(/\s+/))a==="-A"||a==="."||a==="--all"||a==="-a"?o=!0:a.startsWith("-")||r.push(a.replace(/^["']|["']$/g,""));else o=!0;let i=o||r.length===0?et(e):r,s=[];for(let a of i.slice(0,I))try{let c=me(a,y(`${e}/${a}`,"utf8"));c&&s.push(c)}catch{}return s.join(`
43
+ `)}function nt(n){let e=Qe(n),t=o=>{try{return D(o,{cwd:e,encoding:"utf8",maxBuffer:10*1024*1024})}catch{return""}};if(t("git rev-parse --is-inside-work-tree").trim()==="true"){let o=t("git diff --cached");if(o.trim())return o;let i=[],s=t("git diff");s.trim()&&i.push(s);let a=t("git ls-files --others --exclude-standard").split(`
44
+ `).map(c=>c.trim()).filter(Boolean).slice(0,I);for(let c of a)try{let u=me(c,y(`${e}/${c}`,"utf8"));u&&i.push(u)}catch{}return i.join("").trim()?i.join(`
45
+ `):""}return tt(n,e)}async function rt(n,e){let t=()=>process.stdout.write(JSON.stringify({hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}}));if(process.env.SUPERCLAWD_POLICY_JUDGE==="1")return void t();let r="",o="";try{let c=JSON.parse(e);o=c.tool_name??"",r=c.tool_input?.command??""}catch{return void t()}if(!(o==="Bash"&&/\bgit\s+commit\b/.test(r)))return void t();let s=[];try{if(n){let c=JSON.parse(y(n,"utf8"));Array.isArray(c)&&(s=c)}}catch{return void t()}if(s.length===0||!O())return void t();let a=nt(r);if(!a.trim())return void t();a.length>le&&(a=a.slice(0,le));try{let c=(await he(s,He,v=>ze(a,v))).filter(v=>v!==null);if(c.length===0)return void t();let u={deny:3,ask:2,warn:1},l=c.reduce((v,g)=>u[g.action]>u[v.action]?g:v),p=`SuperClawd policy "${l.name}": ${l.reason||l.action}`,f=l.action==="deny"?"deny":l.action==="ask"?"ask":"allow",b=f!=="allow";process.stdout.write(JSON.stringify({hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:f,...b?{permissionDecisionReason:p}:{},...f==="allow"?{additionalContext:p}:{}}}))}catch{return void t()}}var ue=6e4,ot=4;async function he(n,e,t){let r=new Array(n.length).fill(null),o=0,i=Array.from({length:Math.max(1,Math.min(e,n.length))},async()=>{for(;;){let s=o++;if(s>=n.length)return;try{r[s]=await t(n[s],s)}catch{r[s]=null}}});return await Promise.all(i),r}async function st(){let n=process.env.SUPERCLAWD_REPO_FINGERPRINT||"";if(h==="mock"||!S||!w||!R||!n)return;let e=c=>{try{return D(c,{cwd:process.cwd(),encoding:"utf8",maxBuffer:10*1024*1024,stdio:["ignore","pipe","ignore"]})}catch{return""}},t=e("git rev-parse HEAD").trim();if(!t)return;let r=e("git show --format= -p HEAD");if(!r.trim())return;r.length>ue&&(r=r.slice(0,ue));let o=[];try{let c=`${m}/api/prompt/memories?scope=repo&scopeKey=${encodeURIComponent(n)}`,u=await M(c,4e3);if(!u.ok)return;o=(await u.json().catch(()=>({}))).memories??[]}catch{return}if(o.length===0)return;let i=await he(o,ot,async c=>{let u=c.body??c.title??"";if(!u.trim())return null;let l=await J({system:ne,user:`LESSON: ${u}
46
+
47
+ COMMIT DIFF:
48
+ ${r}`});return l?{id:c.id,verdict:l.verdict,reason:l.reason}:null}),s=[],a={};for(let c of i)c&&c.verdict==="stale"&&(s.push(c.id),c.reason&&(a[c.id]=c.reason));try{await A(`${m}/api/prompt/commit-event`,4e3,{method:"POST",headers:_(),body:JSON.stringify({hash:t,repoFingerprint:n,staleIds:s,reasons:a})})}catch{}}var it=new Set(["Edit","Write","MultiEdit","NotebookEdit"]);function at(n){let e="";for(let t=0;t<n.length;t++){let r=n[t];r==="*"?n[t+1]==="*"?(e+=".*",t++,n[t+1]==="/"&&t++):e+="[^/]*":".+^${}()|[]\\".includes(r)?e+="\\"+r:r==="?"?e+=".":e+=r}return new RegExp("^"+e+"$")}function F(n,e){try{return n().test(e)}catch{return!1}}function ct(n,e,t){let r={deny:3,ask:2,warn:1,allow:0},o={decision:"allow",message:null};for(let i of n){if(!i||!i.match||!Array.isArray(i.match.tools)||!(i.match.tools.includes("*")||i.match.tools.includes(e)))continue;let s=!1;if(i.match.pathGlobs&&it.has(e)){let a=t.file_path??t.path??"";s=i.match.pathGlobs.some(c=>F(()=>at(c),a))}if(!s&&i.match.commandPatterns&&e==="Bash"){let a=t.command??"";s=i.match.commandPatterns.some(c=>F(()=>new RegExp(c),a))}if(!s&&i.match.contentPatterns){let a=`${t.content??""}
49
+ ${t.new_string??""}`;s=i.match.contentPatterns.some(c=>F(()=>new RegExp(c),a))}s&&r[i.action]>r[o.decision]&&(o.decision=i.action,o.message=i.message)}return o}function lt(n){let{decision:e,message:t}=n;return{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:e==="deny"?"deny":e==="ask"?"ask":"allow",...!!t&&e!=="allow"?{permissionDecisionReason:t}:{}}}}function ut(n,e){let t=[];try{if(n){let s=JSON.parse(y(n,"utf8"));Array.isArray(s)&&(t=s)}}catch{t=[]}let r="",o={};try{let s=JSON.parse(e);r=s.tool_name??"",o=s.tool_input??{}}catch{}let i=ct(t,r,o);process.stdout.write(JSON.stringify(lt(i)))}function E(){return new Promise(n=>{let e="";try{process.stdin.setEncoding("utf8"),process.stdin.on("data",t=>e+=t),process.stdin.on("end",()=>n(e)),process.stdin.on("error",()=>n(e)),setTimeout(()=>n(e),1500)}catch{n(e)}})}function dt(n){if(!n||!L(n))return"";try{let e=y(n,"utf8").trim().split(`
50
+ `).filter(Boolean);for(let t=e.length-1;t>=0;t--){let r=JSON.parse(e[t]),o=r.message??r;if((o.role??r.type)==="assistant"){let s=o.content,a=Array.isArray(s)?s.map(c=>c.text??"").join(" "):typeof s=="string"?s:"";if(a.trim())return a.trim().slice(0,300)}}}catch{}return""}function pt(n,e,t){if(!(!C(e??"")||h==="mock"||!S||!w||!R))try{let r=process.argv[1];if(!r)return;let o=Buffer.from(t,"utf8").toString("base64");x(process.execPath,[r,"notify-bg",n,e??"",o],{detached:!0,stdio:"ignore"}).unref()}catch{}}async function ft(n,e,t){if(!C(e??"")||h==="mock"||!S||!w||!R)return;let r={};try{r=JSON.parse(t)}catch{}let o=Ye(process.cwd()),i=n==="attention",s=i?r.message||"Claude needs your input":dt(r.transcript_path)||"Session finished",a=`[${o}] ${s}`.slice(0,500),c=e||process.env.SUPERCLAWD_SESSION_ID||"",u={type:i?"attention_needed":"completion",summary:a,x_session_request_id:c},l=()=>A(`${m}/api/prompt/notify-checkpoint`,4e3,{method:"POST",headers:{..._(),"x-session-request-id":c},body:JSON.stringify(u)});try{let p=await l();p.status===404&&c&&(await A(`${m}/api/prompt/inspector`,4e3,{method:"POST",headers:{..._(),"x-session-request-id":c},body:JSON.stringify({ide:!0,platform:"claude-code",llm_model:"claude",x_session_request_id:c,notify_on_checkpoint:!0,enable_session_files:!1})}).catch(()=>{}),p=await l())}catch{}}async function A(n,e,t){let r=new AbortController,o=setTimeout(()=>r.abort(),e);try{return await fetch(n,{...t,signal:r.signal})}finally{clearTimeout(o)}}function de(n,e,t){try{x(n,e,{detached:!0,stdio:"ignore",env:t??process.env}).unref()}catch{}}function pe(n,e,t){if(process.platform==="darwin"){let r=t?`display notification m with title ${G(n)} subtitle ${G(t)} sound name "Glass"`:`display notification m with title ${G(n)} sound name "Glass"`;de("osascript",["-e","on run {m}","-e",r,"-e","end run",e]);return}process.platform!=="win32"&&de("notify-send",[n,e])}function G(n){return`"${n.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`}function gt(n,e,t){if(C(t??"")){if(n==="attention"){let r="";try{r=JSON.parse(e).message??""}catch{}if(r.includes("waiting for your input"))return;pe("Claude Code",r||"Claude needs you","Needs you");return}pe("Claude Code","Done \u2014 your turn.")}}function mt(n,e){let t=Number(process.env.SUPERCLAWD_REMIND_EVERY??8);if(!Number.isFinite(t)||t<=0||!n||!e)return;let r=0;try{r=parseInt(y(e,"utf8").trim(),10)||0}catch{}r+=1;try{K(e,String(r))}catch{}if(r%t!==0)return;let o="";try{o=y(n,"utf8")}catch{return}o&&process.stdout.write(JSON.stringify({hookSpecificOutput:{hookEventName:"PostToolUse",additionalContext:o}}))}var ht=5;async function yt(n,e){if(h==="mock"||!S||!w||!R)return;let t="",r=n==="prompt"?"UserPromptSubmit":"PreToolUse";try{let o=JSON.parse(e||"{}");if(n==="prompt")t=String(o.prompt??"");else{let i=o.tool_input??{};t=String(i.file_path??i.path??"")}}catch{return}if(t=t.trim(),!(t.length<4))try{let o=new URLSearchParams({query:t.slice(0,500)}),i=process.env.SUPERCLAWD_REPO_FINGERPRINT;i&&o.set("repoFingerprint",i);let s=await M(`${m}/api/prompt/memories/search?${o.toString()}`,n==="prompt"?2500:1500);if(!s.ok)return;let c=((await s.json()).memories??[]).slice(0,ht);if(c.length===0)return;let u=c.map(p=>` [${p.scope}] ${p.id} ${(p.title??"").trim()}`).join(`
51
+ `),l=n==="prompt"?"RELEVANT PROJECT MEMORIES for this request (titles only \u2014 fetch the full text with get_memories([id]) before relying on one):":"PROJECT MEMORIES that may relate to this file (titles only \u2014 fetch with get_memories([id]) if relevant):";process.stdout.write(JSON.stringify({hookSpecificOutput:{hookEventName:r,additionalContext:`${l}
52
+ ${u}`}}))}catch{}}var Et=3e4,ye=process.env.SUPERCLAWD_CAPTURE_MODEL||N;function d(n,e){if(process.env.SUPERCLAWD_DEBUG==="1")try{let t=D("date -u +%Y-%m-%dT%H:%M:%SZ",{encoding:"utf8"}).trim();Ue(`${Je()}/.superclawd/capture-debug.log`,JSON.stringify({ts:t,stage:n,...e})+`
53
+ `)}catch{}}function V(n,e=Et){if(!n||!L(n))return"";let t;try{t=y(n,"utf8").trim().split(`
54
+ `).filter(Boolean)}catch{return""}let r=[];for(let i of t){let s;try{s=JSON.parse(i)}catch{continue}let a=s.message??s,c=a.role??s.type;if(c!=="user"&&c!=="assistant")continue;let u=a.content;if(typeof u=="string"){u.trim()&&r.push(`${c.toUpperCase()}: ${u.trim()}`);continue}if(Array.isArray(u)){for(let l of u)if(l?.type==="text"&&typeof l.text=="string"&&l.text.trim())r.push(`${c.toUpperCase()}: ${l.text.trim()}`);else if(l?.type==="tool_use"){let p=JSON.stringify(l.input??{}).slice(0,200);r.push(`[tool ${l.name}: ${p}]`)}else if(l?.type==="tool_result"){let p=l.content,f=typeof p=="string"?p:Array.isArray(p)?p.map(b=>b?.text??"").join(" "):"";f.trim()&&r.push(`[result: ${f.trim().slice(0,200)}]`)}}}let o=r.join(`
55
+ `);return o.length>e&&(o=`\u2026
56
+ `+o.slice(o.length-e)),o}function z(n){let e=$()?.credentials??{},t=n?W(P(n)):null;return{keyId:process.env.SUPERCLAWD_MCP_KEY||e.keyId||"",secret:process.env.SUPERCLAWD_MCP_SECRET||e.secret||"",workspace:process.env.SUPERCLAWD_MCP_WORKSPACE||t?.workspace||e.workspace||""}}function H(n){return{"content-type":"application/json","x-mcp-key-id":n.keyId,"x-mcp-secret":n.secret,"x-workspace-slug":n.workspace,"x-request-id":ge()}}async function B(n,e,t){try{let r=n==="private"?`${m}/api/prompt/memories?scope=private`:`${m}/api/prompt/memories?scope=${n}&scopeKey=${encodeURIComponent(e)}`,o=await A(r,4e3,{headers:H(t)});return o.ok?((await o.json().catch(()=>({}))).memories??[]).filter(s=>s.id).map(s=>({id:String(s.id),body:(s.body??s.title??"").trim(),locked:s.lockedAt!=null})):[]}catch{return[]}}function T(n,e){return n.length?n.map(t=>`[${t.id}]${t.locked?" [LOCKED]":""} ${t.body}`).join(`
57
+ `):e}async function Ee(n,e,t,r){for(let o of n){let i=t(o.scope);if(!i){d(`${r}-skip-unrouted`,{scope:o.scope??null});continue}let s=(o.body||"").trim();if(o.op==="create"){if(s.length<12)continue;try{let a={scope:i.scope,content:s,learnedAgainst:i.learnedAgainst};i.scopeKey!=null&&(a.scopeKey=i.scopeKey),o.title&&o.title.trim()&&(a.title=o.title.trim());let c=await A(`${m}/api/prompt/memories`,8e3,{method:"POST",headers:H(e),body:JSON.stringify(a)});d(`${r}-create`,{scope:i.scope,status:c.status,ok:c.ok})}catch(a){d(`${r}-create-error`,{error:String(a)})}}else if(o.op==="update"&&o.id){if(!i.allowUpdate){d(`${r}-skip-update`,{scope:i.scope,id:o.id});continue}if(s.length<12)continue;try{let a=await A(`${m}/api/prompt/memories/${encodeURIComponent(o.id)}`,8e3,{method:"PUT",headers:H(e),body:JSON.stringify({content:s,learnedAgainst:i.learnedAgainst,...o.title&&o.title.trim()?{title:o.title.trim()}:{}})});d(`${r}-update`,{id:o.id,status:a.status,ok:a.ok})}catch(a){d(`${r}-update-error`,{error:String(a)})}}}}var vt=18e4;function St(n){if(!n)return null;let e;try{e=P(n)}catch{return null}let t=`${e}/capture.lock`;try{return K(t,String(process.pid),{flag:"wx"}),t}catch{try{return Date.now()-X(t).mtimeMs<vt?null:(K(t,String(process.pid)),t)}catch{return null}}}function wt(n){if(n)try{We(n)}catch{}}function Rt(n,e){let t=process.env.SUPERCLAWD_REPO_FINGERPRINT||"";if(process.env.SUPERCLAWD_POLICY_JUDGE==="1")return;let r=z(e);if(h==="mock"||!r.keyId||!r.secret||!r.workspace||!t){d("detached-skip",{backend:h,hasKey:!!r.keyId,hasSecret:!!r.secret,hasWorkspace:!!r.workspace,hasFp:!!t,launchId:e});return}try{let o=process.argv[1];if(!o)return;let i=Buffer.from(n,"utf8").toString("base64"),s=x(process.execPath,[o,"capture-bg",i,e],{detached:!0,stdio:"ignore"});s.unref(),d("detached-spawn",{pid:s.pid??null,launchId:e})}catch(o){d("detached-error",{error:String(o)})}}async function bt(n,e){let t=process.env.SUPERCLAWD_REPO_FINGERPRINT||"",r=z(e);if(d("bg-start",{hasFp:!!t,hasKey:!!r.keyId,hasWorkspace:!!r.workspace}),h==="mock"||!r.keyId||!r.secret||!r.workspace||!t)return;if(!O()){d("bg-no-claude");return}let o={};try{o=JSON.parse(n)}catch{d("bg-bad-payload");return}let i=V(o.transcript_path);if(!i){d("bg-no-digest",{transcript:o.transcript_path??null});return}let s=(i.match(/\n?\[tool /g)||[]).length,a=Number(process.env.SUPERCLAWD_CAPTURE_MIN_TOOLS??3),c=process.env.SUPERCLAWD_PRIVATE_MEMORY==="1",u=Number(process.env.SUPERCLAWD_PRIVATE_MIN_DIGEST??280),l=Number.isFinite(a)&&a>0&&s<a,p=c&&i.length>=u;if(d("bg-digest",{digestLen:i.length,toolUses:s,minTools:a,privateOn:c}),l&&!p)return;let f=St(e);if(!f){d("bg-locked");return}let b=g=>{try{return g&&L(g)?X(g).mtimeMs:0}catch{return 0}},v=b(o.transcript_path);try{if(await fe(t,r,i,c),b(o.transcript_path)>v){let g=V(o.transcript_path),ve=(g.match(/\n?\[tool /g)||[]).length,Se=Number.isFinite(a)&&a>0&&ve<a,we=c&&g.length>=u,Z=!!g&&!(Se&&!we);d("bg-rerun",{digestLen:g.length,willRun:Z}),Z&&await fe(t,r,g,c)}}finally{wt(f)}}async function fe(n,e,t,r){let o=process.env.SUPERCLAWD_REPO_MEMORY!=="0",i=[];try{let l=D("git rev-parse HEAD",{cwd:process.cwd(),encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();l&&(i=[l])}catch{}let s=await B("repo",n,e),a=r?await B("private","",e):[];d("bg-existing",{repo:s.length,private:a.length});let c=await j({system:r?ee:Q,model:ye,user:r?`ALREADY-SAVED REPO MEMORIES (reconcile against these; ids in brackets):
58
+ ${T(s,"NONE \u2014 this repo has no saved memories yet; future sessions start with zero knowledge of it.")}
59
+
60
+ ALREADY-SAVED PRIVATE MEMORIES for this user (create only genuinely new ones; never update):
61
+ ${T(a,"NONE \u2014 this user has no saved private preferences yet.")}
62
+
63
+ FINISHED SESSION (condensed transcript; most recent at the end) \u2014 emit scope-tagged ops to keep both sets accurate & minimal:
64
+ ${t}`:`ALREADY-SAVED MEMORIES FOR THIS REPO (reconcile against these; ids in brackets):
65
+ ${T(s,"NONE \u2014 this repo has no saved memories yet; future sessions start with zero knowledge of it.")}
66
+
67
+ FINISHED SESSION (condensed transcript; most recent at the end) \u2014 emit ops to keep the repo's memory accurate & minimal:
68
+ ${t}`,timeoutMs:6e4,onRaw:process.env.SUPERCLAWD_DEBUG==="1"?l=>d("bg-judge-raw",{raw:l.slice(0,2e3)}):void 0}),u=Array.isArray(c?.ops)?c.ops:[];d("bg-ops",{ops:u.map(l=>`${l.scope??"repo"}:${l.op}`)}),await Ee(u,e,l=>r&&l==="private"?{scope:"private",scopeKey:null,learnedAgainst:[],allowUpdate:!1}:o?{scope:"repo",scopeKey:n,learnedAgainst:i,allowUpdate:!0}:null,"bg")}var q=oe;function At(n,e,t){if(process.env.SUPERCLAWD_POLICY_JUDGE==="1"||h==="mock")return;let r="";try{r=JSON.parse(n).agent_type??""}catch{return}if(d("agent-detached",{agentType:r}),!!r.startsWith(q))try{let o=process.argv[1];if(!o)return;let i=Buffer.from(n,"utf8").toString("base64"),s=x(process.execPath,[o,"capture-agent-bg",i,e,t],{detached:!0,stdio:"ignore"});s.unref(),d("agent-detached-spawn",{pid:s.pid??null})}catch(o){d("agent-detached-error",{error:String(o)})}}async function kt(n,e,t){let r;try{r=JSON.parse(n)}catch{return}let o=r.agent_type??"";if(!o.startsWith(q))return;let i=o.slice(q.length),s="";try{let f=JSON.parse(y(e,"utf8"));typeof f[i]=="string"&&(s=f[i])}catch{}if(d("agent-bg-start",{slug:i,hasAgentId:!!s}),!s)return;let a=z(t);if(h==="mock"||!a.keyId||!a.secret||!a.workspace)return;if(!O()){d("agent-bg-no-claude");return}let c=V(r.agent_transcript_path||r.transcript_path);if(d("agent-bg-digest",{digestLen:c.length}),c.length<200)return;let u=await B("agent",s,a);d("agent-bg-existing",{count:u.length});let l=await j({system:te,model:ye,user:`ALREADY-SAVED LESSONS FOR THIS AGENT (reconcile against these; ids in brackets):
69
+ ${T(u,"NONE \u2014 this agent has no saved lessons yet; it starts each run with only its base prompt.")}
70
+
71
+ FINISHED AGENT RUN (condensed transcript; most recent at the end) \u2014 emit ops to keep the agent's lessons accurate & minimal:
72
+ ${c}`,timeoutMs:6e4,onRaw:process.env.SUPERCLAWD_DEBUG==="1"?f=>d("agent-bg-judge-raw",{raw:f.slice(0,2e3)}):void 0}),p=Array.isArray(l?.ops)?l.ops:[];d("agent-bg-ops",{ops:p.map(f=>f.op)}),await Ee(p,a,()=>({scope:"agent",scopeKey:s,learnedAgainst:[],allowUpdate:!0}),"agent-bg")}async function Ot(){let n=process.argv[2];if(n==="gate")return await E(),Ge();if(n==="guardrails"){let e=process.argv[3],t=await E();return ut(e,t)}if(n==="policy"){let e=process.argv[3],t=await E();return rt(e,t)}if(n==="report-commit")return st();if(n==="notify"){let e=process.argv[3],t=process.argv[4],r=await E();pt(e,t,r);return}if(n==="notify-bg"){let e=process.argv[3],t=process.argv[4]||void 0,r=Buffer.from(process.argv[5]||"","base64").toString("utf8");return ft(e,t,r)}if(n==="notify-local"){let e=process.argv[3],t=process.argv[4]||void 0,r=await E();gt(e,r,t);return}if(n==="retrieve"){let e=process.argv[3]==="file"?"file":"prompt",t=await E();return yt(e,t)}if(n==="remind"){mt(process.argv[3],process.argv[4]);return}if(n==="capture-agent"){let e=process.argv[3]||"",t=process.argv[4]||"",r=await E();At(r,e,t);return}if(n==="capture-agent-bg"){let e=Buffer.from(process.argv[3]||"","base64").toString("utf8"),t=process.argv[4]||"",r=process.argv[5]||"";await kt(e,t,r);return}if(n==="capture"){let e=process.argv[3]||"",t=await E();Rt(t,e);return}if(n==="capture-bg"){let e=Buffer.from(process.argv[3]||"","base64").toString("utf8"),t=process.argv[4]||"";await bt(e,t);return}return await E(),Fe(process.argv[3],process.argv[4]||"SessionStart")}var Pt=new Set(["gate","guardrails","policy","report-commit","notify","notify-bg","notify-local","remind","retrieve","capture","capture-bg","capture-agent","capture-agent-bg"]),Ct=!!process.argv[1]&&import.meta.url===je(process.argv[1]).href;Ct&&Ot().catch(()=>{let n=process.argv[2];Pt.has(n)||process.stdout.write(U(process.argv[4]||"SessionStart",""))});export{ct as evaluate,lt as guardrailDecision,yt as retrieve};