@contextstream/mcp-server 0.4.57 → 0.4.59
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/hooks/auto-rules.js +72 -45
- package/dist/hooks/pre-tool-use.js +4 -4
- package/dist/hooks/runner.js +150 -114
- package/dist/hooks/session-init.js +1037 -1
- package/dist/hooks/user-prompt-submit.js +73 -64
- package/dist/index.js +15320 -14913
- package/dist/test-server.js +1 -1
- package/package.json +1 -1
|
@@ -50,7 +50,7 @@ function compareVersions(v1, v2) {
|
|
|
50
50
|
}
|
|
51
51
|
return 0;
|
|
52
52
|
}
|
|
53
|
-
var CACHE_TTL_MS =
|
|
53
|
+
var CACHE_TTL_MS = 12 * 60 * 60 * 1e3;
|
|
54
54
|
var latestVersionPromise = null;
|
|
55
55
|
function getCacheFilePath() {
|
|
56
56
|
return join(homedir(), ".contextstream", "version-cache.json");
|
|
@@ -331,6 +331,1013 @@ function clearUpdateMarker() {
|
|
|
331
331
|
}
|
|
332
332
|
}
|
|
333
333
|
|
|
334
|
+
// src/rules-templates.ts
|
|
335
|
+
var DEFAULT_CLAUDE_MCP_SERVER_NAME = "contextstream";
|
|
336
|
+
var RULES_VERSION = VERSION === "unknown" ? "0.0.0" : VERSION;
|
|
337
|
+
var CONTEXTSTREAM_TOOL_NAMES = [
|
|
338
|
+
// Standalone tools (always present)
|
|
339
|
+
"init",
|
|
340
|
+
// Renamed from session_init - initialize conversation session
|
|
341
|
+
"context",
|
|
342
|
+
// Renamed from context_smart - get relevant context every message
|
|
343
|
+
"context_feedback",
|
|
344
|
+
"generate_rules",
|
|
345
|
+
// Consolidated domain tools (v0.4.x default)
|
|
346
|
+
"search",
|
|
347
|
+
// Modes: auto (recommended), semantic, hybrid (legacy alias), keyword, pattern
|
|
348
|
+
"session",
|
|
349
|
+
// Actions: capture, capture_lesson, get_lessons, recall, remember, user_context, summary, compress, delta, smart_search, decision_trace
|
|
350
|
+
"memory",
|
|
351
|
+
// Actions: create_event, get_event, update_event, delete_event, list_events, distill_event, create_node, get_node, update_node, delete_node, list_nodes, supersede_node, search, decisions, timeline, summary
|
|
352
|
+
"graph",
|
|
353
|
+
// Actions: dependencies, impact, call_path, related, path, decisions, ingest, circular_dependencies, unused_code, contradictions
|
|
354
|
+
"project",
|
|
355
|
+
// Actions: list, get, create, update, index, overview, statistics, files, index_status, ingest_local
|
|
356
|
+
"workspace",
|
|
357
|
+
// Actions: list, get, associate, bootstrap
|
|
358
|
+
"reminder",
|
|
359
|
+
// Actions: list, active, create, snooze, complete, dismiss
|
|
360
|
+
"integration",
|
|
361
|
+
// Provider: slack, github, all; Actions: status, search, stats, activity, contributors, knowledge, summary, channels, discussions, sync_users, repos, issues
|
|
362
|
+
"help"
|
|
363
|
+
// Actions: tools, auth, version, editor_rules, enable_bundle
|
|
364
|
+
];
|
|
365
|
+
function applyMcpToolPrefix(markdown, toolPrefix) {
|
|
366
|
+
const toolPattern = CONTEXTSTREAM_TOOL_NAMES.join("|");
|
|
367
|
+
const toolRegex = new RegExp(`(?<!__)\\b(${toolPattern})\\b(?=\\s*\\()`, "g");
|
|
368
|
+
return markdown.replace(toolRegex, `${toolPrefix}$1`);
|
|
369
|
+
}
|
|
370
|
+
var CONTEXTSTREAM_RULES_BOOTSTRAP = `
|
|
371
|
+
<contextstream_rules>
|
|
372
|
+
| Message | Required |
|
|
373
|
+
|---------|----------|
|
|
374
|
+
| **1st message** | \`init()\` \u2192 \`context(user_message="...")\` |
|
|
375
|
+
| **Every message** | \`context(user_message="...")\` FIRST |
|
|
376
|
+
| **Before file search** | \`search(mode="auto")\` BEFORE Glob/Grep/Read |
|
|
377
|
+
</contextstream_rules>
|
|
378
|
+
|
|
379
|
+
**Why?** \`context()\` delivers task-specific rules, lessons from past mistakes, and relevant decisions. Skip it = fly blind.
|
|
380
|
+
|
|
381
|
+
**Hooks:** \`<system-reminder>\` tags contain injected instructions \u2014 follow them exactly.
|
|
382
|
+
|
|
383
|
+
**Notices:** [LESSONS_WARNING] \u2192 apply lessons | [PREFERENCE] \u2192 follow user preferences | [RULES_NOTICE] \u2192 run \`generate_rules()\` | [VERSION_NOTICE/CRITICAL] \u2192 tell user about update
|
|
384
|
+
|
|
385
|
+
v${RULES_VERSION}
|
|
386
|
+
`.trim();
|
|
387
|
+
var CONTEXTSTREAM_RULES_DYNAMIC = CONTEXTSTREAM_RULES_BOOTSTRAP;
|
|
388
|
+
var CONTEXTSTREAM_RULES_FULL = `
|
|
389
|
+
## \u{1F6A8} MANDATORY: CALL CONTEXT EVERY MESSAGE \u{1F6A8}
|
|
390
|
+
|
|
391
|
+
<contextstream_rules>
|
|
392
|
+
**EVERY response MUST start with \`context(user_message="...")\`**
|
|
393
|
+
|
|
394
|
+
| Message | What to Call |
|
|
395
|
+
|---------|--------------|
|
|
396
|
+
| 1st message | \`init()\` \u2192 \`context(user_message="<msg>")\` |
|
|
397
|
+
| **EVERY message after** | \`context(user_message="<msg>")\` **FIRST** |
|
|
398
|
+
|
|
399
|
+
**BEFORE Glob/Grep/Read/Search:** \u2192 \`search(mode="auto")\` FIRST
|
|
400
|
+
</contextstream_rules>
|
|
401
|
+
|
|
402
|
+
**This block MUST appear at the start of EVERY response.** Failing to call \`context()\` means missing rules, lessons, and relevant context.
|
|
403
|
+
|
|
404
|
+
---
|
|
405
|
+
|
|
406
|
+
## Why \`context()\` is MANDATORY Every Message
|
|
407
|
+
|
|
408
|
+
\u274C **WRONG:** "I already called init, I don't need context"
|
|
409
|
+
\u2705 **CORRECT:** \`context()\` is required EVERY message, not just the first
|
|
410
|
+
|
|
411
|
+
**What you lose without \`context()\`:**
|
|
412
|
+
- Dynamic rules matched to your current task
|
|
413
|
+
- Lessons from past mistakes (you WILL repeat them)
|
|
414
|
+
- Semantically relevant decisions and context
|
|
415
|
+
- Warnings about risky operations
|
|
416
|
+
|
|
417
|
+
**\`init()\` gives recent items by TIME. \`context()\` finds items RELEVANT to THIS message.**
|
|
418
|
+
|
|
419
|
+
---
|
|
420
|
+
|
|
421
|
+
## Handle Notices from context()
|
|
422
|
+
|
|
423
|
+
- **[LESSONS_WARNING]** \u2192 Tell user about past mistakes BEFORE proceeding
|
|
424
|
+
- **[PREFERENCE]** \u2192 Follow user preferences (high-priority user memories)
|
|
425
|
+
- **[RULES_NOTICE]** \u2192 Run \`generate_rules()\` to update
|
|
426
|
+
- **[VERSION_NOTICE]** \u2192 Tell user to update MCP
|
|
427
|
+
|
|
428
|
+
---
|
|
429
|
+
|
|
430
|
+
## \u{1F6A8} HOOKS - AUTOMATIC RULE ENFORCEMENT \u{1F6A8}
|
|
431
|
+
|
|
432
|
+
**ContextStream installs hooks that automatically enforce rules.** You MUST follow hook output.
|
|
433
|
+
|
|
434
|
+
### Installed Hooks
|
|
435
|
+
|
|
436
|
+
| Hook | What It Does | Output |
|
|
437
|
+
|------|--------------|--------|
|
|
438
|
+
| **UserPromptSubmit** | Injects rules reminder on EVERY message | \`<system-reminder>\` with rules block |
|
|
439
|
+
| **PreToolUse** | Blocks Glob/Grep/Search/Explore when ContextStream is available | Error message redirecting to \`search()\` |
|
|
440
|
+
| **PostToolUse** | Auto-indexes files after Edit/Write operations | Background indexing |
|
|
441
|
+
| **PreCompact** | Saves session state before context compaction | Snapshot creation |
|
|
442
|
+
|
|
443
|
+
### How Hooks Work
|
|
444
|
+
|
|
445
|
+
1. **\`<system-reminder>\` tags** - Injected by UserPromptSubmit hook on every message
|
|
446
|
+
- These tags contain the current rules
|
|
447
|
+
- **FOLLOW THE INSTRUCTIONS INSIDE** - they ARE the rules
|
|
448
|
+
- Example: \`[CONTEXTSTREAM RULES] 1. BEFORE Glob/Grep... [END RULES]\`
|
|
449
|
+
|
|
450
|
+
2. **PreToolUse blocking** - If you try to use Glob/Grep/Search/Explore:
|
|
451
|
+
- Hook returns error: \`STOP: Use mcp__contextstream__search(mode="auto") instead\`
|
|
452
|
+
- **You MUST use the suggested ContextStream tool instead**
|
|
453
|
+
- Local tools are only allowed if project is not indexed or ContextStream returns 0 results
|
|
454
|
+
|
|
455
|
+
3. **PostToolUse indexing** - After Edit/Write operations:
|
|
456
|
+
- Changed files are automatically re-indexed
|
|
457
|
+
- No action required from you
|
|
458
|
+
|
|
459
|
+
4. **PreCompact snapshots** - Before context compaction:
|
|
460
|
+
- Hook reminds you to save important state
|
|
461
|
+
- Call \`session(action="capture", event_type="session_snapshot", ...)\` when warned
|
|
462
|
+
|
|
463
|
+
### Disabling Hooks
|
|
464
|
+
|
|
465
|
+
Set environment variable: \`CONTEXTSTREAM_HOOK_ENABLED=false\`
|
|
466
|
+
|
|
467
|
+
**Note:** Disabling hooks removes rule enforcement. Only disable for debugging.
|
|
468
|
+
|
|
469
|
+
---
|
|
470
|
+
|
|
471
|
+
## \u{1F6A8} CRITICAL RULE #1 - CONTEXTSTREAM SEARCH FIRST \u{1F6A8}
|
|
472
|
+
|
|
473
|
+
**BEFORE using Glob, Grep, Search, Read (for discovery), Explore, or ANY local file scanning:**
|
|
474
|
+
\`\`\`
|
|
475
|
+
STOP \u2192 Call search(mode="auto", query="...") FIRST
|
|
476
|
+
\`\`\`
|
|
477
|
+
|
|
478
|
+
**Note:** PreToolUse hooks block these tools when ContextStream is available.
|
|
479
|
+
**Claude Code users:** Your tool names are \`mcp__contextstream__search\`, \`mcp__contextstream__init\`, etc.
|
|
480
|
+
|
|
481
|
+
\u274C **NEVER DO THIS:**
|
|
482
|
+
- \`Glob("**/*.ts")\` \u2192 Use \`search(mode="pattern", query="*.ts")\` instead
|
|
483
|
+
- \`Grep("functionName")\` \u2192 Use \`search(mode="keyword", query="functionName")\` instead
|
|
484
|
+
- \`Read(file)\` for discovery \u2192 Use \`search(mode="auto", query="...")\` instead
|
|
485
|
+
- \`Task(subagent_type="Explore")\` \u2192 Use \`search(mode="auto")\` instead
|
|
486
|
+
|
|
487
|
+
\u2705 **ALWAYS DO THIS:**
|
|
488
|
+
1. \`search(mode="auto", query="what you're looking for")\`
|
|
489
|
+
2. Only use local tools (Glob/Grep/Read) if ContextStream returns **0 results**
|
|
490
|
+
3. Use Read ONLY for exact file edits after you know the file path
|
|
491
|
+
|
|
492
|
+
This applies to **EVERY search** throughout the **ENTIRE conversation**, not just the first message.
|
|
493
|
+
|
|
494
|
+
---
|
|
495
|
+
|
|
496
|
+
## \u{1F6A8} CRITICAL RULE #2 - AUTO-INDEXING \u{1F6A8}
|
|
497
|
+
|
|
498
|
+
**ContextStream auto-indexes your project on \`init\`.** You do NOT need to:
|
|
499
|
+
- Ask the user to index
|
|
500
|
+
- Manually trigger ingestion
|
|
501
|
+
- Check index_status before every search
|
|
502
|
+
|
|
503
|
+
**When \`init\` returns \`indexing_status: "started"\` or \`"refreshing"\`:**
|
|
504
|
+
- Background indexing is running automatically
|
|
505
|
+
- Search results will be available within seconds to minutes
|
|
506
|
+
- **DO NOT fall back to local tools** - wait for ContextStream search to work
|
|
507
|
+
- If search returns 0 results initially, try again after a moment
|
|
508
|
+
|
|
509
|
+
**Only manually trigger indexing if:**
|
|
510
|
+
- \`init\` returned \`ingest_recommendation.recommended: true\` (rare edge case)
|
|
511
|
+
- User explicitly asks to re-index
|
|
512
|
+
|
|
513
|
+
---
|
|
514
|
+
|
|
515
|
+
## \u{1F6A8} CRITICAL RULE #3 - LESSONS (PAST MISTAKES) \u{1F6A8}
|
|
516
|
+
|
|
517
|
+
**Lessons are past mistakes that MUST inform your work.** Ignoring lessons leads to repeated failures.
|
|
518
|
+
|
|
519
|
+
### On \`init\`:
|
|
520
|
+
- Check for \`lessons\` and \`lessons_warning\` in the response
|
|
521
|
+
- If present, **READ THEM IMMEDIATELY** before doing any work
|
|
522
|
+
- These are high-priority lessons (critical/high severity) relevant to your context
|
|
523
|
+
- **Apply the prevention steps** from each lesson to avoid repeating mistakes
|
|
524
|
+
|
|
525
|
+
### On \`context\`:
|
|
526
|
+
- Check for \`[LESSONS_WARNING]\` tag in the response
|
|
527
|
+
- If present, you **MUST** tell the user about the lessons before proceeding
|
|
528
|
+
- Lessons are proactively fetched when risky actions are detected (refactor, migrate, deploy, etc.)
|
|
529
|
+
- **Do not skip or bury this warning** - lessons represent real past mistakes
|
|
530
|
+
|
|
531
|
+
### Before ANY Non-Trivial Work:
|
|
532
|
+
**ALWAYS call \`session(action="get_lessons", query="<topic>")\`** where \`<topic>\` matches what you're about to do:
|
|
533
|
+
- Before refactoring \u2192 \`session(action="get_lessons", query="refactoring")\`
|
|
534
|
+
- Before API changes \u2192 \`session(action="get_lessons", query="API changes")\`
|
|
535
|
+
- Before database work \u2192 \`session(action="get_lessons", query="database migrations")\`
|
|
536
|
+
- Before deployments \u2192 \`session(action="get_lessons", query="deployment")\`
|
|
537
|
+
|
|
538
|
+
### When Lessons Are Found:
|
|
539
|
+
1. **Summarize the lessons** to the user before proceeding
|
|
540
|
+
2. **Explicitly state how you will avoid the past mistakes**
|
|
541
|
+
3. If a lesson conflicts with the current approach, **warn the user**
|
|
542
|
+
|
|
543
|
+
**Failing to check lessons before risky work is a critical error.**
|
|
544
|
+
|
|
545
|
+
---
|
|
546
|
+
|
|
547
|
+
## ContextStream v0.4.x Integration (Enhanced)
|
|
548
|
+
|
|
549
|
+
You have access to ContextStream MCP tools for persistent memory and context.
|
|
550
|
+
v0.4.x uses **~11 consolidated domain tools** for ~75% token reduction vs previous versions.
|
|
551
|
+
Rules Version: ${RULES_VERSION}
|
|
552
|
+
|
|
553
|
+
## TL;DR - CONTEXT EVERY MESSAGE
|
|
554
|
+
|
|
555
|
+
| Message | Required |
|
|
556
|
+
|---------|----------|
|
|
557
|
+
| **1st message** | \`init()\` \u2192 \`context(user_message="<msg>")\` |
|
|
558
|
+
| **EVERY message after** | \`context(user_message="<msg>")\` **FIRST** |
|
|
559
|
+
| **Before file search** | \`search(mode="auto")\` FIRST |
|
|
560
|
+
| **After significant work** | \`session(action="capture", event_type="decision", ...)\` |
|
|
561
|
+
| **User correction** | \`session(action="capture_lesson", ...)\` |
|
|
562
|
+
|
|
563
|
+
### Why EVERY Message?
|
|
564
|
+
|
|
565
|
+
\`context()\` delivers:
|
|
566
|
+
- **Dynamic rules** matched to your current task
|
|
567
|
+
- **Lessons** from past mistakes (prevents repeating errors)
|
|
568
|
+
- **Relevant decisions** and context (semantic search)
|
|
569
|
+
- **Warnings** about risky operations
|
|
570
|
+
|
|
571
|
+
**Without \`context()\`, you are blind to relevant context and will repeat past mistakes.**
|
|
572
|
+
|
|
573
|
+
### Protocol
|
|
574
|
+
|
|
575
|
+
| Step | What to Call |
|
|
576
|
+
|------|--------------|
|
|
577
|
+
| **1st message** | \`init(folder_path="...", context_hint="<msg>")\`, then \`context(...)\` |
|
|
578
|
+
| **2nd+ messages** | \`context(user_message="<msg>", format="minified", max_tokens=400)\` |
|
|
579
|
+
| **Code search** | \`search(mode="auto", query="...")\` \u2014 BEFORE Glob/Grep/Read |
|
|
580
|
+
| **After significant work** | \`session(action="capture", event_type="decision", ...)\` |
|
|
581
|
+
| **User correction** | \`session(action="capture_lesson", ...)\` |
|
|
582
|
+
| **\u26A0\uFE0F When warnings received** | **STOP**, acknowledge, explain mitigation, then proceed |
|
|
583
|
+
|
|
584
|
+
**First message rule:** After \`init\`:
|
|
585
|
+
1. Check for \`lessons\` in response - if present, READ and SUMMARIZE them to user
|
|
586
|
+
2. Then call \`context\` before any other tool or response
|
|
587
|
+
|
|
588
|
+
**Context Pack (Pro+):** If enabled, use \`context(..., mode="pack", distill=true)\` for code/file queries. If unavailable or disabled, omit \`mode\` and proceed with standard \`context\` (the API will fall back).
|
|
589
|
+
|
|
590
|
+
**Tool naming:** Use the exact tool names exposed by your MCP client. Claude Code typically uses \`mcp__<server>__<tool>\` where \`<server>\` matches your MCP config (often \`contextstream\`). If a tool call fails with "No such tool available", refresh rules and match the tool list.
|
|
591
|
+
|
|
592
|
+
---
|
|
593
|
+
|
|
594
|
+
## Consolidated Domain Tools Architecture
|
|
595
|
+
|
|
596
|
+
v0.4.x consolidates ~58 individual tools into ~11 domain tools with action/mode dispatch:
|
|
597
|
+
|
|
598
|
+
### Standalone Tools
|
|
599
|
+
- **\`init\`** - Initialize session with workspace detection + context (skip for simple utility operations)
|
|
600
|
+
- **\`context\`** - Semantic search for relevant context (skip for simple utility operations)
|
|
601
|
+
|
|
602
|
+
### Domain Tools (Use action/mode parameter)
|
|
603
|
+
|
|
604
|
+
| Domain | Actions/Modes | Example |
|
|
605
|
+
|--------|---------------|---------|
|
|
606
|
+
| **\`search\`** | mode: auto (recommended), semantic, hybrid (legacy alias), keyword, pattern | \`search(mode="auto", query="auth implementation", limit=3)\` |
|
|
607
|
+
| **\`session\`** | action: capture, capture_lesson, get_lessons, recall, remember, user_context, summary, compress, delta, smart_search, decision_trace | \`session(action="capture", event_type="decision", title="Use JWT", content="...")\` |
|
|
608
|
+
| **\`memory\`** | action: create_event, get_event, update_event, delete_event, list_events, distill_event, create_node, get_node, update_node, delete_node, list_nodes, supersede_node, search, decisions, timeline, summary | \`memory(action="list_events", limit=10)\` |
|
|
609
|
+
| **\`graph\`** | action: dependencies, impact, call_path, related, path, decisions, ingest, circular_dependencies, unused_code, contradictions | \`graph(action="impact", symbol_name="AuthService")\` |
|
|
610
|
+
| **\`project\`** | action: list, get, create, update, index, overview, statistics, files, index_status, ingest_local | \`project(action="statistics")\` |
|
|
611
|
+
| **\`workspace\`** | action: list, get, associate, bootstrap | \`workspace(action="list")\` |
|
|
612
|
+
| **\`reminder\`** | action: list, active, create, snooze, complete, dismiss | \`reminder(action="active")\` |
|
|
613
|
+
| **\`integration\`** | provider: slack/github/all; action: status, search, stats, activity, contributors, knowledge, summary, channels, discussions, sync_users, repos, issues | \`integration(provider="github", action="search", query="...")\` |
|
|
614
|
+
| **\`help\`** | action: tools, auth, version, editor_rules, enable_bundle | \`help(action="tools")\` |
|
|
615
|
+
|
|
616
|
+
---
|
|
617
|
+
|
|
618
|
+
### Why context is Required (Even After init)
|
|
619
|
+
|
|
620
|
+
**Common mistake:** "init already gave me context, I don't need context"
|
|
621
|
+
|
|
622
|
+
**This is WRONG. Here's why:**
|
|
623
|
+
- \`init\` returns the last ~10 items **BY TIME** (chronological)
|
|
624
|
+
- \`context\` **SEARCHES** for items **RELEVANT to THIS message** (semantic)
|
|
625
|
+
|
|
626
|
+
**Example failure:**
|
|
627
|
+
- User asks: "how should I implement authentication?"
|
|
628
|
+
- Auth decisions were made 20 conversations ago
|
|
629
|
+
- \`init\` won't have it (too old, not in recent 10)
|
|
630
|
+
- \`context\` FINDS it via semantic search
|
|
631
|
+
|
|
632
|
+
**Without context, you WILL miss relevant older context.**
|
|
633
|
+
|
|
634
|
+
---
|
|
635
|
+
|
|
636
|
+
### Recommended Token Budgets
|
|
637
|
+
|
|
638
|
+
- For trivial/local edits: \`context(..., max_tokens=200)\`
|
|
639
|
+
- Default: \`context(..., max_tokens=400)\`
|
|
640
|
+
- Deep debugging/architecture: \`context(..., max_tokens=800)\`
|
|
641
|
+
- Keep \`format="minified"\` (default) unless debugging
|
|
642
|
+
|
|
643
|
+
If context still feels missing, use \`session(action="recall", query="...")\` for focused deep lookup.
|
|
644
|
+
|
|
645
|
+
---
|
|
646
|
+
|
|
647
|
+
### Rules, Version & Lessons Notices
|
|
648
|
+
|
|
649
|
+
**[RULES_NOTICE]** - Update rules via \`generate_rules()\` (or rerun setup).
|
|
650
|
+
|
|
651
|
+
**[VERSION_NOTICE]** or **[VERSION_CRITICAL]** - You **MUST** tell the user (be helpful, not annoying):
|
|
652
|
+
1. A new MCP server version is available with improvements
|
|
653
|
+
2. Provide update commands (user chooses preferred method):
|
|
654
|
+
- macOS/Linux: \`curl -fsSL https://contextstream.io/scripts/setup.sh | bash\`
|
|
655
|
+
- Windows: \`irm https://contextstream.io/scripts/setup.ps1 | iex\`
|
|
656
|
+
- npm: \`npm install -g @contextstream/mcp-server@latest\`
|
|
657
|
+
3. Restart AI tool after updating
|
|
658
|
+
**Mention once** - don't nag. Users often miss stderr warnings so this helps.
|
|
659
|
+
|
|
660
|
+
**[LESSONS_WARNING]** - You **MUST** before proceeding:
|
|
661
|
+
1. Read all lessons listed
|
|
662
|
+
2. Tell the user about relevant lessons
|
|
663
|
+
3. Explain how you will avoid each past mistake
|
|
664
|
+
**This is critical** - ignoring lessons leads to repeated failures.
|
|
665
|
+
|
|
666
|
+
---
|
|
667
|
+
|
|
668
|
+
### Preferences & Lessons (Use Early)
|
|
669
|
+
|
|
670
|
+
**Preferences ([PREFERENCE] in context response):**
|
|
671
|
+
- High-priority user memories that should guide your behavior
|
|
672
|
+
- Surfaced automatically via \`context()\` warnings field
|
|
673
|
+
- To save: \`session(action="remember", content="...")\`
|
|
674
|
+
- To retrieve explicitly: \`session(action="user_context")\`
|
|
675
|
+
|
|
676
|
+
**Lessons ([LESSONS_WARNING] in context response):**
|
|
677
|
+
- Past mistakes to avoid - apply prevention steps
|
|
678
|
+
- Surfaced automatically via \`context()\` warnings field
|
|
679
|
+
- Before risky changes: \`session(action="get_lessons", query="<topic>")\`
|
|
680
|
+
- On mistakes: \`session(action="capture_lesson", title="...", trigger="...", impact="...", prevention="...")\`
|
|
681
|
+
|
|
682
|
+
---
|
|
683
|
+
|
|
684
|
+
### Context Pressure & Compaction Awareness
|
|
685
|
+
|
|
686
|
+
ContextStream tracks context pressure to help you stay ahead of conversation compaction:
|
|
687
|
+
|
|
688
|
+
**Automatic tracking:** Token usage is tracked automatically. \`context\` returns \`context_pressure\` when usage is high.
|
|
689
|
+
|
|
690
|
+
**When \`context\` returns \`context_pressure\` with high/critical level:**
|
|
691
|
+
1. Review the \`suggested_action\` field:
|
|
692
|
+
- \`prepare_save\`: Start thinking about saving important state
|
|
693
|
+
- \`save_now\`: Immediately call \`session(action="capture", event_type="session_snapshot")\` to preserve state
|
|
694
|
+
|
|
695
|
+
**PreCompact Hook:** Automatically saves session state before context compaction.
|
|
696
|
+
Installed by default. Disable with: \`CONTEXTSTREAM_HOOK_ENABLED=false\`
|
|
697
|
+
|
|
698
|
+
**Before compaction happens (when warned):**
|
|
699
|
+
\`\`\`
|
|
700
|
+
session(action="capture", event_type="session_snapshot", title="Pre-compaction snapshot", content="{
|
|
701
|
+
\\"conversation_summary\\": \\"<summarize what we've been doing>\\",
|
|
702
|
+
\\"current_goal\\": \\"<the main task>\\",
|
|
703
|
+
\\"active_files\\": [\\"file1.ts\\", \\"file2.ts\\"],
|
|
704
|
+
\\"recent_decisions\\": [{title: \\"...\\", rationale: \\"...\\"}],
|
|
705
|
+
\\"unfinished_work\\": [{task: \\"...\\", status: \\"...\\", next_steps: \\"...\\"}]
|
|
706
|
+
}")
|
|
707
|
+
\`\`\`
|
|
708
|
+
|
|
709
|
+
**After compaction (when context seems lost):**
|
|
710
|
+
1. Call \`init(folder_path="...", is_post_compact=true)\` - this auto-restores the most recent snapshot
|
|
711
|
+
2. Or call \`session_restore_context()\` directly to get the saved state
|
|
712
|
+
3. Review the \`restored_context\` to understand prior work
|
|
713
|
+
4. Acknowledge to the user what was restored and continue
|
|
714
|
+
|
|
715
|
+
---
|
|
716
|
+
|
|
717
|
+
### Index Status (Auto-Managed)
|
|
718
|
+
|
|
719
|
+
**Indexing is automatic.** After \`init\`, the project is auto-indexed in the background.
|
|
720
|
+
|
|
721
|
+
**You do NOT need to manually check index_status before every search.** Just use \`search()\`.
|
|
722
|
+
|
|
723
|
+
**If search returns 0 results and you expected matches:**
|
|
724
|
+
1. Check if \`init\` returned \`indexing_status: "started"\` - indexing may still be in progress
|
|
725
|
+
2. Wait a moment and retry \`search()\`
|
|
726
|
+
3. Only as a last resort: \`project(action="index_status")\` to check
|
|
727
|
+
|
|
728
|
+
**Graph data:** If graph queries (\`dependencies\`, \`impact\`) return empty, run \`graph(action="ingest")\` once.
|
|
729
|
+
|
|
730
|
+
**NEVER fall back to local tools (Glob/Grep/Read) just because search returned 0 results on first try.** Retry first.
|
|
731
|
+
|
|
732
|
+
### Enhanced Context (Server-Side Warnings)
|
|
733
|
+
|
|
734
|
+
\`context\` now includes **intelligent server-side filtering** that proactively surfaces relevant warnings:
|
|
735
|
+
|
|
736
|
+
**Response fields:**
|
|
737
|
+
- \`warnings\`: Array of warning strings (displayed with \u26A0\uFE0F prefix)
|
|
738
|
+
|
|
739
|
+
**What triggers warnings:**
|
|
740
|
+
- **Lessons**: Past mistakes relevant to the current query (via semantic matching)
|
|
741
|
+
- **Risky actions**: Detected high-risk operations (deployments, migrations, destructive commands)
|
|
742
|
+
- **Breaking changes**: When modifications may impact other parts of the codebase
|
|
743
|
+
|
|
744
|
+
**When you receive warnings:**
|
|
745
|
+
1. **STOP** and read each warning carefully
|
|
746
|
+
2. **Acknowledge** the warning to the user
|
|
747
|
+
3. **Explain** how you will avoid the issue
|
|
748
|
+
4. Only proceed after addressing the warnings
|
|
749
|
+
|
|
750
|
+
### Search & Code Intelligence (ContextStream-first)
|
|
751
|
+
|
|
752
|
+
\u26A0\uFE0F **STOP: Before using Search/Glob/Grep/Read/Explore** \u2192 Call \`search(mode="auto")\` FIRST. Use local tools ONLY if ContextStream returns 0 results.
|
|
753
|
+
|
|
754
|
+
**\u274C WRONG workflow (wastes tokens, slow):**
|
|
755
|
+
\`\`\`
|
|
756
|
+
Grep "function" \u2192 Read file1.ts \u2192 Read file2.ts \u2192 Read file3.ts \u2192 finally understand
|
|
757
|
+
\`\`\`
|
|
758
|
+
|
|
759
|
+
**\u2705 CORRECT workflow (fast, complete):**
|
|
760
|
+
\`\`\`
|
|
761
|
+
search(mode="auto", query="function implementation") \u2192 done (results include context)
|
|
762
|
+
\`\`\`
|
|
763
|
+
|
|
764
|
+
**Why?** ContextStream search returns semantic matches + context + file locations in ONE call. Local tools require multiple round-trips.
|
|
765
|
+
|
|
766
|
+
**Search order:**
|
|
767
|
+
1. \`session(action="smart_search", query="...")\` - context-enriched
|
|
768
|
+
2. \`search(mode="auto", query="...", limit=3)\` or \`search(mode="keyword", query="<filename>", limit=3)\`
|
|
769
|
+
3. \`project(action="files")\` - file tree/list (only when needed)
|
|
770
|
+
4. \`graph(action="dependencies", ...)\` - code structure
|
|
771
|
+
5. Local repo scans (rg/ls/find) - ONLY if ContextStream returns no results, errors, or the user explicitly asks
|
|
772
|
+
|
|
773
|
+
**Search Mode Selection:**
|
|
774
|
+
|
|
775
|
+
| Need | Mode | Example |
|
|
776
|
+
|------|------|---------|
|
|
777
|
+
| Find code by meaning | \`auto\` | "authentication logic", "error handling" |
|
|
778
|
+
| Exact string/symbol | \`keyword\` | "UserAuthService", "API_KEY" |
|
|
779
|
+
| File patterns | \`pattern\` | "*.sql", "test_*.py" |
|
|
780
|
+
| ALL matches (grep-like) | \`exhaustive\` | "TODO", "FIXME" (find all occurrences) |
|
|
781
|
+
| Symbol renaming | \`refactor\` | "oldFunctionName" (word-boundary matching) |
|
|
782
|
+
| Conceptual search | \`semantic\` | "how does caching work" |
|
|
783
|
+
|
|
784
|
+
**Token Efficiency:** Use \`output_format\` to reduce response size:
|
|
785
|
+
- \`full\` (default): Full content for understanding code
|
|
786
|
+
- \`paths\`: File paths only (80% token savings) - use for file listings
|
|
787
|
+
- \`minimal\`: Compact format (60% savings) - use for refactoring
|
|
788
|
+
- \`count\`: Match counts only (90% savings) - use for quick checks
|
|
789
|
+
|
|
790
|
+
**When to use \`output_format=count\`:**
|
|
791
|
+
- User asks "how many X" or "count of X" \u2192 \`search(..., output_format="count")\`
|
|
792
|
+
- Checking if something exists \u2192 count > 0 is sufficient
|
|
793
|
+
- Large exhaustive searches \u2192 get count first, then fetch if needed
|
|
794
|
+
|
|
795
|
+
**Auto-suggested formats:** Search responses include \`query_interpretation.suggested_output_format\` when the API detects an optimal format:
|
|
796
|
+
- Symbol queries (e.g., "authOptions") \u2192 suggests \`minimal\` (path + line + snippet)
|
|
797
|
+
- Count queries (e.g., "how many") \u2192 suggests \`count\`
|
|
798
|
+
**USE the suggested format** on subsequent searches for best token efficiency.
|
|
799
|
+
|
|
800
|
+
**Search defaults:** \`search\` returns the top 3 results with compact snippets. Use \`limit\` + \`offset\` for pagination, and \`content_max_chars\` to expand snippets when needed.
|
|
801
|
+
|
|
802
|
+
If ContextStream returns results, stop and use them. NEVER use local Search/Explore/Read unless you need exact code edits or ContextStream returned 0 results.
|
|
803
|
+
|
|
804
|
+
**Code Analysis:**
|
|
805
|
+
- Dependencies: \`graph(action="dependencies", file_path="...")\`
|
|
806
|
+
- Change impact: \`graph(action="impact", symbol_name="...")\`
|
|
807
|
+
- Call path: \`graph(action="call_path", from_symbol="...", to_symbol="...")\`
|
|
808
|
+
- Build graph: \`graph(action="ingest")\` - async, can take a few minutes
|
|
809
|
+
|
|
810
|
+
---
|
|
811
|
+
|
|
812
|
+
### Distillation & Memory Hygiene
|
|
813
|
+
|
|
814
|
+
- Quick context: \`session(action="summary")\`
|
|
815
|
+
- Long chat: \`session(action="compress", content="...")\`
|
|
816
|
+
- Memory summary: \`memory(action="summary")\`
|
|
817
|
+
- Condense noisy entries: \`memory(action="distill_event", event_id="...")\`
|
|
818
|
+
|
|
819
|
+
---
|
|
820
|
+
|
|
821
|
+
### When to Capture
|
|
822
|
+
|
|
823
|
+
| When | Call | Example |
|
|
824
|
+
|------|------|---------|
|
|
825
|
+
| User makes decision | \`session(action="capture", event_type="decision", ...)\` | "Let's use PostgreSQL" |
|
|
826
|
+
| User states preference | \`session(action="capture", event_type="preference", ...)\` | "I prefer TypeScript" |
|
|
827
|
+
| Complete significant task | \`session(action="capture", event_type="task", ...)\` | Capture what was done |
|
|
828
|
+
| Need past context | \`session(action="recall", query="...")\` | "What did we decide about X?" |
|
|
829
|
+
|
|
830
|
+
**DO NOT capture utility operations:**
|
|
831
|
+
- \u274C "Listed workspaces" - not meaningful context
|
|
832
|
+
- \u274C "Showed version" - not a decision
|
|
833
|
+
- \u274C "Listed projects" - just data retrieval
|
|
834
|
+
|
|
835
|
+
**DO capture meaningful work:**
|
|
836
|
+
- \u2705 Decisions, preferences, completed features
|
|
837
|
+
- \u2705 Lessons from mistakes
|
|
838
|
+
- \u2705 Insights about architecture or patterns
|
|
839
|
+
|
|
840
|
+
---
|
|
841
|
+
|
|
842
|
+
### \u{1F6A8} Plans & Tasks - USE CONTEXTSTREAM, NOT FILE-BASED PLANS \u{1F6A8}
|
|
843
|
+
|
|
844
|
+
**CRITICAL: When the user requests planning, implementation plans, roadmaps, task breakdowns, or step-by-step approaches:**
|
|
845
|
+
|
|
846
|
+
\u274C **DO NOT** use built-in plan mode (EnterPlanMode tool)
|
|
847
|
+
\u274C **DO NOT** write plans to markdown files or plan documents
|
|
848
|
+
\u274C **DO NOT** ask "should I create a plan file?"
|
|
849
|
+
|
|
850
|
+
\u2705 **ALWAYS** use ContextStream's plan/task system instead
|
|
851
|
+
|
|
852
|
+
**Trigger phrases to detect (use ContextStream immediately):**
|
|
853
|
+
- "create a plan", "make a plan", "plan this", "plan for"
|
|
854
|
+
- "implementation plan", "roadmap", "milestones"
|
|
855
|
+
- "break down", "breakdown", "break this into steps"
|
|
856
|
+
- "what are the steps", "step by step", "outline the approach"
|
|
857
|
+
- "task list", "todo list", "action items"
|
|
858
|
+
- "how should we approach", "implementation strategy"
|
|
859
|
+
|
|
860
|
+
**When detected, immediately:**
|
|
861
|
+
|
|
862
|
+
1. **Create the plan in ContextStream:**
|
|
863
|
+
\`\`\`
|
|
864
|
+
session(action="capture_plan", title="<descriptive title>", description="<what this plan accomplishes>", goals=["goal1", "goal2"], steps=[{id: "1", title: "Step 1", order: 1, description: "..."}, ...])
|
|
865
|
+
\`\`\`
|
|
866
|
+
|
|
867
|
+
2. **Create tasks for each step:**
|
|
868
|
+
\`\`\`
|
|
869
|
+
memory(action="create_task", title="<task title>", plan_id="<plan_id from step 1>", priority="high|medium|low", description="<detailed task description>")
|
|
870
|
+
\`\`\`
|
|
871
|
+
|
|
872
|
+
**Why ContextStream plans are better:**
|
|
873
|
+
- Plans persist across sessions and are searchable
|
|
874
|
+
- Tasks track status (pending/in_progress/completed/blocked)
|
|
875
|
+
- Context is preserved with workspace/project association
|
|
876
|
+
- Can be retrieved with \`session(action="get_plan", plan_id="...", include_tasks=true)\`
|
|
877
|
+
- Future sessions can continue from where you left off
|
|
878
|
+
|
|
879
|
+
**Managing plans/tasks:**
|
|
880
|
+
- List plans: \`session(action="list_plans")\`
|
|
881
|
+
- Get plan with tasks: \`session(action="get_plan", plan_id="<uuid>", include_tasks=true)\`
|
|
882
|
+
- List tasks: \`memory(action="list_tasks", plan_id="<uuid>")\` or \`memory(action="list_tasks")\` for all
|
|
883
|
+
- Update task status: \`memory(action="update_task", task_id="<uuid>", task_status="pending|in_progress|completed|blocked")\`
|
|
884
|
+
- Link task to plan: \`memory(action="update_task", task_id="<uuid>", plan_id="<plan_uuid>")\`
|
|
885
|
+
- Unlink task from plan: \`memory(action="update_task", task_id="<uuid>", plan_id=null)\`
|
|
886
|
+
- Delete: \`memory(action="delete_task", task_id="<uuid>")\` or \`memory(action="delete_event", event_id="<plan_uuid>")\`
|
|
887
|
+
|
|
888
|
+
---
|
|
889
|
+
|
|
890
|
+
### Complete Action Reference
|
|
891
|
+
|
|
892
|
+
**session actions:**
|
|
893
|
+
- \`capture\` - Save decision/insight/task (requires: event_type, title, content)
|
|
894
|
+
- \`capture_lesson\` - Save lesson from mistake (requires: title, category, trigger, impact, prevention)
|
|
895
|
+
- \`get_lessons\` - Retrieve relevant lessons (optional: query, category, severity)
|
|
896
|
+
- \`recall\` - Natural language memory recall (requires: query)
|
|
897
|
+
- \`remember\` - Quick save to memory (requires: content)
|
|
898
|
+
- \`user_context\` - Get user preferences/style
|
|
899
|
+
- \`summary\` - Workspace summary
|
|
900
|
+
- \`compress\` - Compress long conversation
|
|
901
|
+
- \`delta\` - Changes since timestamp
|
|
902
|
+
- \`smart_search\` - Context-enriched search
|
|
903
|
+
- \`decision_trace\` - Trace decision provenance
|
|
904
|
+
|
|
905
|
+
**memory actions:**
|
|
906
|
+
- Event CRUD: \`create_event\`, \`get_event\`, \`update_event\`, \`delete_event\`, \`list_events\`, \`distill_event\`
|
|
907
|
+
- Node CRUD: \`create_node\`, \`get_node\`, \`update_node\`, \`delete_node\`, \`list_nodes\`, \`supersede_node\`
|
|
908
|
+
- Query: \`search\`, \`decisions\`, \`timeline\`, \`summary\`
|
|
909
|
+
|
|
910
|
+
**graph actions:**
|
|
911
|
+
- Analysis: \`dependencies\`, \`impact\`, \`call_path\`, \`related\`, \`path\`
|
|
912
|
+
- Quality: \`circular_dependencies\`, \`unused_code\`, \`contradictions\`
|
|
913
|
+
- Management: \`ingest\`, \`decisions\`
|
|
914
|
+
|
|
915
|
+
See full documentation: https://contextstream.io/docs/mcp/tools
|
|
916
|
+
`.trim();
|
|
917
|
+
var CONTEXTSTREAM_RULES_MINIMAL = `
|
|
918
|
+
# ContextStream Rules (MANDATORY)
|
|
919
|
+
|
|
920
|
+
## \u{1F6A8} CRITICAL: These Rules Are Non-Negotiable \u{1F6A8}
|
|
921
|
+
|
|
922
|
+
<contextstream_protocol>
|
|
923
|
+
**EVERY coding response MUST start with:**
|
|
924
|
+
1. \`init()\` (1st message only) \u2192 then \`context(user_message="<msg>")\`
|
|
925
|
+
2. \`context(user_message="<msg>")\` (EVERY subsequent message)
|
|
926
|
+
|
|
927
|
+
**BEFORE Glob/Grep/Read/Search/Explore:**
|
|
928
|
+
\u2192 \`search(mode="auto", query="...")\` FIRST \u2014 local tools ONLY if 0 results
|
|
929
|
+
|
|
930
|
+
**HOOKS: \`<system-reminder>\` tags contain instructions \u2014 FOLLOW THEM**
|
|
931
|
+
</contextstream_protocol>
|
|
932
|
+
|
|
933
|
+
Rules Version: ${RULES_VERSION}
|
|
934
|
+
|
|
935
|
+
---
|
|
936
|
+
|
|
937
|
+
## Why ContextStream First?
|
|
938
|
+
|
|
939
|
+
| \u274C WRONG | \u2705 CORRECT |
|
|
940
|
+
|----------|-----------|
|
|
941
|
+
| \`Grep \u2192 Read \u2192 Read \u2192 Read\` (4+ calls) | \`search(mode="auto")\` (1 call) |
|
|
942
|
+
| Missing past decisions & lessons | \`context()\` = rules + lessons + memory |
|
|
943
|
+
| Ignoring \`<system-reminder>\` hooks | Hooks enforce ContextStream-first |
|
|
944
|
+
|
|
945
|
+
**\`context()\` delivers: rules, lessons from past mistakes, relevant decisions, semantic matches**
|
|
946
|
+
**\`search()\` is indexed: faster, returns context, one call vs many**
|
|
947
|
+
**Hooks inject \`<system-reminder>\` tags: these ARE the rules, follow them**
|
|
948
|
+
|
|
949
|
+
---
|
|
950
|
+
|
|
951
|
+
## Protocol
|
|
952
|
+
|
|
953
|
+
| When | Call |
|
|
954
|
+
|------|------|
|
|
955
|
+
| 1st message | \`init()\` \u2192 \`context(user_message="...")\` |
|
|
956
|
+
| Every message after | \`context(user_message="...")\` |
|
|
957
|
+
| Before ANY file discovery | \`search(mode="auto", query="...")\` |
|
|
958
|
+
| On \`<system-reminder>\` | **Follow instructions inside** |
|
|
959
|
+
| Save important decisions | \`session(action="capture", event_type="decision", ...)\` |
|
|
960
|
+
| Check past mistakes | \`session(action="get_lessons", query="...")\` |
|
|
961
|
+
|
|
962
|
+
## Search Modes
|
|
963
|
+
|
|
964
|
+
| Mode | When |
|
|
965
|
+
|------|------|
|
|
966
|
+
| \`auto\` | Default \u2014 semantic + keyword |
|
|
967
|
+
| \`hybrid\` | Legacy alias for auto |
|
|
968
|
+
| \`keyword\` | Exact symbol match |
|
|
969
|
+
| \`exhaustive\` | Find ALL occurrences |
|
|
970
|
+
| \`semantic\` | Conceptual questions |
|
|
971
|
+
|
|
972
|
+
## Handle Notices from context()
|
|
973
|
+
|
|
974
|
+
- **[LESSONS_WARNING]** \u2192 Tell user about past mistakes BEFORE proceeding
|
|
975
|
+
- **[PREFERENCE]** \u2192 Follow user preferences (high-priority user memories)
|
|
976
|
+
- **[RULES_NOTICE]** \u2192 Run \`generate_rules()\`
|
|
977
|
+
- **[VERSION_NOTICE]** \u2192 Tell user to update MCP
|
|
978
|
+
|
|
979
|
+
## Fast Path (Simple Utilities Only)
|
|
980
|
+
|
|
981
|
+
Skip init/context ONLY for: "list workspaces", "show version", "list reminders"
|
|
982
|
+
\u2192 Just call: \`workspace(action="list")\`, \`help(action="version")\`, etc.
|
|
983
|
+
|
|
984
|
+
Everything else = full protocol (init \u2192 context \u2192 search \u2192 work)
|
|
985
|
+
|
|
986
|
+
### Lessons (Past Mistakes)
|
|
987
|
+
|
|
988
|
+
- After \`init\`: Check for \`lessons\` field and apply before work
|
|
989
|
+
- Before risky work: \`session(action="get_lessons", query="<topic>")\`
|
|
990
|
+
- On mistakes: \`session(action="capture_lesson", title="...", trigger="...", impact="...", prevention="...")\`
|
|
991
|
+
|
|
992
|
+
### Context Pressure & Compaction
|
|
993
|
+
|
|
994
|
+
- If \`context\` returns high/critical \`context_pressure\`: call \`session(action="capture", ...)\` to save state
|
|
995
|
+
- PreCompact hooks automatically save snapshots before compaction
|
|
996
|
+
|
|
997
|
+
### Enhanced Context (Warnings)
|
|
998
|
+
|
|
999
|
+
\`context\` returns server-side \`warnings\` for lessons, risky actions, and breaking changes.
|
|
1000
|
+
When warnings are present: **STOP**, acknowledge them, explain mitigation, then proceed.
|
|
1001
|
+
|
|
1002
|
+
### Automatic Context Restoration
|
|
1003
|
+
|
|
1004
|
+
**Context restoration is now enabled by default.** Every \`init\` call automatically:
|
|
1005
|
+
- Restores context from recent snapshots (if available)
|
|
1006
|
+
- Returns \`restored_context\` field with snapshot data
|
|
1007
|
+
- Sets \`is_post_compact=true\` in response when restoration occurs
|
|
1008
|
+
|
|
1009
|
+
**No special handling needed after compaction** - just call \`init\` normally.
|
|
1010
|
+
|
|
1011
|
+
To disable automatic restoration:
|
|
1012
|
+
- Pass \`is_post_compact=false\` in the API call
|
|
1013
|
+
- Or set \`CONTEXTSTREAM_RESTORE_CONTEXT=false\` environment variable
|
|
1014
|
+
|
|
1015
|
+
### Notices - MUST HANDLE IMMEDIATELY
|
|
1016
|
+
|
|
1017
|
+
- **[VERSION_NOTICE]** or **[VERSION_CRITICAL]**: Tell user about the update in a helpful, non-annoying way. Provide update commands:
|
|
1018
|
+
- macOS/Linux: \`curl -fsSL https://contextstream.io/scripts/setup.sh | bash\`
|
|
1019
|
+
- Windows: \`irm https://contextstream.io/scripts/setup.ps1 | iex\`
|
|
1020
|
+
- npm: \`npm install -g @contextstream/mcp-server@latest\`
|
|
1021
|
+
- **[RULES_NOTICE]**: Run \`generate_rules(overwrite_existing=true)\` to update
|
|
1022
|
+
- **[LESSONS_WARNING]**: Read lessons, tell user about them, explain how you'll avoid past mistakes
|
|
1023
|
+
- **[PREFERENCE]**: Follow user preferences - these are high-priority user memories that should guide your behavior
|
|
1024
|
+
|
|
1025
|
+
### Plans & Tasks
|
|
1026
|
+
|
|
1027
|
+
When user asks for a plan, use ContextStream (not EnterPlanMode):
|
|
1028
|
+
1. \`session(action="capture_plan", title="...", steps=[...])\`
|
|
1029
|
+
2. \`memory(action="create_task", title="...", plan_id="<id>")\`
|
|
1030
|
+
|
|
1031
|
+
### Workspace-Only Mode (Multi-Project Folders)
|
|
1032
|
+
|
|
1033
|
+
If working in a parent folder containing multiple projects:
|
|
1034
|
+
\`\`\`
|
|
1035
|
+
init(folder_path="...", skip_project_creation=true)
|
|
1036
|
+
\`\`\`
|
|
1037
|
+
|
|
1038
|
+
This enables workspace-level memory and context without project-specific indexing.
|
|
1039
|
+
Use for monorepos or folders with multiple independent projects.
|
|
1040
|
+
|
|
1041
|
+
Full docs: https://contextstream.io/docs/mcp/tools
|
|
1042
|
+
`.trim();
|
|
1043
|
+
var NO_HOOKS_SUPPLEMENT = `
|
|
1044
|
+
|
|
1045
|
+
---
|
|
1046
|
+
## \u26A0\uFE0F IMPORTANT: No Hooks Available \u26A0\uFE0F
|
|
1047
|
+
|
|
1048
|
+
**This editor does NOT have hooks to enforce ContextStream behavior.**
|
|
1049
|
+
You MUST follow these rules manually - there is no automatic enforcement.
|
|
1050
|
+
|
|
1051
|
+
---
|
|
1052
|
+
|
|
1053
|
+
## \u{1F680} SESSION START PROTOCOL
|
|
1054
|
+
|
|
1055
|
+
**On EVERY new session, you MUST:**
|
|
1056
|
+
|
|
1057
|
+
1. **Call \`init(folder_path="<project_path>")\`** FIRST
|
|
1058
|
+
- This triggers project indexing
|
|
1059
|
+
- Check response for \`indexing_status\`
|
|
1060
|
+
- If \`"started"\` or \`"refreshing"\`: wait before searching
|
|
1061
|
+
|
|
1062
|
+
2. **Generate a unique session_id** (e.g., \`"session-" + timestamp\` or a UUID)
|
|
1063
|
+
- Use this SAME session_id for ALL context() calls in this conversation
|
|
1064
|
+
- This groups all turns together in the transcript
|
|
1065
|
+
|
|
1066
|
+
3. **Call \`context(user_message="<first_message>", save_exchange=true, session_id="<your-session-id>")\`**
|
|
1067
|
+
- Gets task-specific rules, lessons, and preferences
|
|
1068
|
+
- Check for [LESSONS_WARNING] - past mistakes to avoid
|
|
1069
|
+
- Check for [PREFERENCE] - user preferences to follow
|
|
1070
|
+
- Check for [RULES_NOTICE] - update rules if needed
|
|
1071
|
+
- **save_exchange=true** saves each conversation turn for later retrieval
|
|
1072
|
+
|
|
1073
|
+
4. **NEVER skip init/context** - you will miss critical context
|
|
1074
|
+
|
|
1075
|
+
---
|
|
1076
|
+
|
|
1077
|
+
## \u{1F4BE} AUTOMATIC TRANSCRIPT SAVING (CRITICAL)
|
|
1078
|
+
|
|
1079
|
+
**This editor does NOT have hooks to auto-save transcripts.**
|
|
1080
|
+
You MUST save each conversation turn manually:
|
|
1081
|
+
|
|
1082
|
+
### On EVERY message (including the first):
|
|
1083
|
+
\`\`\`
|
|
1084
|
+
context(user_message="<user's message>", save_exchange=true, session_id="<session-id>")
|
|
1085
|
+
\`\`\`
|
|
1086
|
+
|
|
1087
|
+
### Why save_exchange matters:
|
|
1088
|
+
- Transcripts enable searching past conversations
|
|
1089
|
+
- Allows context restoration after compaction
|
|
1090
|
+
- Provides conversation history for debugging
|
|
1091
|
+
- Required for the Transcripts page in the dashboard
|
|
1092
|
+
|
|
1093
|
+
### Session ID Guidelines:
|
|
1094
|
+
- Generate ONCE at the start of the conversation
|
|
1095
|
+
- Use a unique identifier: \`"session-" + Date.now()\` or a UUID
|
|
1096
|
+
- Keep the SAME session_id for ALL context() calls in this session
|
|
1097
|
+
- Different sessions = different transcripts
|
|
1098
|
+
|
|
1099
|
+
---
|
|
1100
|
+
|
|
1101
|
+
## \u{1F4C1} FILE INDEXING (CRITICAL)
|
|
1102
|
+
|
|
1103
|
+
**There is NO automatic file indexing in this editor.**
|
|
1104
|
+
You MUST manage indexing manually:
|
|
1105
|
+
|
|
1106
|
+
### After Creating/Editing Files:
|
|
1107
|
+
\`\`\`
|
|
1108
|
+
project(action="index") # Re-index entire project
|
|
1109
|
+
\`\`\`
|
|
1110
|
+
|
|
1111
|
+
### For Single File Updates:
|
|
1112
|
+
\`\`\`
|
|
1113
|
+
project(action="ingest_local", path="<file_path>")
|
|
1114
|
+
\`\`\`
|
|
1115
|
+
|
|
1116
|
+
### Signs You Need to Re-index:
|
|
1117
|
+
- Search doesn't find code you just wrote
|
|
1118
|
+
- Search returns old versions of functions
|
|
1119
|
+
- New files don't appear in search results
|
|
1120
|
+
|
|
1121
|
+
### Best Practice:
|
|
1122
|
+
After completing a feature or making multiple file changes, ALWAYS run:
|
|
1123
|
+
\`\`\`
|
|
1124
|
+
project(action="index")
|
|
1125
|
+
\`\`\`
|
|
1126
|
+
|
|
1127
|
+
---
|
|
1128
|
+
|
|
1129
|
+
## \u{1F50D} SEARCH-FIRST (No PreToolUse Hook)
|
|
1130
|
+
|
|
1131
|
+
**There is NO hook to block local tools.** You MUST self-enforce:
|
|
1132
|
+
|
|
1133
|
+
### Before ANY Search, Check Index Status:
|
|
1134
|
+
\`\`\`
|
|
1135
|
+
project(action="index_status")
|
|
1136
|
+
\`\`\`
|
|
1137
|
+
|
|
1138
|
+
This tells you:
|
|
1139
|
+
- \`indexed\`: true/false - is project indexed?
|
|
1140
|
+
- \`last_indexed_at\`: timestamp - when was it last indexed?
|
|
1141
|
+
- \`file_count\`: number - how many files indexed?
|
|
1142
|
+
|
|
1143
|
+
### Search Protocol:
|
|
1144
|
+
|
|
1145
|
+
**IF project is indexed and fresh:**
|
|
1146
|
+
\`\`\`
|
|
1147
|
+
search(mode="auto", query="what you're looking for")
|
|
1148
|
+
\`\`\`
|
|
1149
|
+
|
|
1150
|
+
**IF project is NOT indexed or very stale (>7 days):**
|
|
1151
|
+
\u2192 Use local tools (Glob/Grep/Read) directly
|
|
1152
|
+
\u2192 OR run \`project(action="index")\` first, then search
|
|
1153
|
+
|
|
1154
|
+
**IF ContextStream search returns 0 results or errors:**
|
|
1155
|
+
\u2192 Use local tools (Glob/Grep/Read) as fallback
|
|
1156
|
+
|
|
1157
|
+
### When Local Tools Are OK:
|
|
1158
|
+
\u2705 Project is not indexed
|
|
1159
|
+
\u2705 Index is stale/outdated (>7 days old)
|
|
1160
|
+
\u2705 ContextStream search returns 0 results
|
|
1161
|
+
\u2705 ContextStream returns errors
|
|
1162
|
+
\u2705 User explicitly requests local tools
|
|
1163
|
+
|
|
1164
|
+
### When to Use ContextStream Search:
|
|
1165
|
+
\u2705 Project is indexed and fresh
|
|
1166
|
+
\u2705 Looking for code by meaning/concept
|
|
1167
|
+
\u2705 Need semantic understanding
|
|
1168
|
+
|
|
1169
|
+
---
|
|
1170
|
+
|
|
1171
|
+
## \u{1F4BE} CONTEXT COMPACTION (No PreCompact Hook)
|
|
1172
|
+
|
|
1173
|
+
**There is NO automatic state saving before compaction.**
|
|
1174
|
+
You MUST save state manually when the conversation gets long:
|
|
1175
|
+
|
|
1176
|
+
### When to Save State:
|
|
1177
|
+
- After completing a major task
|
|
1178
|
+
- Before the conversation might be compacted
|
|
1179
|
+
- If \`context()\` returns \`context_pressure.level: "high"\`
|
|
1180
|
+
|
|
1181
|
+
### How to Save State:
|
|
1182
|
+
\`\`\`
|
|
1183
|
+
session(action="capture", event_type="session_snapshot",
|
|
1184
|
+
title="Session checkpoint",
|
|
1185
|
+
content="{ \\"summary\\": \\"what we did\\", \\"active_files\\": [...], \\"next_steps\\": [...] }")
|
|
1186
|
+
\`\`\`
|
|
1187
|
+
|
|
1188
|
+
### After Compaction (if context seems lost):
|
|
1189
|
+
\`\`\`
|
|
1190
|
+
init(folder_path="...", is_post_compact=true)
|
|
1191
|
+
\`\`\`
|
|
1192
|
+
This restores the most recent snapshot.
|
|
1193
|
+
|
|
1194
|
+
---
|
|
1195
|
+
|
|
1196
|
+
## \u{1F4CB} PLANS & TASKS (No EnterPlanMode)
|
|
1197
|
+
|
|
1198
|
+
**Always use ContextStream for planning:**
|
|
1199
|
+
|
|
1200
|
+
\`\`\`
|
|
1201
|
+
session(action="capture_plan", title="...", steps=[...])
|
|
1202
|
+
memory(action="create_task", title="...", plan_id="...")
|
|
1203
|
+
\`\`\`
|
|
1204
|
+
|
|
1205
|
+
\u274C DO NOT use built-in plan mode or write plans to markdown files.
|
|
1206
|
+
|
|
1207
|
+
---
|
|
1208
|
+
|
|
1209
|
+
## \u{1F504} VERSION UPDATES (Check Periodically)
|
|
1210
|
+
|
|
1211
|
+
**This editor does NOT have hooks to check for updates automatically.**
|
|
1212
|
+
You should check for updates using \`help(action="version")\` periodically (e.g., at session start).
|
|
1213
|
+
|
|
1214
|
+
### If the response includes [VERSION_NOTICE] or [VERSION_CRITICAL]:
|
|
1215
|
+
|
|
1216
|
+
**Tell the user** about the available update in a helpful, non-annoying way:
|
|
1217
|
+
- Frame it as "new features and improvements available"
|
|
1218
|
+
- Provide the update commands (user can choose their preferred method)
|
|
1219
|
+
- Don't nag repeatedly - mention once, then only if user asks
|
|
1220
|
+
|
|
1221
|
+
### Update Commands (provide all options):
|
|
1222
|
+
|
|
1223
|
+
**macOS/Linux:**
|
|
1224
|
+
\`\`\`bash
|
|
1225
|
+
curl -fsSL https://contextstream.io/scripts/setup.sh | bash
|
|
1226
|
+
\`\`\`
|
|
1227
|
+
|
|
1228
|
+
**Windows (PowerShell):**
|
|
1229
|
+
\`\`\`powershell
|
|
1230
|
+
irm https://contextstream.io/scripts/setup.ps1 | iex
|
|
1231
|
+
\`\`\`
|
|
1232
|
+
|
|
1233
|
+
**npm (requires Node.js 18+):**
|
|
1234
|
+
\`\`\`bash
|
|
1235
|
+
npm install -g @contextstream/mcp-server@latest
|
|
1236
|
+
\`\`\`
|
|
1237
|
+
|
|
1238
|
+
After updating, user should restart their AI tool.
|
|
1239
|
+
|
|
1240
|
+
---
|
|
1241
|
+
`;
|
|
1242
|
+
var NO_HOOKS_EDITORS = ["codex", "aider", "antigravity"];
|
|
1243
|
+
var TEMPLATES = {
|
|
1244
|
+
codex: {
|
|
1245
|
+
filename: "AGENTS.md",
|
|
1246
|
+
description: "Codex CLI agent instructions",
|
|
1247
|
+
build: (rules) => `# Codex CLI Instructions
|
|
1248
|
+
${rules}
|
|
1249
|
+
`
|
|
1250
|
+
},
|
|
1251
|
+
cursor: {
|
|
1252
|
+
filename: ".cursorrules",
|
|
1253
|
+
description: "Cursor AI rules",
|
|
1254
|
+
build: (rules) => `# Cursor Rules
|
|
1255
|
+
${rules}
|
|
1256
|
+
`
|
|
1257
|
+
},
|
|
1258
|
+
cline: {
|
|
1259
|
+
filename: ".clinerules",
|
|
1260
|
+
description: "Cline AI rules",
|
|
1261
|
+
build: (rules) => `# Cline Rules
|
|
1262
|
+
${rules}
|
|
1263
|
+
`
|
|
1264
|
+
},
|
|
1265
|
+
kilo: {
|
|
1266
|
+
filename: ".kilocode/rules/contextstream.md",
|
|
1267
|
+
description: "Kilo Code AI rules",
|
|
1268
|
+
build: (rules) => `# Kilo Code Rules
|
|
1269
|
+
${rules}
|
|
1270
|
+
`
|
|
1271
|
+
},
|
|
1272
|
+
roo: {
|
|
1273
|
+
filename: ".roo/rules/contextstream.md",
|
|
1274
|
+
description: "Roo Code AI rules",
|
|
1275
|
+
build: (rules) => `# Roo Code Rules
|
|
1276
|
+
${rules}
|
|
1277
|
+
`
|
|
1278
|
+
},
|
|
1279
|
+
claude: {
|
|
1280
|
+
filename: "CLAUDE.md",
|
|
1281
|
+
description: "Claude Code instructions",
|
|
1282
|
+
build: (rules) => `# Claude Code Instructions
|
|
1283
|
+
${rules}
|
|
1284
|
+
`
|
|
1285
|
+
},
|
|
1286
|
+
aider: {
|
|
1287
|
+
filename: ".aider.conf.yml",
|
|
1288
|
+
description: "Aider configuration with system prompt",
|
|
1289
|
+
build: (rules) => `# Aider Configuration
|
|
1290
|
+
# Note: Aider uses different config format - this adds to the system prompt
|
|
1291
|
+
|
|
1292
|
+
# Add ContextStream guidance to conventions
|
|
1293
|
+
conventions: |
|
|
1294
|
+
${rules.split("\n").map((line) => " " + line).join("\n")}
|
|
1295
|
+
`
|
|
1296
|
+
},
|
|
1297
|
+
antigravity: {
|
|
1298
|
+
filename: "GEMINI.md",
|
|
1299
|
+
description: "Google Antigravity AI rules",
|
|
1300
|
+
build: (rules) => `# Antigravity Agent Rules
|
|
1301
|
+
${rules}
|
|
1302
|
+
`
|
|
1303
|
+
}
|
|
1304
|
+
};
|
|
1305
|
+
function getAvailableEditors() {
|
|
1306
|
+
return Object.keys(TEMPLATES);
|
|
1307
|
+
}
|
|
1308
|
+
function getTemplate(editor) {
|
|
1309
|
+
return TEMPLATES[editor.toLowerCase()] || null;
|
|
1310
|
+
}
|
|
1311
|
+
function generateRuleContent(editor, options) {
|
|
1312
|
+
const template = getTemplate(editor);
|
|
1313
|
+
if (!template) return null;
|
|
1314
|
+
const mode = options?.mode || "bootstrap";
|
|
1315
|
+
const rules = mode === "full" ? CONTEXTSTREAM_RULES_FULL : mode === "minimal" ? CONTEXTSTREAM_RULES_MINIMAL : mode === "bootstrap" ? CONTEXTSTREAM_RULES_BOOTSTRAP : CONTEXTSTREAM_RULES_DYNAMIC;
|
|
1316
|
+
let content = template.build(rules);
|
|
1317
|
+
if (options?.workspaceName || options?.projectName) {
|
|
1318
|
+
const header = `
|
|
1319
|
+
# Workspace: ${options.workspaceName || "Unknown"}
|
|
1320
|
+
${options.projectName ? `# Project: ${options.projectName}` : ""}
|
|
1321
|
+
${options.workspaceId ? `# Workspace ID: ${options.workspaceId}` : ""}
|
|
1322
|
+
|
|
1323
|
+
`;
|
|
1324
|
+
content = header + content;
|
|
1325
|
+
}
|
|
1326
|
+
if (NO_HOOKS_EDITORS.includes(editor.toLowerCase())) {
|
|
1327
|
+
content += NO_HOOKS_SUPPLEMENT;
|
|
1328
|
+
}
|
|
1329
|
+
if (options?.additionalRules) {
|
|
1330
|
+
content += "\n\n## Project-Specific Rules\n\n" + options.additionalRules;
|
|
1331
|
+
}
|
|
1332
|
+
if (editor.toLowerCase() === "claude") {
|
|
1333
|
+
content = applyMcpToolPrefix(content, `mcp__${DEFAULT_CLAUDE_MCP_SERVER_NAME}__`);
|
|
1334
|
+
}
|
|
1335
|
+
return {
|
|
1336
|
+
filename: template.filename,
|
|
1337
|
+
content: content.trim() + "\n"
|
|
1338
|
+
};
|
|
1339
|
+
}
|
|
1340
|
+
|
|
334
1341
|
// src/hooks/session-init.ts
|
|
335
1342
|
var ENABLED = process.env.CONTEXTSTREAM_SESSION_INIT_ENABLED !== "false";
|
|
336
1343
|
var API_URL = process.env.CONTEXTSTREAM_API_URL || "https://api.contextstream.io";
|
|
@@ -493,6 +1500,34 @@ function formatContext(ctx, options = {}) {
|
|
|
493
1500
|
parts.push('Call `mcp__contextstream__context(user_message="...")` for task-specific context.');
|
|
494
1501
|
return parts.join("\n");
|
|
495
1502
|
}
|
|
1503
|
+
var CONTEXTSTREAM_START_MARKER = "<!-- BEGIN ContextStream -->";
|
|
1504
|
+
var CONTEXTSTREAM_END_MARKER = "<!-- END ContextStream -->";
|
|
1505
|
+
function regenerateRuleFiles(folderPath) {
|
|
1506
|
+
let updated = 0;
|
|
1507
|
+
const editors = getAvailableEditors();
|
|
1508
|
+
for (const editor of editors) {
|
|
1509
|
+
const rule = generateRuleContent(editor, { mode: "bootstrap" });
|
|
1510
|
+
if (!rule) continue;
|
|
1511
|
+
const filePath = path.join(folderPath, rule.filename);
|
|
1512
|
+
if (!fs.existsSync(filePath)) continue;
|
|
1513
|
+
try {
|
|
1514
|
+
const existing = fs.readFileSync(filePath, "utf8");
|
|
1515
|
+
const startIdx = existing.indexOf(CONTEXTSTREAM_START_MARKER);
|
|
1516
|
+
const endIdx = existing.indexOf(CONTEXTSTREAM_END_MARKER);
|
|
1517
|
+
if (startIdx === -1 || endIdx === -1 || endIdx <= startIdx) continue;
|
|
1518
|
+
const before = existing.substring(0, startIdx).trimEnd();
|
|
1519
|
+
const after = existing.substring(endIdx + CONTEXTSTREAM_END_MARKER.length).trimStart();
|
|
1520
|
+
const newBlock = `${CONTEXTSTREAM_START_MARKER}
|
|
1521
|
+
${rule.content.trim()}
|
|
1522
|
+
${CONTEXTSTREAM_END_MARKER}`;
|
|
1523
|
+
const merged = [before, newBlock, after].filter((p) => p.length > 0).join("\n\n");
|
|
1524
|
+
fs.writeFileSync(filePath, merged.trim() + "\n", "utf8");
|
|
1525
|
+
updated++;
|
|
1526
|
+
} catch {
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
return updated;
|
|
1530
|
+
}
|
|
496
1531
|
async function runSessionInitHook() {
|
|
497
1532
|
if (!ENABLED) {
|
|
498
1533
|
process.exit(0);
|
|
@@ -514,6 +1549,7 @@ async function runSessionInitHook() {
|
|
|
514
1549
|
loadConfigFromMcpJson(cwd);
|
|
515
1550
|
const updateMarker = checkUpdateMarker();
|
|
516
1551
|
if (updateMarker) {
|
|
1552
|
+
regenerateRuleFiles(cwd);
|
|
517
1553
|
clearUpdateMarker();
|
|
518
1554
|
}
|
|
519
1555
|
const [context, autoUpdateResult, versionNotice] = await Promise.all([
|