@ekkos/cli 1.3.1 → 1.3.5
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/dist/capture/jsonl-rewriter.d.ts +1 -1
- package/dist/capture/jsonl-rewriter.js +3 -3
- package/dist/capture/transcript-repair.d.ts +2 -2
- package/dist/capture/transcript-repair.js +2 -2
- package/dist/commands/claw.d.ts +13 -0
- package/dist/commands/claw.js +253 -0
- package/dist/commands/dashboard.js +742 -118
- package/dist/commands/doctor.d.ts +3 -3
- package/dist/commands/doctor.js +6 -79
- package/dist/commands/gemini.d.ts +19 -0
- package/dist/commands/gemini.js +193 -0
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.js +56 -41
- package/dist/commands/run.d.ts +0 -1
- package/dist/commands/run.js +288 -263
- package/dist/commands/scan.d.ts +21 -0
- package/dist/commands/scan.js +386 -0
- package/dist/commands/status.d.ts +4 -1
- package/dist/commands/status.js +165 -27
- package/dist/commands/swarm-dashboard.js +156 -28
- package/dist/commands/swarm.d.ts +1 -1
- package/dist/commands/swarm.js +1 -1
- package/dist/commands/test-claude.d.ts +2 -2
- package/dist/commands/test-claude.js +3 -3
- package/dist/deploy/index.d.ts +0 -2
- package/dist/deploy/index.js +0 -2
- package/dist/deploy/settings.d.ts +6 -5
- package/dist/deploy/settings.js +64 -16
- package/dist/deploy/skills.js +1 -2
- package/dist/index.js +86 -96
- package/dist/lib/usage-parser.d.ts +1 -1
- package/dist/lib/usage-parser.js +9 -6
- package/dist/local/index.d.ts +14 -0
- package/dist/local/index.js +28 -0
- package/dist/local/local-embeddings.d.ts +49 -0
- package/dist/local/local-embeddings.js +232 -0
- package/dist/local/offline-fallback.d.ts +44 -0
- package/dist/local/offline-fallback.js +159 -0
- package/dist/local/sqlite-store.d.ts +126 -0
- package/dist/local/sqlite-store.js +393 -0
- package/dist/local/sync-engine.d.ts +42 -0
- package/dist/local/sync-engine.js +223 -0
- package/dist/utils/platform.d.ts +5 -1
- package/dist/utils/platform.js +24 -4
- package/dist/utils/proxy-url.d.ts +21 -0
- package/dist/utils/proxy-url.js +34 -0
- package/dist/utils/state.d.ts +1 -1
- package/dist/utils/state.js +11 -3
- package/dist/utils/templates.js +1 -1
- package/package.json +11 -4
- package/templates/CLAUDE.md +49 -107
- package/dist/agent/daemon.d.ts +0 -130
- package/dist/agent/daemon.js +0 -606
- package/dist/agent/health-check.d.ts +0 -35
- package/dist/agent/health-check.js +0 -243
- package/dist/agent/pty-runner.d.ts +0 -53
- package/dist/agent/pty-runner.js +0 -190
- package/dist/commands/agent.d.ts +0 -50
- package/dist/commands/agent.js +0 -544
- package/dist/commands/setup-remote.d.ts +0 -20
- package/dist/commands/setup-remote.js +0 -582
- package/dist/utils/verify-remote-terminal.d.ts +0 -10
- package/dist/utils/verify-remote-terminal.js +0 -415
- package/templates/README.md +0 -378
- package/templates/claude-plugins/PHASE2_COMPLETION.md +0 -346
- package/templates/claude-plugins/PLUGIN_PROPOSALS.md +0 -1776
- package/templates/claude-plugins/README.md +0 -587
- package/templates/claude-plugins/agents/code-reviewer.json +0 -14
- package/templates/claude-plugins/agents/debug-detective.json +0 -15
- package/templates/claude-plugins/agents/git-companion.json +0 -14
- package/templates/claude-plugins/blog-manager/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins/blog-manager/commands/blog.md +0 -691
- package/templates/claude-plugins/golden-loop-monitor/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins/golden-loop-monitor/commands/loop-status.md +0 -434
- package/templates/claude-plugins/learning-tracker/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins/learning-tracker/commands/my-patterns.md +0 -282
- package/templates/claude-plugins/memory-lens/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins/memory-lens/commands/memory-search.md +0 -181
- package/templates/claude-plugins/pattern-coach/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins/pattern-coach/commands/forge.md +0 -365
- package/templates/claude-plugins/project-schema-validator/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins/project-schema-validator/commands/validate-schema.md +0 -582
- package/templates/claude-plugins-admin/AGENT_TEAM_PROPOSALS.md +0 -819
- package/templates/claude-plugins-admin/README.md +0 -446
- package/templates/claude-plugins-admin/autonomous-admin-agent/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins-admin/autonomous-admin-agent/commands/agent.md +0 -595
- package/templates/claude-plugins-admin/backend-agent/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins-admin/backend-agent/commands/backend.md +0 -798
- package/templates/claude-plugins-admin/deploy-guardian/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins-admin/deploy-guardian/commands/deploy.md +0 -554
- package/templates/claude-plugins-admin/frontend-agent/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins-admin/frontend-agent/commands/frontend.md +0 -881
- package/templates/claude-plugins-admin/mcp-server-manager/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins-admin/mcp-server-manager/commands/mcp.md +0 -85
- package/templates/claude-plugins-admin/memory-system-monitor/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins-admin/memory-system-monitor/commands/memory-health.md +0 -569
- package/templates/claude-plugins-admin/qa-agent/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins-admin/qa-agent/commands/qa.md +0 -863
- package/templates/claude-plugins-admin/tech-lead-agent/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins-admin/tech-lead-agent/commands/lead.md +0 -732
- package/templates/commands/continue.md +0 -47
- package/templates/cursor-rules/ekkos-memory.md +0 -127
- package/templates/ekkos-manifest.json +0 -223
- package/templates/helpers/json-parse.cjs +0 -101
- package/templates/hooks-node/lib/state.js +0 -187
- package/templates/hooks-node/stop.js +0 -416
- package/templates/hooks-node/user-prompt-submit.js +0 -337
- package/templates/plan-template.md +0 -306
- package/templates/rules/00-hooks-contract.mdc +0 -89
- package/templates/rules/30-ekkos-core.mdc +0 -188
- package/templates/rules/31-ekkos-messages.mdc +0 -78
- package/templates/shared/hooks-enabled.json +0 -22
- package/templates/shared/session-words.json +0 -45
- package/templates/skills/ekkOS_Deep_Recall/Skill.md +0 -282
- package/templates/skills/ekkOS_Learn/Skill.md +0 -265
- package/templates/skills/ekkOS_Memory_First/Skill.md +0 -206
- package/templates/skills/ekkOS_Plan_Assist/Skill.md +0 -302
- package/templates/skills/ekkOS_Preferences/Skill.md +0 -247
- package/templates/skills/ekkOS_Reflect/Skill.md +0 -257
- package/templates/skills/ekkOS_Safety/Skill.md +0 -265
- package/templates/skills/ekkOS_Schema/Skill.md +0 -251
- package/templates/skills/ekkOS_Summary/Skill.md +0 -257
- package/templates/spec-template.md +0 -159
- package/templates/windsurf-rules/ekkos-memory.md +0 -127
- package/templates/windsurf-skills/README.md +0 -58
- package/templates/windsurf-skills/ekkos-continue/SKILL.md +0 -81
- package/templates/windsurf-skills/ekkos-golden-loop/SKILL.md +0 -225
- package/templates/windsurf-skills/ekkos-insights/SKILL.md +0 -138
- package/templates/windsurf-skills/ekkos-recall/SKILL.md +0 -96
- package/templates/windsurf-skills/ekkos-safety/SKILL.md +0 -89
- package/templates/windsurf-skills/ekkos-vault/SKILL.md +0 -86
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
# /continue
|
|
2
|
-
|
|
3
|
-
Restore your last 5 turns after running `/clear`.
|
|
4
|
-
|
|
5
|
-
## Usage
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
/clear # First: free up context
|
|
9
|
-
/continue # Then: restore last 5 turns
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
## What Happens
|
|
13
|
-
|
|
14
|
-
1. Hook detects `/continue`
|
|
15
|
-
2. Fetches last 5 turns from ekkOS API
|
|
16
|
-
3. Injects them as context
|
|
17
|
-
4. Claude continues seamlessly
|
|
18
|
-
|
|
19
|
-
## Why This Exists
|
|
20
|
-
|
|
21
|
-
When context gets full (90%+), you need to `/clear` but don't want to lose your work. This command restores just enough context (5 turns) to continue working without re-explaining everything.
|
|
22
|
-
|
|
23
|
-
## The Flow
|
|
24
|
-
|
|
25
|
-
```
|
|
26
|
-
Work normally until context ~90%
|
|
27
|
-
↓
|
|
28
|
-
Run: /clear (frees context)
|
|
29
|
-
↓
|
|
30
|
-
Run: /continue (restores 5 turns)
|
|
31
|
-
↓
|
|
32
|
-
Keep working
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## Example
|
|
36
|
-
|
|
37
|
-
```
|
|
38
|
-
[Context at 92%]
|
|
39
|
-
|
|
40
|
-
You: /clear
|
|
41
|
-
Claude: Context cleared.
|
|
42
|
-
|
|
43
|
-
You: /continue
|
|
44
|
-
Hook: ✓ Session continued (5 turns restored)
|
|
45
|
-
|
|
46
|
-
Claude: ✓ **Continuing** - We were working on the /continue command...
|
|
47
|
-
```
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "ekkOS Memory — 11-layer cognitive memory with 29 MCP tools"
|
|
3
|
-
alwaysApply: true
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# ekkOS Memory System
|
|
7
|
-
|
|
8
|
-
You have access to **ekkOS memory** via 29 MCP tools. This is an 11-layer cognitive memory system that makes AI smarter over time by learning from past sessions.
|
|
9
|
-
|
|
10
|
-
## MANDATORY RULES
|
|
11
|
-
|
|
12
|
-
### RULE 1: SEARCH BEFORE ANSWERING
|
|
13
|
-
Before answering ANY technical question, call `ekkOS_Search` first.
|
|
14
|
-
|
|
15
|
-
### RULE 2: ACKNOWLEDGE RETRIEVED PATTERNS
|
|
16
|
-
When patterns are retrieved, acknowledge each one:
|
|
17
|
-
```
|
|
18
|
-
[ekkOS_SELECT]
|
|
19
|
-
- id: <pattern_id>
|
|
20
|
-
reason: <why using>
|
|
21
|
-
confidence: <0.0-1.0>
|
|
22
|
-
[/ekkOS_SELECT]
|
|
23
|
-
|
|
24
|
-
[ekkOS_SKIP]
|
|
25
|
-
- id: <pattern_id>
|
|
26
|
-
reason: <why not relevant>
|
|
27
|
-
[/ekkOS_SKIP]
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
Suppress SELECT/SKIP blocks for non-technical turns (acknowledgments, affirmations).
|
|
31
|
-
|
|
32
|
-
### RULE 3: FORGE WHAT YOU LEARN
|
|
33
|
-
When you fix a bug, get corrected, or learn something new, call `ekkOS_Forge` immediately.
|
|
34
|
-
When something DOESN'T work, forge it as an anti-pattern.
|
|
35
|
-
|
|
36
|
-
## MCP Tools — 29 Visible
|
|
37
|
-
|
|
38
|
-
### Core Memory (6)
|
|
39
|
-
| Tool | Description |
|
|
40
|
-
|------|-------------|
|
|
41
|
-
| `ekkOS_Search` | Search across all 11 memory layers |
|
|
42
|
-
| `ekkOS_Forge` | Create pattern from learned solution |
|
|
43
|
-
| `ekkOS_Track` | Track when a pattern is applied |
|
|
44
|
-
| `ekkOS_Outcome` | Record if pattern worked or failed |
|
|
45
|
-
| `ekkOS_Stats` | Get statistics for all layers |
|
|
46
|
-
| `ekkOS_Context` | Get relevant context for a task |
|
|
47
|
-
|
|
48
|
-
### Retrieval (4)
|
|
49
|
-
| Tool | Description |
|
|
50
|
-
|------|-------------|
|
|
51
|
-
| `ekkOS_Codebase` | Search project code embeddings |
|
|
52
|
-
| `ekkOS_Recall` | Recall past conversations by time |
|
|
53
|
-
| `ekkOS_PreserveContext` | Preserve working memory before compaction |
|
|
54
|
-
| `ekkOS_RestoreContext` | Restore context after compaction |
|
|
55
|
-
|
|
56
|
-
### Directives (4)
|
|
57
|
-
| Tool | Description |
|
|
58
|
-
|------|-------------|
|
|
59
|
-
| `ekkOS_Directive` | Create MUST/NEVER/PREFER/AVOID rules |
|
|
60
|
-
| `ekkOS_UpdateDirective` | Update an existing directive |
|
|
61
|
-
| `ekkOS_DeleteDirective` | Remove a directive |
|
|
62
|
-
| `ekkOS_UniversalDirectives` | Get directives that apply across all projects |
|
|
63
|
-
|
|
64
|
-
### Utility (5)
|
|
65
|
-
| Tool | Description |
|
|
66
|
-
|------|-------------|
|
|
67
|
-
| `ekkOS_Summary` | Get summary of recent memory activity |
|
|
68
|
-
| `ekkOS_Conflict` | Check for conflicts before destructive actions |
|
|
69
|
-
| `ekkOS_Export` | Export patterns, directives, plans as JSON backup |
|
|
70
|
-
| `ekkOS_Import` | Import memory from backup (auto-deduplication) |
|
|
71
|
-
| `ekkOS_Health` | System health check |
|
|
72
|
-
|
|
73
|
-
### Plans (5)
|
|
74
|
-
| Tool | Description |
|
|
75
|
-
|------|-------------|
|
|
76
|
-
| `ekkOS_Plan` | Create structured task plan |
|
|
77
|
-
| `ekkOS_Plans` | List your plans |
|
|
78
|
-
| `ekkOS_PlanStatus` | Update plan status |
|
|
79
|
-
| `ekkOS_PlanStep` | Mark step complete/incomplete |
|
|
80
|
-
| `ekkOS_Generate` | AI-generate plan from context |
|
|
81
|
-
|
|
82
|
-
### Secrets (5)
|
|
83
|
-
| Tool | Description |
|
|
84
|
-
|------|-------------|
|
|
85
|
-
| `ekkOS_StoreSecret` | Encrypt and store sensitive data |
|
|
86
|
-
| `ekkOS_GetSecret` | Retrieve and decrypt a secret |
|
|
87
|
-
| `ekkOS_ListSecrets` | List secrets metadata (no values exposed) |
|
|
88
|
-
| `ekkOS_DeleteSecret` | Permanently delete a secret |
|
|
89
|
-
| `ekkOS_RotateSecret` | Update a secret with a new value |
|
|
90
|
-
|
|
91
|
-
## 11-Layer Architecture
|
|
92
|
-
|
|
93
|
-
| # | Layer | Purpose |
|
|
94
|
-
|---|-------|---------|
|
|
95
|
-
| 1 | Working | Current session state |
|
|
96
|
-
| 2 | Episodic | Past conversations |
|
|
97
|
-
| 3 | Semantic | Embeddings & knowledge |
|
|
98
|
-
| 4 | Patterns | Proven solutions |
|
|
99
|
-
| 5 | Procedural | Step-by-step guides |
|
|
100
|
-
| 6 | Collective | Cross-project wisdom |
|
|
101
|
-
| 7 | Meta | Pattern effectiveness |
|
|
102
|
-
| 8 | Codebase | Project-specific code |
|
|
103
|
-
| 9 | Directives | User rules (MUST/NEVER/PREFER/AVOID) |
|
|
104
|
-
| 10 | Conflict | Auto-resolves contradictions |
|
|
105
|
-
| 11 | Secrets | Encrypted credentials (AES-256-GCM) |
|
|
106
|
-
|
|
107
|
-
## When To Use What
|
|
108
|
-
|
|
109
|
-
| Tool | Trigger |
|
|
110
|
-
|------|---------|
|
|
111
|
-
| `ekkOS_Search` | Technical question, past discussion, architecture, debugging |
|
|
112
|
-
| `ekkOS_Forge` | Bug fixed, better approach, gotcha, correction, anti-pattern |
|
|
113
|
-
| `ekkOS_Directive` | User says "always" → MUST, "never" → NEVER, "prefer" → PREFER, "avoid" → AVOID |
|
|
114
|
-
| `ekkOS_Conflict` | Before delete, deploy, config change, destructive commands |
|
|
115
|
-
| Plan tools | Task has 3+ steps, complex feature request |
|
|
116
|
-
| Secret tools | User shares API key/token/password, need stored credentials |
|
|
117
|
-
| `ekkOS_Recall` | "yesterday", "last week", "remember when", "what did we discuss" |
|
|
118
|
-
|
|
119
|
-
## Response Format
|
|
120
|
-
|
|
121
|
-
End every response with:
|
|
122
|
-
```
|
|
123
|
-
---
|
|
124
|
-
🧠 **ekkOS_™** · 📅 YYYY-MM-DD H:MM AM/PM TZ
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
For more info: https://docs.ekkos.dev
|
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://ekkos.dev/schemas/manifest-v1.json",
|
|
3
|
-
"manifestVersion": "1.0.0",
|
|
4
|
-
"generatedAt": "2026-02-20T07:39:17.071Z",
|
|
5
|
-
"platforms": {
|
|
6
|
-
"darwin": {
|
|
7
|
-
"configDir": "~/.ekkos",
|
|
8
|
-
"globalHooksDir": "~/.claude/hooks",
|
|
9
|
-
"shell": "bash"
|
|
10
|
-
},
|
|
11
|
-
"linux": {
|
|
12
|
-
"configDir": "~/.ekkos",
|
|
13
|
-
"globalHooksDir": "~/.claude/hooks",
|
|
14
|
-
"shell": "bash"
|
|
15
|
-
},
|
|
16
|
-
"win32": {
|
|
17
|
-
"configDir": "%USERPROFILE%\\.ekkos",
|
|
18
|
-
"globalHooksDir": "%USERPROFILE%\\.claude\\hooks",
|
|
19
|
-
"shell": "powershell"
|
|
20
|
-
}
|
|
21
|
-
},
|
|
22
|
-
"files": {
|
|
23
|
-
"managed": [
|
|
24
|
-
{
|
|
25
|
-
"source": "shared/session-words.json",
|
|
26
|
-
"destination": ".defaults/session-words.json",
|
|
27
|
-
"description": "Default session word lists (managed fallback)",
|
|
28
|
-
"checksum": "c64af03b9ae58d8c94e71886f80e590ad3a72fb2dcdbe02812789fecb4773e1a",
|
|
29
|
-
"overwrite": "always"
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
"source": "shared/hooks-enabled.json",
|
|
33
|
-
"destination": ".defaults/hooks-enabled.json",
|
|
34
|
-
"description": "Default hooks enablement config (managed fallback)",
|
|
35
|
-
"checksum": "74b833a1979f1b9467be6dcdeecc024073a4f3c02625b0751f4b1f9d53f143a3",
|
|
36
|
-
"overwrite": "always"
|
|
37
|
-
}
|
|
38
|
-
],
|
|
39
|
-
"helpers": [
|
|
40
|
-
{
|
|
41
|
-
"source": "helpers/json-parse.cjs",
|
|
42
|
-
"destination": ".helpers/json-parse.cjs",
|
|
43
|
-
"description": "Node-based JSON parser (replaces jq dependency)",
|
|
44
|
-
"checksum": "e421977262b3bffcbec9f6f7a172df6f998f3b4deac64d478ef5a0a17034b026",
|
|
45
|
-
"executable": true,
|
|
46
|
-
"overwrite": "always"
|
|
47
|
-
}
|
|
48
|
-
],
|
|
49
|
-
"userEditable": [
|
|
50
|
-
{
|
|
51
|
-
"source": "shared/session-words.json",
|
|
52
|
-
"destination": "session-words.json",
|
|
53
|
-
"description": "User-customizable session word lists",
|
|
54
|
-
"checksum": "c64af03b9ae58d8c94e71886f80e590ad3a72fb2dcdbe02812789fecb4773e1a",
|
|
55
|
-
"overwrite": "createOnly"
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
"source": "shared/hooks-enabled.json",
|
|
59
|
-
"destination": "hooks-enabled.json",
|
|
60
|
-
"description": "User-controlled hook enablement",
|
|
61
|
-
"checksum": "74b833a1979f1b9467be6dcdeecc024073a4f3c02625b0751f4b1f9d53f143a3",
|
|
62
|
-
"overwrite": "createOnly"
|
|
63
|
-
}
|
|
64
|
-
],
|
|
65
|
-
"hooks": {
|
|
66
|
-
"bash": [
|
|
67
|
-
{
|
|
68
|
-
"source": "hooks/user-prompt-submit.sh",
|
|
69
|
-
"destination": "user-prompt-submit.sh",
|
|
70
|
-
"description": "User prompt submit hook (Unix)",
|
|
71
|
-
"checksum": "c53b621f3c64031f61b7ca1b3bf5ba4bec895b6a39aa7627422f0f2a2d26ab7d",
|
|
72
|
-
"executable": true
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
"source": "hooks/stop.sh",
|
|
76
|
-
"destination": "stop.sh",
|
|
77
|
-
"description": "Session stop hook (Unix)",
|
|
78
|
-
"checksum": "f3b4495c0c2bbdf5bfef762568faec7b70b41b463dad4c88b37cf7ee32b5257d",
|
|
79
|
-
"executable": true
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
"source": "hooks/session-start.sh",
|
|
83
|
-
"destination": "session-start.sh",
|
|
84
|
-
"description": "Session start hook (Unix)",
|
|
85
|
-
"checksum": "8d17fd3203045589f0c410f465b0d1e98d6ed24dc3bc99f44878e44e9501a22d",
|
|
86
|
-
"executable": true
|
|
87
|
-
},
|
|
88
|
-
{
|
|
89
|
-
"source": "hooks/assistant-response.sh",
|
|
90
|
-
"destination": "assistant-response.sh",
|
|
91
|
-
"description": "Assistant response hook (Unix)",
|
|
92
|
-
"checksum": "99400adf6ced406f0295c25db3b8fb892212ad3ba625f427c042d8526ac8f6f7",
|
|
93
|
-
"executable": true
|
|
94
|
-
}
|
|
95
|
-
],
|
|
96
|
-
"powershell": [
|
|
97
|
-
{
|
|
98
|
-
"source": "hooks/user-prompt-submit.ps1",
|
|
99
|
-
"destination": "user-prompt-submit.ps1",
|
|
100
|
-
"description": "User prompt submit hook (Windows)",
|
|
101
|
-
"checksum": "ba1090ed7a4e7deef1267b52474225669a9c966b9adf596b31865c2dca1dc749"
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
"source": "hooks/stop.ps1",
|
|
105
|
-
"destination": "stop.ps1",
|
|
106
|
-
"description": "Session stop hook (Windows)",
|
|
107
|
-
"checksum": "c4f0191ac28ced0410ea560197ab3b0a7e2de83363a789731d64620bc605564d"
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
"source": "hooks/session-start.ps1",
|
|
111
|
-
"destination": "session-start.ps1",
|
|
112
|
-
"description": "Session start hook (Windows)",
|
|
113
|
-
"checksum": "1930bda7c517054531ff3ad78e8cce7e60d57f5b3884728da0d7cf1cc5c54ac4"
|
|
114
|
-
},
|
|
115
|
-
{
|
|
116
|
-
"source": "hooks/assistant-response.ps1",
|
|
117
|
-
"destination": "assistant-response.ps1",
|
|
118
|
-
"description": "Assistant response hook (Windows)",
|
|
119
|
-
"checksum": "680e6d7c597f90fb54bc86d173f4c145093eb21352b30c7d6afbe19d1d5fdce4"
|
|
120
|
-
}
|
|
121
|
-
],
|
|
122
|
-
"lib": [
|
|
123
|
-
{
|
|
124
|
-
"source": "hooks/lib/contract.sh",
|
|
125
|
-
"destination": "lib/contract.sh",
|
|
126
|
-
"description": "Hook contract library",
|
|
127
|
-
"checksum": "3ef16930ba10cd37a1c5fa8469ec13a6a84cadb882d3f9a96c72da875ba07fc7",
|
|
128
|
-
"executable": true
|
|
129
|
-
},
|
|
130
|
-
{
|
|
131
|
-
"source": "hooks/lib/state.sh",
|
|
132
|
-
"destination": "lib/state.sh",
|
|
133
|
-
"description": "Hook state management library",
|
|
134
|
-
"checksum": "99223ce9b869d78762084ff184327fa2814af7a16e5f2ac9619af43b5e551d7c",
|
|
135
|
-
"executable": true
|
|
136
|
-
}
|
|
137
|
-
]
|
|
138
|
-
}
|
|
139
|
-
},
|
|
140
|
-
"projectStubs": {
|
|
141
|
-
"description": "Delegating stub hooks for project-level installation. These source global hooks first, then load project-specific overrides.",
|
|
142
|
-
"bash": [
|
|
143
|
-
{
|
|
144
|
-
"source": "project-stubs/user-prompt-submit.sh",
|
|
145
|
-
"destination": "user-prompt-submit.sh",
|
|
146
|
-
"description": "Project delegating stub for user-prompt-submit (Unix)",
|
|
147
|
-
"checksum": "47cc6b45dbb027e321c136f7c0935bae0d3dc349f01912fbe42ae27d382e297d",
|
|
148
|
-
"executable": true
|
|
149
|
-
},
|
|
150
|
-
{
|
|
151
|
-
"source": "project-stubs/stop.sh",
|
|
152
|
-
"destination": "stop.sh",
|
|
153
|
-
"description": "Project delegating stub for stop (Unix)",
|
|
154
|
-
"checksum": "a429c5ee596e6c975df32feb8ba952c77c0492d91bd9cd80f9eac2e721040eb4",
|
|
155
|
-
"executable": true
|
|
156
|
-
},
|
|
157
|
-
{
|
|
158
|
-
"source": "project-stubs/session-start.sh",
|
|
159
|
-
"destination": "session-start.sh",
|
|
160
|
-
"description": "Project delegating stub for session-start (Unix)",
|
|
161
|
-
"checksum": "189379e81e000153d057e49afd71791d28a6b73baab4b49b39de34918a00c493",
|
|
162
|
-
"executable": true
|
|
163
|
-
}
|
|
164
|
-
],
|
|
165
|
-
"powershell": [
|
|
166
|
-
{
|
|
167
|
-
"source": "project-stubs/user-prompt-submit.ps1",
|
|
168
|
-
"destination": "user-prompt-submit.ps1",
|
|
169
|
-
"description": "Project delegating stub for user-prompt-submit (Windows)",
|
|
170
|
-
"checksum": "86cfea6a6e1181fc6b9180e82a3e34e1ba8e8b412c65bdf013d2367ea8b93283"
|
|
171
|
-
},
|
|
172
|
-
{
|
|
173
|
-
"source": "project-stubs/stop.ps1",
|
|
174
|
-
"destination": "stop.ps1",
|
|
175
|
-
"description": "Project delegating stub for stop (Windows)",
|
|
176
|
-
"checksum": "042f815ed455c5b5e51291b8740deafaea827c594695b270f4d4e4e5086bc234"
|
|
177
|
-
},
|
|
178
|
-
{
|
|
179
|
-
"source": "project-stubs/session-start.ps1",
|
|
180
|
-
"destination": "session-start.ps1",
|
|
181
|
-
"description": "Project delegating stub for session-start (Windows)",
|
|
182
|
-
"checksum": "14081806c7ca63a67999314f31e14a6c1293e57a8ce64335122f359e3bb8fba4"
|
|
183
|
-
}
|
|
184
|
-
]
|
|
185
|
-
},
|
|
186
|
-
"cli": {
|
|
187
|
-
"minVersion": "0.2.9",
|
|
188
|
-
"legacySupported": true,
|
|
189
|
-
"requiredCommands": {
|
|
190
|
-
"0.2.9": [
|
|
191
|
-
"run",
|
|
192
|
-
"config"
|
|
193
|
-
],
|
|
194
|
-
"0.3.0": [
|
|
195
|
-
"run",
|
|
196
|
-
"config",
|
|
197
|
-
"hooks"
|
|
198
|
-
]
|
|
199
|
-
}
|
|
200
|
-
},
|
|
201
|
-
"validation": {
|
|
202
|
-
"requiredFiles": [
|
|
203
|
-
"shared/session-words.json",
|
|
204
|
-
"shared/hooks-enabled.json",
|
|
205
|
-
"helpers/json-parse.cjs",
|
|
206
|
-
"hooks/user-prompt-submit.sh",
|
|
207
|
-
"hooks/user-prompt-submit.ps1",
|
|
208
|
-
"hooks/stop.sh",
|
|
209
|
-
"hooks/stop.ps1",
|
|
210
|
-
"hooks/session-start.sh",
|
|
211
|
-
"hooks/session-start.ps1",
|
|
212
|
-
"hooks/assistant-response.sh",
|
|
213
|
-
"hooks/assistant-response.ps1",
|
|
214
|
-
"project-stubs/user-prompt-submit.sh",
|
|
215
|
-
"project-stubs/user-prompt-submit.ps1",
|
|
216
|
-
"project-stubs/stop.sh",
|
|
217
|
-
"project-stubs/stop.ps1",
|
|
218
|
-
"project-stubs/session-start.sh",
|
|
219
|
-
"project-stubs/session-start.ps1"
|
|
220
|
-
],
|
|
221
|
-
"checksumAlgorithm": "sha256"
|
|
222
|
-
}
|
|
223
|
-
}
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* json-parse.cjs - Minimal JSON parser for ekkOS hooks
|
|
4
|
-
* Eliminates jq dependency for cross-platform compatibility
|
|
5
|
-
*
|
|
6
|
-
* Usage: json-parse.cjs <file> [path]
|
|
7
|
-
*
|
|
8
|
-
* Examples:
|
|
9
|
-
* json-parse.cjs config.json # Output entire file
|
|
10
|
-
* json-parse.cjs config.json .apiKey # Output single value
|
|
11
|
-
* json-parse.cjs words.json .adjectives # Output array (one per line)
|
|
12
|
-
* json-parse.cjs hooks.json .targets.claude.stop # Nested path
|
|
13
|
-
*
|
|
14
|
-
* Exit codes:
|
|
15
|
-
* 0 - Success (including empty/null result)
|
|
16
|
-
* 1 - Error (file not found, invalid JSON, etc.)
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
const fs = require('fs');
|
|
20
|
-
const path = require('path');
|
|
21
|
-
|
|
22
|
-
const args = process.argv.slice(2);
|
|
23
|
-
|
|
24
|
-
if (args.length < 1) {
|
|
25
|
-
console.error('Usage: json-parse.cjs <file> [path]');
|
|
26
|
-
console.error('Example: json-parse.cjs config.json .apiKey');
|
|
27
|
-
process.exit(1);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const filePath = args[0];
|
|
31
|
-
const jsonPath = args[1] || null;
|
|
32
|
-
|
|
33
|
-
// Check file exists
|
|
34
|
-
if (!fs.existsSync(filePath)) {
|
|
35
|
-
console.error(`Error: File not found: ${filePath}`);
|
|
36
|
-
process.exit(1);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
let data;
|
|
40
|
-
try {
|
|
41
|
-
const content = fs.readFileSync(filePath, 'utf8');
|
|
42
|
-
data = JSON.parse(content);
|
|
43
|
-
} catch (err) {
|
|
44
|
-
console.error(`Error: Failed to parse JSON: ${err.message}`);
|
|
45
|
-
process.exit(1);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// If no path specified, output entire JSON
|
|
49
|
-
if (!jsonPath) {
|
|
50
|
-
console.log(JSON.stringify(data, null, 2));
|
|
51
|
-
process.exit(0);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Parse path and extract value
|
|
55
|
-
// Supports: .foo.bar, .foo[0], .foo.bar[1].baz
|
|
56
|
-
function extractValue(obj, pathStr) {
|
|
57
|
-
if (!pathStr || pathStr === '.') return obj;
|
|
58
|
-
|
|
59
|
-
// Remove leading dot if present
|
|
60
|
-
const cleanPath = pathStr.startsWith('.') ? pathStr.slice(1) : pathStr;
|
|
61
|
-
if (!cleanPath) return obj;
|
|
62
|
-
|
|
63
|
-
// Split on . and [ but keep the brackets for array access
|
|
64
|
-
const parts = cleanPath.split(/\.|\[|\]/).filter(Boolean);
|
|
65
|
-
|
|
66
|
-
let result = obj;
|
|
67
|
-
for (const part of parts) {
|
|
68
|
-
if (result === undefined || result === null) {
|
|
69
|
-
return undefined;
|
|
70
|
-
}
|
|
71
|
-
result = result[part];
|
|
72
|
-
}
|
|
73
|
-
return result;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const result = extractValue(data, jsonPath);
|
|
77
|
-
|
|
78
|
-
// Handle different result types
|
|
79
|
-
if (result === undefined || result === null) {
|
|
80
|
-
// Empty output, exit 0 (not an error - just no value)
|
|
81
|
-
process.exit(0);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (Array.isArray(result)) {
|
|
85
|
-
// Output array items one per line (like jq -r '.[]')
|
|
86
|
-
for (const item of result) {
|
|
87
|
-
if (typeof item === 'object') {
|
|
88
|
-
console.log(JSON.stringify(item));
|
|
89
|
-
} else {
|
|
90
|
-
console.log(item);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
} else if (typeof result === 'object') {
|
|
94
|
-
console.log(JSON.stringify(result, null, 2));
|
|
95
|
-
} else if (typeof result === 'boolean') {
|
|
96
|
-
console.log(result ? 'true' : 'false');
|
|
97
|
-
} else {
|
|
98
|
-
console.log(result);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
process.exit(0);
|
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* ekkOS™ Hook State Management Library (Node.js - Cross-Platform)
|
|
4
|
-
* Shared state functions for coordinating between hooks
|
|
5
|
-
* Works on Windows, macOS, and Linux without bash/curl/jq dependencies
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const fs = require('fs');
|
|
9
|
-
const path = require('path');
|
|
10
|
-
const crypto = require('crypto');
|
|
11
|
-
|
|
12
|
-
// Get project root (where .claude directory lives)
|
|
13
|
-
function getProjectRoot() {
|
|
14
|
-
const scriptDir = __dirname;
|
|
15
|
-
return path.dirname(path.dirname(path.dirname(scriptDir)));
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const PROJECT_ROOT = getProjectRoot();
|
|
19
|
-
const STATE_DIR = path.join(PROJECT_ROOT, '.claude', 'state');
|
|
20
|
-
|
|
21
|
-
// Ensure state directory exists
|
|
22
|
-
function ensureStateDir() {
|
|
23
|
-
if (!fs.existsSync(STATE_DIR)) {
|
|
24
|
-
fs.mkdirSync(STATE_DIR, { recursive: true });
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
29
|
-
// State File Management
|
|
30
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
31
|
-
|
|
32
|
-
function savePatterns(sessionId, patterns, modelUsed) {
|
|
33
|
-
ensureStateDir();
|
|
34
|
-
const stateFile = path.join(STATE_DIR, `patterns-${sessionId}.json`);
|
|
35
|
-
|
|
36
|
-
const data = {
|
|
37
|
-
patterns: patterns,
|
|
38
|
-
model_used: modelUsed,
|
|
39
|
-
saved_at: new Date().toISOString()
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
fs.writeFileSync(stateFile, JSON.stringify(data, null, 2));
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function loadPatterns(sessionId) {
|
|
46
|
-
const stateFile = path.join(STATE_DIR, `patterns-${sessionId}.json`);
|
|
47
|
-
|
|
48
|
-
if (fs.existsSync(stateFile)) {
|
|
49
|
-
try {
|
|
50
|
-
return JSON.parse(fs.readFileSync(stateFile, 'utf8'));
|
|
51
|
-
} catch {
|
|
52
|
-
return {};
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return {};
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function clearPatterns(sessionId) {
|
|
59
|
-
const stateFile = path.join(STATE_DIR, `patterns-${sessionId}.json`);
|
|
60
|
-
if (fs.existsSync(stateFile)) {
|
|
61
|
-
fs.unlinkSync(stateFile);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
66
|
-
// Capture Deduplication
|
|
67
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
68
|
-
|
|
69
|
-
function generateTurnHash(userQuery, assistantResponse) {
|
|
70
|
-
return crypto.createHash('md5').update(`${userQuery}${assistantResponse}`).digest('hex');
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function wasTurnCaptured(sessionId, turnHash) {
|
|
74
|
-
const captureLog = path.join(STATE_DIR, `captures-${sessionId}.log`);
|
|
75
|
-
|
|
76
|
-
if (fs.existsSync(captureLog)) {
|
|
77
|
-
const hashes = fs.readFileSync(captureLog, 'utf8').split('\n');
|
|
78
|
-
return hashes.includes(turnHash);
|
|
79
|
-
}
|
|
80
|
-
return false;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function markTurnCaptured(sessionId, turnHash) {
|
|
84
|
-
ensureStateDir();
|
|
85
|
-
const captureLog = path.join(STATE_DIR, `captures-${sessionId}.log`);
|
|
86
|
-
|
|
87
|
-
fs.appendFileSync(captureLog, `${turnHash}\n`);
|
|
88
|
-
|
|
89
|
-
// Keep only last 100 hashes
|
|
90
|
-
try {
|
|
91
|
-
const hashes = fs.readFileSync(captureLog, 'utf8').split('\n').filter(Boolean);
|
|
92
|
-
if (hashes.length > 100) {
|
|
93
|
-
fs.writeFileSync(captureLog, hashes.slice(-100).join('\n') + '\n');
|
|
94
|
-
}
|
|
95
|
-
} catch {
|
|
96
|
-
// Ignore cleanup errors
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
101
|
-
// Lock Management
|
|
102
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
103
|
-
|
|
104
|
-
function acquireLock(sessionId) {
|
|
105
|
-
ensureStateDir();
|
|
106
|
-
const lockFile = path.join(STATE_DIR, `lock-${sessionId}.lock`);
|
|
107
|
-
const timeout = 5000; // 5 seconds
|
|
108
|
-
const startTime = Date.now();
|
|
109
|
-
|
|
110
|
-
while (fs.existsSync(lockFile)) {
|
|
111
|
-
if (Date.now() - startTime > timeout) {
|
|
112
|
-
// Check if lock is stale (older than 10 seconds)
|
|
113
|
-
try {
|
|
114
|
-
const stat = fs.statSync(lockFile);
|
|
115
|
-
if (Date.now() - stat.mtimeMs > 10000) {
|
|
116
|
-
fs.unlinkSync(lockFile);
|
|
117
|
-
break;
|
|
118
|
-
}
|
|
119
|
-
} catch {
|
|
120
|
-
break;
|
|
121
|
-
}
|
|
122
|
-
return false;
|
|
123
|
-
}
|
|
124
|
-
// Wait 100ms
|
|
125
|
-
const waitUntil = Date.now() + 100;
|
|
126
|
-
while (Date.now() < waitUntil) {}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
fs.writeFileSync(lockFile, process.pid.toString());
|
|
130
|
-
return true;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function releaseLock(sessionId) {
|
|
134
|
-
const lockFile = path.join(STATE_DIR, `lock-${sessionId}.lock`);
|
|
135
|
-
|
|
136
|
-
try {
|
|
137
|
-
const content = fs.readFileSync(lockFile, 'utf8');
|
|
138
|
-
if (content.trim() === process.pid.toString()) {
|
|
139
|
-
fs.unlinkSync(lockFile);
|
|
140
|
-
}
|
|
141
|
-
} catch {
|
|
142
|
-
// Lock file doesn't exist or can't be read
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
147
|
-
// Cleanup
|
|
148
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
149
|
-
|
|
150
|
-
function cleanupOldState() {
|
|
151
|
-
if (!fs.existsSync(STATE_DIR)) return;
|
|
152
|
-
|
|
153
|
-
const now = Date.now();
|
|
154
|
-
const oneDayMs = 24 * 60 * 60 * 1000;
|
|
155
|
-
|
|
156
|
-
try {
|
|
157
|
-
const files = fs.readdirSync(STATE_DIR);
|
|
158
|
-
for (const file of files) {
|
|
159
|
-
const filePath = path.join(STATE_DIR, file);
|
|
160
|
-
try {
|
|
161
|
-
const stat = fs.statSync(filePath);
|
|
162
|
-
if (now - stat.mtimeMs > oneDayMs) {
|
|
163
|
-
fs.unlinkSync(filePath);
|
|
164
|
-
}
|
|
165
|
-
} catch {
|
|
166
|
-
// Ignore file errors
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
} catch {
|
|
170
|
-
// Ignore directory errors
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
module.exports = {
|
|
175
|
-
PROJECT_ROOT,
|
|
176
|
-
STATE_DIR,
|
|
177
|
-
ensureStateDir,
|
|
178
|
-
savePatterns,
|
|
179
|
-
loadPatterns,
|
|
180
|
-
clearPatterns,
|
|
181
|
-
generateTurnHash,
|
|
182
|
-
wasTurnCaptured,
|
|
183
|
-
markTurnCaptured,
|
|
184
|
-
acquireLock,
|
|
185
|
-
releaseLock,
|
|
186
|
-
cleanupOldState
|
|
187
|
-
};
|