@ekkos/cli 1.2.18 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/cache/capture.js +0 -0
  2. package/dist/commands/dashboard.js +121 -66
  3. package/dist/commands/hooks.d.ts +25 -36
  4. package/dist/commands/hooks.js +43 -615
  5. package/dist/commands/init.js +7 -23
  6. package/dist/commands/run.js +90 -3
  7. package/dist/commands/setup.js +10 -352
  8. package/dist/deploy/hooks.d.ts +8 -5
  9. package/dist/deploy/hooks.js +12 -105
  10. package/dist/deploy/settings.d.ts +8 -2
  11. package/dist/deploy/settings.js +22 -51
  12. package/dist/index.js +17 -39
  13. package/dist/utils/state.js +7 -2
  14. package/package.json +1 -1
  15. package/templates/CLAUDE.md +82 -292
  16. package/templates/cursor-rules/ekkos-memory.md +48 -108
  17. package/templates/windsurf-rules/ekkos-memory.md +62 -64
  18. package/templates/cursor-hooks/after-agent-response.sh +0 -117
  19. package/templates/cursor-hooks/before-submit-prompt.sh +0 -419
  20. package/templates/cursor-hooks/hooks.json +0 -20
  21. package/templates/cursor-hooks/lib/contract.sh +0 -320
  22. package/templates/cursor-hooks/stop.sh +0 -75
  23. package/templates/hooks/assistant-response.ps1 +0 -256
  24. package/templates/hooks/assistant-response.sh +0 -160
  25. package/templates/hooks/hooks.json +0 -40
  26. package/templates/hooks/lib/contract.sh +0 -332
  27. package/templates/hooks/lib/count-tokens.cjs +0 -86
  28. package/templates/hooks/lib/ekkos-reminders.sh +0 -98
  29. package/templates/hooks/lib/state.sh +0 -210
  30. package/templates/hooks/session-start.ps1 +0 -146
  31. package/templates/hooks/session-start.sh +0 -353
  32. package/templates/hooks/stop.ps1 +0 -349
  33. package/templates/hooks/stop.sh +0 -382
  34. package/templates/hooks/user-prompt-submit.ps1 +0 -419
  35. package/templates/hooks/user-prompt-submit.sh +0 -516
  36. package/templates/project-stubs/session-start.ps1 +0 -63
  37. package/templates/project-stubs/session-start.sh +0 -55
  38. package/templates/project-stubs/stop.ps1 +0 -63
  39. package/templates/project-stubs/stop.sh +0 -55
  40. package/templates/project-stubs/user-prompt-submit.ps1 +0 -63
  41. package/templates/project-stubs/user-prompt-submit.sh +0 -55
  42. package/templates/windsurf-hooks/README.md +0 -212
  43. package/templates/windsurf-hooks/hooks.json +0 -17
  44. package/templates/windsurf-hooks/install.sh +0 -148
  45. package/templates/windsurf-hooks/lib/contract.sh +0 -322
  46. package/templates/windsurf-hooks/post-cascade-response.sh +0 -251
  47. package/templates/windsurf-hooks/pre-user-prompt.sh +0 -435
