loki-mode 5.38.0 → 5.39.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.
package/README.md CHANGED
@@ -13,6 +13,8 @@
13
13
  [![HumanEval](https://img.shields.io/badge/HumanEval-98.17%25%20Pass%401-brightgreen)](benchmarks/results/)
14
14
  [![SWE-bench](https://img.shields.io/badge/SWE--bench-99.67%25%20Patch%20Gen-brightgreen)](benchmarks/results/)
15
15
 
16
+ **Current Version: v5.39.1**
17
+
16
18
  **[Documentation Website](https://asklokesh.github.io/loki-mode/)** | **[Architecture](https://asklokesh.github.io/loki-mode/blog/#architecture)** | **[Research](https://asklokesh.github.io/loki-mode/blog/#research)** | **[Comparisons](https://asklokesh.github.io/loki-mode/blog/#comparisons)**
17
19
 
18
20
  > **PRD → Deployed Product in Zero Human Intervention**
@@ -77,7 +79,7 @@ jobs:
77
79
  runs-on: ubuntu-latest
78
80
  steps:
79
81
  - uses: actions/checkout@v4
80
- - uses: asklokesh/loki-mode@v5
82
+ - uses: asklokesh/loki-mode@v5.38
81
83
  with:
82
84
  github_token: ${{ secrets.GITHUB_TOKEN }}
83
85
  mode: review # review, fix, or test
@@ -214,6 +216,8 @@ PRD → Research → Architecture → Development → Testing → Deployment →
214
216
  | **Stops on errors** | **Self-healing**: circuit breakers, dead letter queues, exponential backoff, automatic recovery |
215
217
  | **No visibility** into progress | **Real-time dashboard** with agent monitoring, task queues, and live status updates |
216
218
  | **"Done" when code is written** | **Never "done"**: continuous optimization, A/B testing, customer feedback loops, perpetual improvement |
219
+ | **No security controls** | **Enterprise-ready**: TLS/HTTPS, OIDC/SSO, RBAC, audit trails, SIEM integration, Prometheus metrics (v5.36.0-v5.38.0) |
220
+ | **Direct commits to main** | **Branch protection**: auto-create feature branches, clean PR workflow, never touches main directly (v5.37.0) |
217
221
 
218
222
  ### **Core Advantages**
219
223
 
@@ -235,6 +239,14 @@ PRD → Research → Architecture → Development → Testing → Deployment →
235
239
  | **CLI (v4.1.0)** | `loki` command for start/stop/pause/status | [CLI Commands](#cli-commands-v410) |
236
240
  | **Config Files** | YAML configuration support | [autonomy/config.example.yaml](autonomy/config.example.yaml) |
237
241
  | **Dashboard** | Realtime Kanban board, agent monitoring | [Dashboard Guide](docs/dashboard-guide.md) |
242
+ | **TLS/HTTPS (v5.36.0)** | Dashboard encryption with self-signed certs | [Network Security](docs/network-security.md) |
243
+ | **OIDC/SSO (v5.36.0)** | Google, Azure AD, Okta authentication | [Authentication Guide](docs/authentication.md) |
244
+ | **RBAC (v5.37.0)** | Admin, operator, viewer, auditor roles | [Authorization Guide](docs/authorization.md) |
245
+ | **Metrics Export (v5.38.0)** | Prometheus/OpenMetrics `/metrics` endpoint | [Metrics Guide](docs/metrics.md) |
246
+ | **Branch Protection (v5.37.0)** | Auto-create feature branches for PRs | [Git Workflow](docs/git-workflow.md) |
247
+ | **Audit Trail (v5.37.0)** | Agent action logging with integrity chain | [Audit Logging](docs/audit-logging.md) |
248
+ | **SIEM Integration (v5.38.0)** | Syslog forwarding for enterprise security | [SIEM Guide](docs/siem-integration.md) |
249
+ | **OpenClaw Bridge (v5.38.0)** | Multi-agent coordination protocol | [OpenClaw Integration](docs/openclaw-integration.md) |
238
250
  | **41 Agent Types** | Engineering, Ops, Business, Data, Product, Growth, Orchestration | [Agent Definitions](references/agent-types.md) |
239
251
  | **RARV Cycle** | Reason-Act-Reflect-Verify workflow | [Core Workflow](references/core-workflow.md) |
240
252
  | **Quality Gates** | 7-gate system: guardrails, static analysis, blind review, anti-sycophancy, severity blocking, test coverage | [Quality Control](references/quality-control.md) |
@@ -248,6 +260,67 @@ PRD → Research → Architecture → Development → Testing → Deployment →
248
260
 
249
261
  ---
250
262
 
263
+ ## Enterprise Security & Compliance (v5.36.0-v5.38.0)
264
+
265
+ Loki Mode now includes production-ready security and compliance features for enterprise deployments:
266
+
267
+ ### **Authentication & Authorization**
268
+ - **TLS/HTTPS Encryption**: Self-signed certificates for dashboard encryption (v5.36.0)
269
+ - **OIDC/SSO Integration**: Support for Google, Azure AD, and Okta authentication (v5.36.0)
270
+ - **RBAC Roles**: Four-tier role system (v5.37.0)
271
+ - **Admin**: Full control, configuration changes, user management
272
+ - **Operator**: Start/stop sessions, modify tasks, execute actions
273
+ - **Viewer**: Read-only dashboard access, view logs and metrics
274
+ - **Auditor**: Access audit logs, compliance reports, security events
275
+
276
+ ### **Observability & Monitoring**
277
+ - **Prometheus/OpenMetrics**: `/metrics` endpoint for production monitoring (v5.38.0)
278
+ - Task completion rates, agent performance, memory usage
279
+ - Integration with Grafana, Datadog, New Relic
280
+ - **Audit Trail**: SHA-256 integrity chain for all agent actions (v5.37.0)
281
+ - Tamper-evident logging with cryptographic verification
282
+ - Complete action history: who did what, when, and why
283
+ - **SIEM Integration**: Syslog forwarding (RFC 5424) for enterprise security (v5.38.0)
284
+ - Send logs to Splunk, QRadar, ArcSight, Elastic SIEM
285
+ - Real-time security event detection and alerting
286
+
287
+ ### **Development Safety**
288
+ - **Branch Protection**: Auto-create feature branches for all PR work (v5.37.0)
289
+ - Never commits directly to main/master
290
+ - Automatic branch naming: `loki/feature/<task-id>`
291
+ - Clean merge workflow with squash commits
292
+ - **OpenClaw Bridge**: Multi-agent coordination protocol integration (v5.38.0)
293
+ - Standardized inter-agent communication
294
+ - Cross-system orchestration support
295
+
296
+ ### **Quick Start (Enterprise Mode)**
297
+
298
+ ```bash
299
+ # Enable TLS/HTTPS
300
+ export LOKI_TLS_ENABLED=true
301
+ export LOKI_TLS_CERT=/path/to/cert.pem
302
+ export LOKI_TLS_KEY=/path/to/key.pem
303
+
304
+ # Configure OIDC
305
+ export LOKI_OIDC_PROVIDER=google
306
+ export LOKI_OIDC_CLIENT_ID=your-client-id
307
+ export LOKI_OIDC_CLIENT_SECRET=your-client-secret
308
+
309
+ # Enable audit logging
310
+ export LOKI_AUDIT_ENABLED=true
311
+ export LOKI_AUDIT_INTEGRITY_CHECK=true
312
+
313
+ # Enable Prometheus metrics
314
+ export LOKI_METRICS_ENABLED=true
315
+
316
+ # Start with enterprise features
317
+ loki start --enterprise ./my-prd.md
318
+ ```
319
+
320
+ For detailed configuration, see [docs/network-security.md](docs/network-security.md), [docs/authentication.md](docs/authentication.md), and [docs/authorization.md](docs/authorization.md).
321
+
322
+ ---
323
+
251
324
  ## Dashboard & Real-Time Monitoring
252
325
 
253
326
  Monitor your autonomous startup being built in real-time through the Loki Mode dashboard:
@@ -309,9 +382,11 @@ Last Updated: 2026-01-04 20:45:32
309
382
 
310
383
  # Or open manually
311
384
  open http://localhost:57374
385
+ # HTTPS mode (v5.36.0+):
386
+ open https://localhost:57374
312
387
  ```
313
388
 
314
- The dashboard at `http://localhost:57374` auto-refreshes via WebSocket. Works with any modern browser.
389
+ The dashboard at `http://localhost:57374` (or `https://localhost:57374` with TLS enabled) auto-refreshes via WebSocket. Works with any modern browser.
315
390
 
316
391
  ---
317
392
 
@@ -464,18 +539,23 @@ graph TB
464
539
  PROVIDERS --> AGENTS
465
540
 
466
541
  subgraph INFRA["Infrastructure"]
467
- DASHBOARD["Dashboard<br/>(FastAPI + Web UI)"]
542
+ DASHBOARD["Dashboard<br/>(FastAPI + Web UI)<br/>TLS/HTTPS, OIDC, RBAC"]
468
543
  MEMORY["Memory System<br/>(Episodic/Semantic/Procedural)"]
469
544
  COUNCIL["Completion Council<br/>(3-member voting)"]
470
545
  QUEUE["Task Queue<br/>(.loki/queue/)"]
546
+ METRICS["Metrics Export<br/>(Prometheus/OpenMetrics)"]
547
+ AUDIT["Audit Trail<br/>(SHA-256 integrity chain)"]
471
548
  end
472
549
 
473
550
  AGENTS --> QUEUE
474
551
  VERIFY --> COUNCIL
475
552
  REFLECT --> MEMORY
476
553
  COMPOUND --> MEMORY
554
+ AGENTS --> AUDIT
477
555
  DASHBOARD -.->|"reads"| QUEUE
478
556
  DASHBOARD -.->|"reads"| MEMORY
557
+ DASHBOARD -.->|"reads"| AUDIT
558
+ DASHBOARD -.->|"exposes"| METRICS
479
559
  ```
480
560
 
481
561
  **Key components:**
@@ -484,7 +564,9 @@ graph TB
484
564
  - **Agent Swarms** -- 41 specialized agent types across 7 swarms, spawned on demand based on project complexity.
485
565
  - **Completion Council** -- 3 members vote on whether the project is done. Anti-sycophancy devil's advocate on unanimous votes.
486
566
  - **Memory System** -- Episodic traces, semantic patterns, procedural skills. Progressive disclosure reduces context usage by 60-80%.
487
- - **Dashboard** -- FastAPI server reading `.loki/` flat files, with real-time web UI for task queue, agents, logs, and council state.
567
+ - **Dashboard** -- FastAPI server reading `.loki/` flat files, with real-time web UI for task queue, agents, logs, and council state. Now with TLS/HTTPS, OIDC/SSO, and RBAC (v5.36.0-v5.37.0).
568
+ - **Metrics Export** -- Prometheus/OpenMetrics endpoint for production monitoring (v5.38.0).
569
+ - **Audit Trail** -- SHA-256 integrity chain for tamper-evident logging of all agent actions (v5.37.0).
488
570
 
489
571
  ---
490
572
 
@@ -503,6 +585,10 @@ The `loki` CLI provides easy access to all Loki Mode features:
503
585
  | `loki import` | Import GitHub issues as tasks |
504
586
  | `loki config show` | Show configuration |
505
587
  | `loki config init` | Create config file from template |
588
+ | `loki audit logs` | View audit trail (v5.37.0) |
589
+ | `loki audit verify` | Verify log integrity chain (v5.37.0) |
590
+ | `loki metrics` | Display Prometheus metrics (v5.38.0) |
591
+ | `loki syslog test` | Test SIEM integration (v5.38.0) |
506
592
  | `loki version` | Show version |
507
593
 
508
594
  ### Configuration File
@@ -622,6 +708,9 @@ IMPLEMENT → REVIEW (parallel) → AGGREGATE → FIX → RE-REVIEW → COMPLETE
622
708
  ├── metrics/ # Efficiency tracking and reward signals
623
709
  ├── messages/ # Inter-agent communication
624
710
  ├── logs/ # Audit logs
711
+ ├── audit/ # Audit trail with SHA-256 integrity chain (v5.37.0)
712
+ ├── security/ # TLS certificates, OIDC configs (v5.36.0)
713
+ ├── rbac/ # Role definitions and permissions (v5.37.0)
625
714
  ├── config/ # Configuration files
626
715
  ├── prompts/ # Agent role prompts
627
716
  ├── artifacts/ # Releases, reports, backups
@@ -710,6 +799,13 @@ LOKI_MAX_WAIT=7200 \
710
799
  | `LOKI_BASE_WAIT` | 60 | Base wait time in seconds |
711
800
  | `LOKI_MAX_WAIT` | 3600 | Maximum wait time (1 hour) |
712
801
  | `LOKI_SKIP_PREREQS` | false | Skip prerequisite checks |
802
+ | `LOKI_TLS_ENABLED` | false | Enable HTTPS/TLS for dashboard (v5.36.0) |
803
+ | `LOKI_OIDC_PROVIDER` | - | OIDC provider: google, azure, okta (v5.36.0) |
804
+ | `LOKI_RBAC_ENABLED` | false | Enable role-based access control (v5.37.0) |
805
+ | `LOKI_AUDIT_ENABLED` | false | Enable audit logging with integrity chain (v5.37.0) |
806
+ | `LOKI_METRICS_ENABLED` | false | Enable Prometheus /metrics endpoint (v5.38.0) |
807
+ | `LOKI_SYSLOG_ENABLED` | false | Enable syslog forwarding to SIEM (v5.38.0) |
808
+ | `LOKI_BRANCH_PROTECTION` | true | Auto-create feature branches (v5.37.0) |
713
809
 
714
810
  ### **Circuit Breakers**
715
811
 
@@ -779,6 +875,27 @@ npx vibe-kanban
779
875
 
780
876
  See [integrations/vibe-kanban.md](integrations/vibe-kanban.md) for complete step-by-step setup guide and troubleshooting.
781
877
 
878
+ ### **OpenClaw Bridge (v5.38.0)**
879
+
880
+ Loki Mode now supports the OpenClaw multi-agent coordination protocol for cross-system orchestration:
881
+
882
+ ```bash
883
+ # Enable OpenClaw bridge
884
+ export LOKI_OPENCLAW_ENABLED=true
885
+ export LOKI_OPENCLAW_ENDPOINT=http://openclaw-server:8080
886
+
887
+ # Start with OpenClaw integration
888
+ loki start --openclaw ./prd.md
889
+ ```
890
+
891
+ **Benefits:**
892
+ - Standardized inter-agent communication across different AI systems
893
+ - Coordinate with external agent frameworks (AutoGPT, MetaGPT, etc.)
894
+ - Share task queues and state between multiple orchestrators
895
+ - Cross-platform agent collaboration
896
+
897
+ See [docs/openclaw-integration.md](docs/openclaw-integration.md) for complete setup and API reference.
898
+
782
899
  ---
783
900
 
784
901
  ## Testing
package/SKILL.md CHANGED
@@ -3,7 +3,7 @@ name: loki-mode
3
3
  description: Multi-agent autonomous startup system. Triggers on "Loki Mode". Takes PRD to deployed product with zero human intervention. Requires --dangerously-skip-permissions flag.
4
4
  ---
5
5
 
6
- # Loki Mode v5.38.0
6
+ # Loki Mode v5.39.1
7
7
 
8
8
  **You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
9
9
 
@@ -260,4 +260,4 @@ The following features are documented in skill modules but not yet fully automat
260
260
  | Quality gates 3-reviewer system | Implemented (v5.35.0) | 5 specialist reviewers in `skills/quality-gates.md`; execution in run.sh |
261
261
  | Benchmarks (HumanEval, SWE-bench) | Infrastructure only | Runner scripts and datasets exist in `benchmarks/`; no published results |
262
262
 
263
- **v5.38.0 | feat: branch protection, prometheus metrics, log integrity, OpenClaw bridge | ~260 lines core**
263
+ **v5.39.1 | fix: 46-bug audit across all distributions, JSON injection, Docker mounts, auth hardening | ~260 lines core**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 5.38.0
1
+ 5.39.1
package/api/README.md CHANGED
@@ -62,7 +62,7 @@ export LOKI_API_TOKEN=$(loki serve --generate-token)
62
62
  loki serve --host 0.0.0.0
63
63
 
64
64
  # Connect from another machine
65
- curl -H "Authorization: Bearer $LOKI_API_TOKEN" http://server:8420/health
65
+ curl -H "Authorization: Bearer $LOKI_API_TOKEN" http://server:57374/health
66
66
  ```
67
67
 
68
68
  ## API Endpoints
@@ -148,7 +148,7 @@ curl -H "Authorization: Bearer $LOKI_API_TOKEN" http://server:8420/health
148
148
  ### Start a Session
149
149
 
150
150
  ```bash
151
- curl -X POST http://localhost:8420/api/sessions \
151
+ curl -X POST http://localhost:57374/api/sessions \
152
152
  -H "Content-Type: application/json" \
153
153
  -d '{"provider": "claude", "prdPath": "./docs/prd.md"}'
154
154
  ```
@@ -156,7 +156,7 @@ curl -X POST http://localhost:8420/api/sessions \
156
156
  ### Subscribe to Events
157
157
 
158
158
  ```javascript
159
- const events = new EventSource('http://localhost:8420/api/events');
159
+ const events = new EventSource('http://localhost:57374/api/events');
160
160
 
161
161
  events.addEventListener('task:completed', (e) => {
162
162
  const event = JSON.parse(e.data);
@@ -178,7 +178,7 @@ events.onerror = (err) => {
178
178
  ```typescript
179
179
  import { LokiClient } from './api/client.ts';
180
180
 
181
- const client = new LokiClient('http://localhost:8420');
181
+ const client = new LokiClient('http://localhost:57374');
182
182
 
183
183
  // Start a session
184
184
  const { sessionId } = await client.startSession({
@@ -207,16 +207,16 @@ client.close();
207
207
 
208
208
  ```bash
209
209
  # Filter by session
210
- curl "http://localhost:8420/api/events?sessionId=session_123"
210
+ curl "http://localhost:57374/api/events?sessionId=session_123"
211
211
 
212
212
  # Filter by event types
213
- curl "http://localhost:8420/api/events?types=task:completed,task:failed"
213
+ curl "http://localhost:57374/api/events?types=task:completed,task:failed"
214
214
 
215
215
  # Filter log level
216
- curl "http://localhost:8420/api/events?minLevel=warn"
216
+ curl "http://localhost:57374/api/events?minLevel=warn"
217
217
 
218
218
  # Replay recent history
219
- curl "http://localhost:8420/api/events?history=50"
219
+ curl "http://localhost:57374/api/events?history=50"
220
220
  ```
221
221
 
222
222
  ## Development
package/autonomy/loki CHANGED
@@ -112,6 +112,13 @@ EMIT_SH="$SKILL_DIR/events/emit.sh"
112
112
  LEARNING_EMIT_SH="$SKILL_DIR/learning/emit.sh"
113
113
  LOKI_DIR=".loki"
114
114
 
115
+ # Anonymous usage telemetry
116
+ PROJECT_DIR="$SKILL_DIR"
117
+ _TELEMETRY_SCRIPT="$SKILL_DIR/autonomy/telemetry.sh"
118
+ if [ -f "$_TELEMETRY_SCRIPT" ]; then
119
+ source "$_TELEMETRY_SCRIPT"
120
+ fi
121
+
115
122
  # Get version from VERSION file
116
123
  get_version() {
117
124
  if [ -f "$SKILL_DIR/VERSION" ]; then
@@ -321,6 +328,10 @@ show_help() {
321
328
  echo " memory [cmd] Cross-project learnings (list|show|search|stats)"
322
329
  echo " compound [cmd] Knowledge compounding (list|show|search|run|stats)"
323
330
  echo " council [cmd] Completion council (status|verdicts|convergence|force-review|report)"
331
+ echo " checkpoint|cp Save/restore session checkpoints"
332
+ echo " projects Multi-project registry management"
333
+ echo " audit Agent action audit log"
334
+ echo " enterprise Enterprise feature management (tokens, OIDC)"
324
335
  echo " metrics Prometheus/OpenMetrics metrics from dashboard"
325
336
  echo " dogfood Show self-development statistics"
326
337
  echo " secrets [cmd] API key status and validation (status|validate)"
@@ -4219,6 +4230,8 @@ main() {
4219
4230
  local command="$1"
4220
4231
  shift
4221
4232
 
4233
+ loki_telemetry "cli_command" "command=$command" 2>/dev/null || true
4234
+
4222
4235
  case "$command" in
4223
4236
  start)
4224
4237
  cmd_start "$@"
@@ -7079,8 +7092,8 @@ cmd_metrics() {
7079
7092
  # Fetch metrics from dashboard
7080
7093
  local url="http://${host}:${port}/metrics"
7081
7094
  local response
7082
- response=$(curl -sf "$url" 2>/dev/null)
7083
- if [ $? -ne 0 ]; then
7095
+ response=$(curl -sf "$url" 2>/dev/null) || true
7096
+ if [ -z "$response" ]; then
7084
7097
  echo -e "${RED}Error: Could not connect to dashboard at ${url}${NC}"
7085
7098
  echo "Make sure the dashboard is running: loki serve"
7086
7099
  exit 1
package/autonomy/run.sh CHANGED
@@ -534,6 +534,13 @@ if [ -f "$COUNCIL_SCRIPT" ]; then
534
534
  source "$COUNCIL_SCRIPT"
535
535
  fi
536
536
 
537
+ # Anonymous usage telemetry (opt-out: LOKI_TELEMETRY_DISABLED=true or DO_NOT_TRACK=1)
538
+ TELEMETRY_SCRIPT="$SCRIPT_DIR/telemetry.sh"
539
+ if [ -f "$TELEMETRY_SCRIPT" ]; then
540
+ # shellcheck source=telemetry.sh
541
+ source "$TELEMETRY_SCRIPT"
542
+ fi
543
+
537
544
  # 2026 Research Enhancements (minimal additions)
538
545
  PROMPT_REPETITION=${LOKI_PROMPT_REPETITION:-true}
539
546
  CONFIDENCE_ROUTING=${LOKI_CONFIDENCE_ROUTING:-true}
@@ -777,8 +784,14 @@ get_iteration_duration_ms() {
777
784
 
778
785
  validate_api_keys() {
779
786
  local provider="${LOKI_PROVIDER:-claude}"
780
- local key_var=""
781
787
 
788
+ # CLI tools (claude, codex, gemini) use their own login sessions.
789
+ # Only require API keys inside Docker/K8s where CLI login isn't available.
790
+ if [[ ! -f "/.dockerenv" ]] && [[ -z "${KUBERNETES_SERVICE_HOST:-}" ]]; then
791
+ return 0
792
+ fi
793
+
794
+ local key_var=""
782
795
  case "$provider" in
783
796
  claude) key_var="ANTHROPIC_API_KEY" ;;
784
797
  codex) key_var="OPENAI_API_KEY" ;;
@@ -1542,17 +1555,18 @@ create_worktree() {
1542
1555
 
1543
1556
  log_step "Creating worktree: $stream_name"
1544
1557
 
1558
+ local wt_exit=1
1545
1559
  if [ -n "$branch_name" ]; then
1546
1560
  # Create new branch
1547
- git -C "$TARGET_DIR" worktree add "$worktree_path" -b "$branch_name" 2>/dev/null || \
1548
- git -C "$TARGET_DIR" worktree add "$worktree_path" "$branch_name" 2>/dev/null
1561
+ git -C "$TARGET_DIR" worktree add "$worktree_path" -b "$branch_name" 2>/dev/null && wt_exit=0 || \
1562
+ { git -C "$TARGET_DIR" worktree add "$worktree_path" "$branch_name" 2>/dev/null && wt_exit=0; }
1549
1563
  else
1550
1564
  # Track main branch
1551
- git -C "$TARGET_DIR" worktree add "$worktree_path" main 2>/dev/null || \
1552
- git -C "$TARGET_DIR" worktree add "$worktree_path" HEAD 2>/dev/null
1565
+ git -C "$TARGET_DIR" worktree add "$worktree_path" main 2>/dev/null && wt_exit=0 || \
1566
+ { git -C "$TARGET_DIR" worktree add "$worktree_path" HEAD 2>/dev/null && wt_exit=0; }
1553
1567
  fi
1554
1568
 
1555
- if [ $? -eq 0 ]; then
1569
+ if [ $wt_exit -eq 0 ]; then
1556
1570
  WORKTREE_PATHS[$stream_name]="$worktree_path"
1557
1571
 
1558
1572
  # Copy .loki state to worktree
@@ -2180,6 +2194,11 @@ EOF
2180
2194
 
2181
2195
  # Write budget.json if a budget limit is configured
2182
2196
  if [ -n "$BUDGET_LIMIT" ]; then
2197
+ # Validate budget limit is numeric before writing JSON
2198
+ if ! echo "$BUDGET_LIMIT" | grep -qE '^[0-9]+(\.[0-9]+)?$'; then
2199
+ log_warn "Invalid BUDGET_LIMIT '$BUDGET_LIMIT', defaulting to 0"
2200
+ BUDGET_LIMIT=0
2201
+ fi
2183
2202
  cat > ".loki/metrics/budget.json" << BUDGET_EOF
2184
2203
  {
2185
2204
  "limit": $BUDGET_LIMIT,
@@ -3402,10 +3421,15 @@ audit_log() {
3402
3421
 
3403
3422
  mkdir -p .loki/logs
3404
3423
 
3405
- local log_entry=$(cat << EOF
3406
- {"timestamp":"$(date -u +%Y-%m-%dT%H:%M:%SZ)","event":"$event_type","data":"$event_data","user":"$(whoami)","pid":$$}
3407
- EOF
3408
- )
3424
+ local log_entry
3425
+ if command -v jq >/dev/null 2>&1; then
3426
+ log_entry=$(jq -n --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" --arg evt "$event_type" --arg data "$event_data" --arg user "$(whoami)" --argjson pid "$$" '{timestamp:$ts,event:$evt,data:$data,user:$user,pid:$pid}')
3427
+ else
3428
+ local safe_type safe_data
3429
+ safe_type=$(printf '%s' "$event_type" | sed 's/["\\]/\\&/g; s/\n/\\n/g')
3430
+ safe_data=$(printf '%s' "$event_data" | sed 's/["\\]/\\&/g; s/\n/\\n/g')
3431
+ log_entry="{\"timestamp\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"event\":\"$safe_type\",\"data\":\"$safe_data\",\"user\":\"$(whoami)\",\"pid\":$$}"
3432
+ fi
3409
3433
  echo "$log_entry" >> "$audit_file"
3410
3434
  }
3411
3435
 
@@ -3644,10 +3668,16 @@ save_learning() {
3644
3668
  init_learnings_db
3645
3669
  fi
3646
3670
 
3647
- local learning_entry=$(cat << EOF
3648
- {"timestamp":"$(date -u +%Y-%m-%dT%H:%M:%SZ)","project":"$project","category":"$category","description":"$description"}
3649
- EOF
3650
- )
3671
+ local learning_entry
3672
+ if command -v jq >/dev/null 2>&1; then
3673
+ learning_entry=$(jq -n --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" --arg proj "$project" --arg cat "$category" --arg desc "$description" '{timestamp:$ts,project:$proj,category:$cat,description:$desc}')
3674
+ else
3675
+ local safe_proj safe_cat safe_desc
3676
+ safe_proj=$(printf '%s' "$project" | sed 's/["\\]/\\&/g; s/\n/\\n/g')
3677
+ safe_cat=$(printf '%s' "$category" | sed 's/["\\]/\\&/g; s/\n/\\n/g')
3678
+ safe_desc=$(printf '%s' "$description" | sed 's/["\\]/\\&/g; s/\n/\\n/g')
3679
+ learning_entry="{\"timestamp\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"project\":\"$safe_proj\",\"category\":\"$safe_cat\",\"description\":\"$safe_desc\"}"
3680
+ fi
3651
3681
  echo "$learning_entry" >> "$target_file"
3652
3682
  log_info "Saved $learning_type: $category"
3653
3683
  }
@@ -6653,6 +6683,7 @@ except (json.JSONDecodeError, OSError): pass
6653
6683
 
6654
6684
  main() {
6655
6685
  trap cleanup INT TERM
6686
+ SESSION_START_EPOCH=$(date +%s)
6656
6687
 
6657
6688
  echo ""
6658
6689
  echo -e "${BOLD}${BLUE}"
@@ -6904,8 +6935,8 @@ main() {
6904
6935
 
6905
6936
  # Load relevant learnings for this project context
6906
6937
  if [ -n "$PRD_PATH" ] && [ -f "$PRD_PATH" ]; then
6907
- get_relevant_learnings "$(cat "$PRD_PATH" | head -100)"
6908
- load_solutions_context "$(cat "$PRD_PATH" | head -100)"
6938
+ get_relevant_learnings "$(head -100 "$PRD_PATH")"
6939
+ load_solutions_context "$(head -100 "$PRD_PATH")"
6909
6940
  else
6910
6941
  get_relevant_learnings "general development"
6911
6942
  load_solutions_context "general development"
@@ -6926,6 +6957,12 @@ main() {
6926
6957
  "complexity=${DETECTED_COMPLEXITY:-standard}" \
6927
6958
  "pid=$$"
6928
6959
 
6960
+ # Anonymous usage telemetry
6961
+ loki_telemetry "session_start" \
6962
+ "provider=${PROVIDER_NAME:-claude}" \
6963
+ "complexity=${DETECTED_COMPLEXITY:-standard}" \
6964
+ "parallel=${PARALLEL_MODE:-false}" 2>/dev/null || true
6965
+
6929
6966
  # Run in appropriate mode
6930
6967
  local result=0
6931
6968
  if [ "$PARALLEL_MODE" = "true" ]; then
@@ -6985,6 +7022,14 @@ main() {
6985
7022
  "provider=${PROVIDER_NAME:-claude}" \
6986
7023
  "iterations=$ITERATION_COUNT"
6987
7024
 
7025
+ # Anonymous usage telemetry
7026
+ local session_duration=$(($(date +%s) - ${SESSION_START_EPOCH:-$(date +%s)}))
7027
+ loki_telemetry "session_end" \
7028
+ "provider=${PROVIDER_NAME:-claude}" \
7029
+ "duration=$session_duration" \
7030
+ "iterations=$ITERATION_COUNT" \
7031
+ "result=$result" 2>/dev/null || true
7032
+
6988
7033
  # Emit learning signal for session completion (SYN-018)
6989
7034
  if [ "$result" = "0" ]; then
6990
7035
  emit_learning_signal success_pattern \
@@ -45,7 +45,7 @@ PROJECT_DIR="${PROJECT_DIR%/}"
45
45
 
46
46
  # Container name includes path hash to avoid collisions between similarly-named projects
47
47
  # macOS uses md5 instead of md5sum
48
- PROJECT_HASH=$(echo "$PROJECT_DIR" | md5sum 2>/dev/null | cut -c1-8 || md5 2>/dev/null | cut -c1-8 || echo "$$")
48
+ PROJECT_HASH=$(echo "$PROJECT_DIR" | (md5sum 2>/dev/null || md5 -r 2>/dev/null || echo "$$") | cut -c1-8)
49
49
  CONTAINER_NAME="loki-sandbox-$(basename "$PROJECT_DIR" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g')-${PROJECT_HASH}"
50
50
 
51
51
  # Sandbox settings
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env bash
2
+ # Anonymous usage telemetry for Loki Mode
3
+ # Opt-out: LOKI_TELEMETRY_DISABLED=true or DO_NOT_TRACK=1
4
+ # All calls are fire-and-forget, silent on failure, non-blocking
5
+
6
+ LOKI_POSTHOG_HOST="${LOKI_TELEMETRY_ENDPOINT:-https://us.i.posthog.com}"
7
+ LOKI_POSTHOG_KEY="phc_ya0vGBru41AJWtGNfZZ8H9W4yjoZy4KON0nnayS7s87"
8
+
9
+ _loki_telemetry_enabled() {
10
+ [ "${LOKI_TELEMETRY_DISABLED:-}" = "true" ] && return 1
11
+ [ "${DO_NOT_TRACK:-}" = "1" ] && return 1
12
+ command -v curl >/dev/null 2>&1 || return 1
13
+ return 0
14
+ }
15
+
16
+ _loki_telemetry_id() {
17
+ local id_file="${HOME}/.loki-telemetry-id"
18
+ if [ -f "$id_file" ] 2>/dev/null; then
19
+ cat "$id_file" 2>/dev/null
20
+ return
21
+ fi
22
+ local new_id
23
+ new_id=$(python3 -c "import uuid; print(uuid.uuid4())" 2>/dev/null) || \
24
+ new_id=$(uuidgen 2>/dev/null | tr '[:upper:]' '[:lower:]') || \
25
+ new_id="anon-$(date +%s)-$$"
26
+ printf '%s\n' "$new_id" > "$id_file" 2>/dev/null
27
+ printf '%s' "$new_id"
28
+ }
29
+
30
+ _loki_detect_channel() {
31
+ local dir="${PROJECT_DIR:-${SKILL_DIR:-${SCRIPT_DIR:-}}}"
32
+ if [ -f "/.dockerenv" ] 2>/dev/null; then printf 'docker'; return; fi
33
+ case "$dir" in
34
+ */Cellar/*|*/homebrew/*) printf 'homebrew' ;;
35
+ */node_modules/*) printf 'npm' ;;
36
+ */.claude/skills/*) printf 'skill' ;;
37
+ *) printf 'source' ;;
38
+ esac
39
+ }
40
+
41
+ loki_telemetry() {
42
+ _loki_telemetry_enabled || return 0
43
+ local event="$1"; shift
44
+ local distinct_id props_json
45
+ distinct_id=$(_loki_telemetry_id 2>/dev/null) || return 0
46
+ local version
47
+ version=$(cat "${SCRIPT_DIR:-${SKILL_DIR:-}}/VERSION" 2>/dev/null || cat "${SCRIPT_DIR:-${SKILL_DIR:-}}/../VERSION" 2>/dev/null || echo "unknown")
48
+ version=$(echo "$version" | tr -d '[:space:]')
49
+ local channel
50
+ channel=$(_loki_detect_channel 2>/dev/null || echo "unknown")
51
+ local os_name arch
52
+ os_name=$(uname -s 2>/dev/null || echo "unknown")
53
+ arch=$(uname -m 2>/dev/null || echo "unknown")
54
+
55
+ # Build properties from remaining args (key=value pairs)
56
+ local extra_props=""
57
+ for arg in "$@"; do
58
+ local key="${arg%%=*}"
59
+ local val="${arg#*=}"
60
+ extra_props="${extra_props},\"${key}\":\"${val}\""
61
+ done
62
+
63
+ local payload
64
+ payload=$(printf '{"api_key":"%s","event":"%s","distinct_id":"%s","properties":{"os":"%s","arch":"%s","version":"%s","channel":"%s"%s}}' \
65
+ "$LOKI_POSTHOG_KEY" "$event" "$distinct_id" "$os_name" "$arch" "$version" "$channel" "$extra_props")
66
+
67
+ (curl -sS --max-time 3 -X POST "${LOKI_POSTHOG_HOST}/capture/" \
68
+ -H "Content-Type: application/json" \
69
+ -d "$payload" >/dev/null 2>&1 &) 2>/dev/null
70
+ return 0
71
+ }
@@ -89,3 +89,40 @@ console.log('Or in Claude Code:');
89
89
  console.log(' claude --dangerously-skip-permissions');
90
90
  console.log(' Then say: "Loki Mode"');
91
91
  console.log('');
92
+
93
+ // Anonymous install telemetry (fire-and-forget, silent)
94
+ try {
95
+ if (process.env.LOKI_TELEMETRY_DISABLED !== 'true' && process.env.DO_NOT_TRACK !== '1') {
96
+ const https = require('https');
97
+ const crypto = require('crypto');
98
+ const idFile = path.join(homeDir, '.loki-telemetry-id');
99
+ let distinctId;
100
+ try {
101
+ distinctId = fs.readFileSync(idFile, 'utf8').trim();
102
+ } catch {
103
+ distinctId = crypto.randomUUID();
104
+ try { fs.writeFileSync(idFile, distinctId + '\n'); } catch {}
105
+ }
106
+ const payload = JSON.stringify({
107
+ api_key: 'phc_ya0vGBru41AJWtGNfZZ8H9W4yjoZy4KON0nnayS7s87',
108
+ event: 'install',
109
+ distinct_id: distinctId,
110
+ properties: {
111
+ os: os.platform(),
112
+ arch: os.arch(),
113
+ version: version,
114
+ channel: 'npm',
115
+ node_version: process.version,
116
+ },
117
+ });
118
+ const req = https.request({
119
+ hostname: 'us.i.posthog.com',
120
+ path: '/capture/',
121
+ method: 'POST',
122
+ headers: { 'Content-Type': 'application/json', 'Content-Length': payload.length },
123
+ timeout: 3000,
124
+ });
125
+ req.on('error', () => {});
126
+ req.end(payload);
127
+ }
128
+ } catch {}