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 +121 -4
- package/SKILL.md +2 -2
- package/VERSION +1 -1
- package/api/README.md +8 -8
- package/autonomy/loki +15 -2
- package/autonomy/run.sh +61 -16
- package/autonomy/sandbox.sh +1 -1
- package/autonomy/telemetry.sh +71 -0
- package/bin/postinstall.js +37 -0
- package/completions/_loki +312 -0
- package/completions/loki.bash +133 -0
- package/dashboard/__init__.py +1 -1
- package/dashboard/audit.py +57 -0
- package/dashboard/run.py +2 -2
- package/dashboard/server.py +13 -6
- package/dashboard/static/index.html +1 -1
- package/dashboard/telemetry.py +94 -0
- package/docs/INSTALLATION.md +29 -3
- package/docs/dashboard-guide.md +8 -2
- package/mcp/__init__.py +24 -0
- package/mcp/learning_collector.py +642 -0
- package/mcp/requirements.txt +1 -0
- package/mcp/resources.py +351 -0
- package/mcp/server.py +1042 -0
- package/mcp/tools.py +193 -0
- package/package.json +4 -2
- package/providers/claude.sh +1 -1
package/README.md
CHANGED
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
[](benchmarks/results/)
|
|
14
14
|
[](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.
|
|
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.
|
|
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.
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
210
|
+
curl "http://localhost:57374/api/events?sessionId=session_123"
|
|
211
211
|
|
|
212
212
|
# Filter by event types
|
|
213
|
-
curl "http://localhost:
|
|
213
|
+
curl "http://localhost:57374/api/events?types=task:completed,task:failed"
|
|
214
214
|
|
|
215
215
|
# Filter log level
|
|
216
|
-
curl "http://localhost:
|
|
216
|
+
curl "http://localhost:57374/api/events?minLevel=warn"
|
|
217
217
|
|
|
218
218
|
# Replay recent history
|
|
219
|
-
curl "http://localhost:
|
|
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 [
|
|
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 [
|
|
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
|
|
3406
|
-
|
|
3407
|
-
|
|
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
|
|
3648
|
-
|
|
3649
|
-
|
|
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 "$(
|
|
6908
|
-
load_solutions_context "$(
|
|
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 \
|
package/autonomy/sandbox.sh
CHANGED
|
@@ -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
|
|
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
|
+
}
|
package/bin/postinstall.js
CHANGED
|
@@ -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 {}
|