@@ -1,63 +0,0 @@
1
- # ═══════════════════════════════════════════════════════════════════════════
2
- # ekkOS Project Hook Stub: stop.ps1
3
- # EKKOS_MANAGED=1
4
- # EKKOS_MANIFEST_SHA256=project-stub-v1
5
- # EKKOS_TEMPLATE_VERSION=1.0.0
6
- #
7
- # This is a DELEGATING STUB that:
8
- # 1. Executes the global hook first
9
- # 2. Then loads project-specific overrides if present
10
- #
11
- # Do not modify this file directly. Customizations go in:
12
- # <project>\.ekkos\hooks.local.ps1
13
- # ═══════════════════════════════════════════════════════════════════════════
14
-
15
- $ErrorActionPreference = 'Stop'
16
-
17
- # ═══════════════════════════════════════════════════════════════════════════
18
- # RESOLVE PATHS
19
- # ═══════════════════════════════════════════════════════════════════════════
20
-
21
- # Get absolute path to this stub
22
- $StubPath = $PSScriptRoot
23
- $StubFile = $MyInvocation.MyCommand.Path
24
-
25
- # Project root is two levels up from .claude\hooks\
26
- $ProjectRoot = (Get-Item "$StubPath\..\..").FullName
27
-
28
- # Global hooks directory
29
- $GlobalHooksDir = Join-Path $env:USERPROFILE ".claude\hooks"
30
-
31
- # Global hook path
32
- $GlobalHook = Join-Path $GlobalHooksDir "stop.ps1"
33
-
34
- # Project override file
35
- $ProjectOverride = Join-Path $ProjectRoot ".ekkos\hooks.local.ps1"
36
-
37
- # ═══════════════════════════════════════════════════════════════════════════
38
- # EXECUTE GLOBAL HOOK
39
- # ═══════════════════════════════════════════════════════════════════════════
40
-
41
- if (Test-Path $GlobalHook) {
42
- try {
43
- # Dot-source the global hook (inherits all env vars and args)
44
- . $GlobalHook
45
- } catch {
46
- Write-Error "[ekkOS] Error executing global hook: $_"
47
- }
48
- } else {
49
- Write-Warning "[ekkOS] Global hook not found: $GlobalHook"
50
- }
51
-
52
- # ═══════════════════════════════════════════════════════════════════════════
53
- # LOAD PROJECT OVERRIDES (optional)
54
- # ═══════════════════════════════════════════════════════════════════════════
55
-
56
- if (Test-Path $ProjectOverride) {
57
- try {
58
- # Dot-source project-specific customizations
59
- . $ProjectOverride
60
- } catch {
61
- Write-Warning "[ekkOS] Error loading project override: $_"
62
- }
63
- }
@@ -1,55 +0,0 @@
1
- #!/usr/bin/env bash
2
- # ═══════════════════════════════════════════════════════════════════════════
3
- # ekkOS Project Hook Stub: stop.sh
4
- # EKKOS_MANAGED=1
5
- # EKKOS_MANIFEST_SHA256=project-stub-v1
6
- # EKKOS_TEMPLATE_VERSION=1.0.0
7
- #
8
- # This is a DELEGATING STUB that:
9
- # 1. Executes the global hook first
10
- # 2. Then loads project-specific overrides if present
11
- #
12
- # Do not modify this file directly. Customizations go in:
13
- # <project>/.ekkos/hooks.local.sh
14
- # ═══════════════════════════════════════════════════════════════════════════
15
- set -euo pipefail
16
-
17
- # ═══════════════════════════════════════════════════════════════════════════
18
- # RESOLVE PATHS
19
- # ═══════════════════════════════════════════════════════════════════════════
20
-
21
- # Get absolute path to this stub
22
- STUB_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/$(basename "${BASH_SOURCE[0]}")"
23
-
24
- # Project root is two levels up from .claude/hooks/
25
- PROJECT_ROOT="$(cd "$(dirname "$STUB_PATH")/../.." && pwd)"
26
-
27
- # Global hooks directory
28
- GLOBAL_HOOKS_DIR="$HOME/.claude/hooks"
29
-
30
- # Global hook path
31
- GLOBAL_HOOK="$GLOBAL_HOOKS_DIR/stop.sh"
32
-
33
- # Project override file
34
- PROJECT_OVERRIDE="$PROJECT_ROOT/.ekkos/hooks.local.sh"
35
-
36
- # ═══════════════════════════════════════════════════════════════════════════
37
- # EXECUTE GLOBAL HOOK
38
- # ═══════════════════════════════════════════════════════════════════════════
39
-
40
- if [ -f "$GLOBAL_HOOK" ] && [ -x "$GLOBAL_HOOK" ]; then
41
- # Source the global hook (inherits all env vars and args)
42
- source "$GLOBAL_HOOK"
43
- else
44
- echo "[ekkOS] Warning: Global hook not found: $GLOBAL_HOOK" >&2
45
- fi
46
-
47
- # ═══════════════════════════════════════════════════════════════════════════
48
- # LOAD PROJECT OVERRIDES (optional)
49
- # ═══════════════════════════════════════════════════════════════════════════
50
-
51
- if [ -f "$PROJECT_OVERRIDE" ]; then
52
- # Source project-specific customizations
53
- # These can override functions or add project-specific behavior
54
- source "$PROJECT_OVERRIDE"
55
- fi
@@ -1,63 +0,0 @@
1
- # ═══════════════════════════════════════════════════════════════════════════
2
- # ekkOS Project Hook Stub: user-prompt-submit.ps1
3
- # EKKOS_MANAGED=1
4
- # EKKOS_MANIFEST_SHA256=project-stub-v1
5
- # EKKOS_TEMPLATE_VERSION=1.0.0
6
- #
7
- # This is a DELEGATING STUB that:
8
- # 1. Executes the global hook first
9
- # 2. Then loads project-specific overrides if present
10
- #
11
- # Do not modify this file directly. Customizations go in:
12
- # <project>\.ekkos\hooks.local.ps1
13
- # ═══════════════════════════════════════════════════════════════════════════
14
-
15
- $ErrorActionPreference = 'Stop'
16
-
17
- # ═══════════════════════════════════════════════════════════════════════════
18
- # RESOLVE PATHS
19
- # ═══════════════════════════════════════════════════════════════════════════
20
-
21
- # Get absolute path to this stub
22
- $StubPath = $PSScriptRoot
23
- $StubFile = $MyInvocation.MyCommand.Path
24
-
25
- # Project root is two levels up from .claude\hooks\
26
- $ProjectRoot = (Get-Item "$StubPath\..\..").FullName
27
-
28
- # Global hooks directory
29
- $GlobalHooksDir = Join-Path $env:USERPROFILE ".claude\hooks"
30
-
31
- # Global hook path
32
- $GlobalHook = Join-Path $GlobalHooksDir "user-prompt-submit.ps1"
33
-
34
- # Project override file
35
- $ProjectOverride = Join-Path $ProjectRoot ".ekkos\hooks.local.ps1"
36
-
37
- # ═══════════════════════════════════════════════════════════════════════════
38
- # EXECUTE GLOBAL HOOK
39
- # ═══════════════════════════════════════════════════════════════════════════
40
-
41
- if (Test-Path $GlobalHook) {
42
- try {
43
- # Dot-source the global hook (inherits all env vars and args)
44
- . $GlobalHook
45
- } catch {
46
- Write-Error "[ekkOS] Error executing global hook: $_"
47
- }
48
- } else {
49
- Write-Warning "[ekkOS] Global hook not found: $GlobalHook"
50
- }
51
-
52
- # ═══════════════════════════════════════════════════════════════════════════
53
- # LOAD PROJECT OVERRIDES (optional)
54
- # ═══════════════════════════════════════════════════════════════════════════
55
-
56
- if (Test-Path $ProjectOverride) {
57
- try {
58
- # Dot-source project-specific customizations
59
- . $ProjectOverride
60
- } catch {
61
- Write-Warning "[ekkOS] Error loading project override: $_"
62
- }
63
- }
@@ -1,55 +0,0 @@
1
- #!/usr/bin/env bash
2
- # ═══════════════════════════════════════════════════════════════════════════
3
- # ekkOS Project Hook Stub: user-prompt-submit.sh
4
- # EKKOS_MANAGED=1
5
- # EKKOS_MANIFEST_SHA256=project-stub-v1
6
- # EKKOS_TEMPLATE_VERSION=1.0.0
7
- #
8
- # This is a DELEGATING STUB that:
9
- # 1. Executes the global hook first
10
- # 2. Then loads project-specific overrides if present
11
- #
12
- # Do not modify this file directly. Customizations go in:
13
- # <project>/.ekkos/hooks.local.sh
14
- # ═══════════════════════════════════════════════════════════════════════════
15
- set -euo pipefail
16
-
17
- # ═══════════════════════════════════════════════════════════════════════════
18
- # RESOLVE PATHS
19
- # ═══════════════════════════════════════════════════════════════════════════
20
-
21
- # Get absolute path to this stub
22
- STUB_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/$(basename "${BASH_SOURCE[0]}")"
23
-
24
- # Project root is two levels up from .claude/hooks/
25
- PROJECT_ROOT="$(cd "$(dirname "$STUB_PATH")/../.." && pwd)"
26
-
27
- # Global hooks directory
28
- GLOBAL_HOOKS_DIR="$HOME/.claude/hooks"
29
-
30
- # Global hook path
31
- GLOBAL_HOOK="$GLOBAL_HOOKS_DIR/user-prompt-submit.sh"
32
-
33
- # Project override file
34
- PROJECT_OVERRIDE="$PROJECT_ROOT/.ekkos/hooks.local.sh"
35
-
36
- # ═══════════════════════════════════════════════════════════════════════════
37
- # EXECUTE GLOBAL HOOK
38
- # ═══════════════════════════════════════════════════════════════════════════
39
-
40
- if [ -f "$GLOBAL_HOOK" ] && [ -x "$GLOBAL_HOOK" ]; then
41
- # Source the global hook (inherits all env vars and args)
42
- source "$GLOBAL_HOOK"
43
- else
44
- echo "[ekkOS] Warning: Global hook not found: $GLOBAL_HOOK" >&2
45
- fi
46
-
47
- # ═══════════════════════════════════════════════════════════════════════════
48
- # LOAD PROJECT OVERRIDES (optional)
49
- # ═══════════════════════════════════════════════════════════════════════════
50
-
51
- if [ -f "$PROJECT_OVERRIDE" ]; then
52
- # Source project-specific customizations
53
- # These can override functions or add project-specific behavior
54
- source "$PROJECT_OVERRIDE"
55
- fi
@@ -1,212 +0,0 @@
1
- # ekkOS Windsurf Cascade Hooks
2
-
3
- Complete Golden Loop integration for Windsurf Cascade with proactive memory retrieval, PatternGuard enforcement, and automatic turn capture.
4
-
5
- ## Features
6
-
7
- - **Proactive Memory Retrieval**: Automatically retrieves patterns from all 8 memory layers before each prompt
8
- - **Endless Context**: Auto-restores conversation context after context compaction (10+ min gaps)
9
- - **Time Machine**: Supports "Continue from here" to restore past sessions
10
- - **PatternGuard**: Enforces 100% pattern acknowledgment with SELECT/SKIP markers
11
- - **Footer Enforcement**: Requires ekkOS™ branded timestamp footer on all responses
12
- - **Golden Loop Compliance**: Turn contracts, validation, and outcome tracking
13
-
14
- ## Installation
15
-
16
- ### 1. Copy hooks to your project
17
-
18
- ```bash
19
- # From your project root
20
- cp -r /path/to/ekkos/templates/windsurf-hooks .windsurf/
21
- ```
22
-
23
- ### 2. Configure Windsurf hooks
24
-
25
- Create `.windsurf/hooks.json` in your project root:
26
-
27
- ```json
28
- {
29
- "version": 1,
30
- "hooks": {
31
- "pre_user_prompt": [
32
- {
33
- "command": "./.windsurf/hooks/pre-user-prompt.sh",
34
- "show_output": false
35
- }
36
- ],
37
- "post_cascade_response": [
38
- {
39
- "command": "./.windsurf/hooks/post-cascade-response.sh",
40
- "show_output": false
41
- }
42
- ]
43
- }
44
- }
45
- ```
46
-
47
- ### 3. Authenticate ekkOS
48
-
49
- Ensure you have a valid ekkOS config:
50
-
51
- ```bash
52
- # Check your auth
53
- cat ~/.ekkos/config.json
54
- ```
55
-
56
- If not configured, run `ekkOS: Connect` in VS Code to set up authentication.
57
-
58
- ### 4. Test the integration
59
-
60
- Open Cascade and ask a technical question. You should see:
61
-
62
- ```
63
- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
64
- 🧠 ekkOS™ Memory Substrate
65
- ✓ 3 patterns loaded from memory
66
- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
67
- ```
68
-
69
- ## How It Works
70
-
71
- ### Hook Flow
72
-
73
- ```
74
- User Prompt
75
-
76
- pre_user_prompt hook
77
- ├─ Retrieves patterns from ekkOS API
78
- ├─ Checks for Time Machine requests
79
- ├─ Auto-restores Endless Context (if gap detected)
80
- ├─ Writes turn contract
81
- └─ Injects patterns + footer requirement
82
-
83
- Cascade processes augmented prompt
84
-
85
- Cascade generates response
86
-
87
- post_cascade_response hook
88
- ├─ Validates PatternGuard (acknowledgments)
89
- ├─ Checks footer presence
90
- ├─ Captures turn to L2 episodic memory
91
- ├─ Tracks pattern outcomes
92
- └─ Reports compliance status
93
- ```
94
-
95
- ### Golden Loop Enforcement
96
-
97
- **RETRIEVE** (pre_user_prompt):
98
- - Searches all 8 memory layers
99
- - Returns patterns with IDs
100
- - Writes turn contract as evidence
101
-
102
- **ACKNOWLEDGE** (Cascade response must include):
103
- ```
104
- [ekkOS_SELECT]
105
- - id: <pattern-uuid>
106
- reason: <why using>
107
- confidence: <0.0-1.0>
108
- [/ekkOS_SELECT]
109
-
110
- [ekkOS_SKIP]
111
- - id: <pattern-uuid>
112
- reason: <why not relevant>
113
- [/ekkOS_SKIP]
114
- ```
115
-
116
- **FOOTER** (required on all responses):
117
- ```
118
- 🧠 **ekkOS_™** · 📅 YYYY-MM-DD H:MM AM/PM TZ
119
- ```
120
-
121
- **CAPTURE** (post_cascade_response):
122
- - Stores turn in episodic memory (L2)
123
- - Validates compliance
124
- - Tracks pattern usage outcomes
125
-
126
- ## Configuration Options
127
-
128
- ### Strict Mode
129
-
130
- Set `EKKOS_STRICT=1` to block turns when retrieval fails:
131
-
132
- ```bash
133
- export EKKOS_STRICT=1
134
- ```
135
-
136
- ### Auth Sources (priority order)
137
-
138
- 1. `~/.ekkos/config.json` (preferred - set by VS Code extension)
139
- 2. Project `.env.local` (SUPABASE_SECRET_KEY)
140
- 3. Environment variable `SUPABASE_SECRET_KEY`
141
-
142
- ### Hook Locations
143
-
144
- Cascade merges hooks from all locations (system → user → workspace):
145
-
146
- - **System**: `/Library/Application Support/Windsurf/hooks.json` (macOS)
147
- - **User**: `~/.codeium/windsurf/hooks.json`
148
- - **Workspace**: `.windsurf/hooks.json` (project-specific)
149
-
150
- ## File Structure
151
-
152
- ```
153
- .windsurf/
154
- ├── hooks.json # Hook configuration
155
- └── hooks/
156
- ├── pre-user-prompt.sh # Retrieval + injection
157
- ├── post-cascade-response.sh # Capture + validation
158
- └── lib/
159
- └── contract.sh # Turn contract library
160
- ```
161
-
162
- ## Troubleshooting
163
-
164
- ### "No auth token" message
165
-
166
- 1. Run `ekkOS: Connect` in VS Code
167
- 2. Check `~/.ekkos/config.json` exists with `hookApiKey` or `apiKey`
168
- 3. Verify the key is valid at https://platform.ekkos.dev
169
-
170
- ### Hooks not firing
171
-
172
- 1. Check file permissions: `chmod +x .windsurf/hooks/*.sh`
173
- 2. Verify JSON syntax in `hooks.json`
174
- 3. Check Windsurf logs: Cascade toolbar → Settings → Download diagnostics
175
- 4. Ensure `jq` is installed: `which jq`
176
-
177
- ### Patterns not loading
178
-
179
- 1. Test API health: `curl https://mcp.ekkos.dev/api/v1/gateway/health`
180
- 2. Check network connectivity
181
- 3. Verify auth token has access to your user data
182
-
183
- ### Footer enforcement not working
184
-
185
- The footer check is in `post_cascade_response`. Non-compliance is logged but doesn't block the response (unless STRICT mode is on). Check your responses include:
186
- - The 🧠 emoji
187
- - `ekkOS` text
188
- - 📅 date stamp
189
-
190
- ## Comparison: Windsurf vs Cursor/Claude Code
191
-
192
- | Feature | Windsurf Hooks | Cursor Hooks | Claude Code |
193
- |---------|----------------|--------------|-------------|
194
- | Hook names | `pre_user_prompt`, `post_cascade_response` | `beforeSubmitPrompt`, `afterAgentResponse` | `.claude/` scripts |
195
- | Auto-inject | ✅ Yes | ✅ Yes | ✅ Yes |
196
- | Endless Context | ✅ Yes | ✅ Yes | ✅ Yes |
197
- | Time Machine | ✅ Yes | ✅ Yes | ✅ Yes |
198
- | PatternGuard | ✅ Yes | ✅ Yes | ✅ Yes |
199
- | Footer required | ✅ Yes | ✅ Yes | ✅ Yes |
200
-
201
- ## API Endpoints Used
202
-
203
- - `POST /api/v1/context/retrieve` - Pattern retrieval
204
- - `POST /api/v1/capture` - Turn storage
205
- - `POST /api/v1/turns/recall` - Endless Context restoration
206
- - `GET /api/v1/context/restore-request/pending` - Time Machine check
207
- - `POST /api/v1/context/restore-request/consume` - Time Machine consume
208
- - `POST /api/v1/patterns/outcome` - Pattern outcome tracking
209
-
210
- ## License
211
-
212
- Part of the ekkOS memory system. See main repository for license details.
@@ -1,17 +0,0 @@
1
- {
2
- "version": 1,
3
- "hooks": {
4
- "pre_user_prompt": [
5
- {
6
- "command": "./.windsurf/hooks/pre-user-prompt.sh",
7
- "show_output": false
8
- }
9
- ],
10
- "post_cascade_response": [
11
- {
12
- "command": "./.windsurf/hooks/post-cascade-response.sh",
13
- "show_output": false
14
- }
15
- ]
16
- }
17
- }
@@ -1,148 +0,0 @@
1
- #!/bin/bash
2
- # ═══════════════════════════════════════════════════════════════════════════
3
- # ekkOS Windsurf Hooks Installer
4
- # ═══════════════════════════════════════════════════════════════════════════
5
- #
6
- # Usage: ./install.sh [--global]
7
- # --global: Install to ~/.windsurf/ (works in all projects)
8
- # (default): Install to ./.windsurf/ (project-level only)
9
- #
10
- # ═══════════════════════════════════════════════════════════════════════════
11
-
12
- set -e
13
-
14
- # Colors
15
- RED='\033[0;31m'
16
- GREEN='\033[0;32m'
17
- YELLOW='\033[1;33m'
18
- BLUE='\033[0;34m'
19
- NC='\033[0m' # No Color
20
-
21
- # Parse arguments
22
- GLOBAL_INSTALL=false
23
- if [ "$1" = "--global" ]; then
24
- GLOBAL_INSTALL=true
25
- fi
26
-
27
- # Get script directory
28
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
29
-
30
- # Determine install location
31
- if [ "$GLOBAL_INSTALL" = true ]; then
32
- WINDSURF_DIR="$HOME/.windsurf"
33
- echo -e "${BLUE}🧠 ekkOS Windsurf Hooks Installer (GLOBAL)${NC}"
34
- echo -e "${BLUE}📍 Installing to: $WINDSURF_DIR/${NC}"
35
- else
36
- WINDSURF_DIR="./.windsurf"
37
- echo -e "${BLUE}🧠 ekkOS Windsurf Hooks Installer (Project-level)${NC}"
38
- fi
39
-
40
- echo "═══════════════════════════════════════════════════════════════════"
41
-
42
- # Check if running in a project (only for local install)
43
- if [ "$GLOBAL_INSTALL" = false ]; then
44
- if [ ! -d ".git" ] && [ ! -f "package.json" ] && [ ! -f "Cargo.toml" ] && [ ! -f "pyproject.toml" ]; then
45
- echo -e "${YELLOW}⚠️ Warning: No project files detected. Make sure you're in a project root.${NC}"
46
- read -p "Continue anyway? (y/N) " -n 1 -r
47
- echo
48
- if [[ ! $REPLY =~ ^[Yy]$ ]]; then
49
- exit 1
50
- fi
51
- fi
52
- fi
53
-
54
- # Check for jq
55
- if ! command -v jq &> /dev/null; then
56
- echo -e "${RED}❌ jq is required but not installed.${NC}"
57
- echo " Install with: brew install jq (macOS) or apt-get install jq (Linux)"
58
- exit 1
59
- fi
60
-
61
- # Check for curl
62
- if ! command -v curl &> /dev/null; then
63
- echo -e "${RED}❌ curl is required but not installed.${NC}"
64
- exit 1
65
- fi
66
-
67
- # Create .windsurf directory
68
- echo -e "${BLUE}📁 Creating .windsurf directory...${NC}"
69
- mkdir -p "$WINDSURF_DIR/hooks/lib"
70
-
71
- # Copy hook files
72
- echo -e "${BLUE}📄 Copying hook files...${NC}"
73
- cp "$SCRIPT_DIR/hooks.json" "$WINDSURF_DIR/hooks.json"
74
- cp "$SCRIPT_DIR/pre-user-prompt.sh" "$WINDSURF_DIR/hooks/"
75
- cp "$SCRIPT_DIR/post-cascade-response.sh" "$WINDSURF_DIR/hooks/"
76
- cp "$SCRIPT_DIR/lib/contract.sh" "$WINDSURF_DIR/hooks/lib/"
77
-
78
- # Make scripts executable
79
- echo -e "${BLUE}🔧 Setting permissions...${NC}"
80
- chmod +x "$WINDSURF_DIR/hooks/"*.sh
81
- chmod +x "$WINDSURF_DIR/hooks/lib/"*.sh
82
-
83
- # Check for ekkOS auth
84
- echo -e "${BLUE}🔐 Checking ekkOS authentication...${NC}"
85
- EKKOS_CONFIG="$HOME/.ekkos/config.json"
86
-
87
- if [ -f "$EKKOS_CONFIG" ]; then
88
- if jq -e '.hookApiKey // .apiKey' "$EKKOS_CONFIG" > /dev/null 2>&1; then
89
- echo -e "${GREEN}✅ ekkOS auth found in ~/.ekkos/config.json${NC}"
90
- else
91
- echo -e "${YELLOW}⚠️ ~/.ekkos/config.json exists but no API key found${NC}"
92
- echo " Run 'ekkOS: Connect' in VS Code to authenticate"
93
- fi
94
- else
95
- echo -e "${YELLOW}⚠️ No ekkOS config found${NC}"
96
- echo " Run 'ekkOS: Connect' in VS Code to authenticate"
97
- fi
98
-
99
- # Test API connectivity
100
- echo -e "${BLUE}🌐 Testing ekkOS API connectivity...${NC}"
101
- if curl -s --connect-timeout 3 https://mcp.ekkos.dev/api/v1/gateway/health > /dev/null 2>&1; then
102
- echo -e "${GREEN}✅ ekkOS API is reachable${NC}"
103
- else
104
- echo -e "${YELLOW}⚠️ Could not reach ekkOS API (may be network issues)${NC}"
105
- fi
106
-
107
- # Summary
108
- echo ""
109
- echo -e "${GREEN}✅ Installation complete!${NC}"
110
- echo "═══════════════════════════════════════════════════════════════════"
111
- echo ""
112
-
113
- if [ "$GLOBAL_INSTALL" = true ]; then
114
- echo "📂 Installed files (GLOBAL - works in ALL projects):"
115
- echo " ~/.windsurf/hooks.json"
116
- echo " ~/.windsurf/hooks/pre-user-prompt.sh"
117
- echo " ~/.windsurf/hooks/post-cascade-response.sh"
118
- echo " ~/.windsurf/hooks/lib/contract.sh"
119
- echo ""
120
- echo "🚀 Next steps:"
121
- echo " 1. Open any project in Windsurf Cascade"
122
- echo " 2. Ask a technical question"
123
- echo " 3. You should see: '🧠 ekkOS™ Memory Substrate' header"
124
- echo ""
125
- echo "� To use in a specific project, create a symlink:"
126
- echo " ln -s ~/.windsurf ./.windsurf"
127
- else
128
- echo "📂 Installed files (Project-level):"
129
- echo " .windsurf/hooks.json"
130
- echo " .windsurf/hooks/pre-user-prompt.sh"
131
- echo " .windsurf/hooks/post-cascade-response.sh"
132
- echo " .windsurf/hooks/lib/contract.sh"
133
- echo ""
134
- echo "🚀 Next steps:"
135
- echo " 1. Open Windsurf Cascade in this project"
136
- echo " 2. Ask a technical question"
137
- echo " 3. You should see: '🧠 ekkOS™ Memory Substrate' header"
138
- echo ""
139
- # Git ignore suggestion
140
- if [ -d ".git" ]; then
141
- if ! grep -q ".windsurf/state" .gitignore 2>/dev/null; then
142
- echo -e "${YELLOW}💡 Tip: Add '.windsurf/state' to your .gitignore${NC}"
143
- fi
144
- fi
145
- fi
146
-
147
- echo ""
148
- echo "📖 For more info: cat ~/.windsurf/hooks/README.md"