🔥 Vigil MCP
The AI that reaches back out to you.
Most AI tools wait. You open them, you ask, they answer. Vigil flips that.
Connect it to Claude once — and it remembers what you said you'd do, reasons about when it's worth interrupting you, and follows up on its own.
The problem
Every AI interaction ends the same way: you close the tab and the context disappears. The AI has no persistence, no agency, no follow-through. It's reactive by design.
Vigil is a layer that changes that.
How it works
Vigil is an MCP server — a tool layer that any compatible AI can plug into. When connected:
- Claude detects commitments automatically — "I'll come back tomorrow", "remind me to push this on Friday", "I'll do X after lunch" → saved instantly, no command needed
- A policy engine runs in the background — every 60 seconds, it evaluates every pending commitment against 7 conditions before deciding whether to act
- When you open a new session, Claude reads
vigil://pending and opens with urgent items naturally — "Hey, you said you'd finish the README. Still on it?"
- Desktop and push notifications fire when things are overdue and you haven't opened Claude yet
- Nudges go to Slack or Discord if you've configured a webhook
- V3 integrations run every 5 minutes — idle detection, adaptive learning, and weekly reports work silently in the background
- Every decision is logged and explainable — ask "why did you message me?" and get the full trace
Policy engine
Vigil doesn't act on a timer. It reasons.
Every potential nudge passes through a 7-step decision chain:
1. Hypothetical intent? → never act
2. Grace period (<30 min old)? → too fresh, skip
3. Early phase (>48h to deadline)? → too soon, skip
4. Cooldown window active? → avoid spam (4h / 1h / 2h by phase)
5. Daily attention budget exhausted? → suppress unless importance ≥ 0.8
6. Soft intent? → reduce effective importance by 0.2
7. Phase + importance threshold → fire or stay silent
Every decision — including suppressed ones — is written to decision_log with phase, urgency, budget used, and full reasoning text.
Temporal phases
early | > 48h until due | — | No nudge |
execution | 4–48h until due | 4h | Nudge if importance ≥ 0.6 |
risk | < 4h until due | 1h | Always nudge |
overdue | Past deadline | 2h | Escalate |
Auto-decay
Nudged 3+ times with no response → importance decays 15% per cycle. After 6 ignored nudges → auto-archived. No noise, no spam.
Features
| 🧠 Policy engine | 7-step reasoning chain, not a simple timer |
| 💬 Natural language input | "remind me to push the PR before EOD" → parsed and saved automatically |
| 📬 Proactive notifications | Native macOS/Windows/Linux OR Web Push to phone/browser |
| 🔔 Slack/Discord integration | Nudges delivered to your Slack or Discord channel |
| 🤖 Slack slash commands | /vigil remind me to X creates a commitment from Slack |
| 📱 Installable PWA | Add dashboard to phone home screen — iOS 16.4+ / all Android |
| ☁️ Hosted mode | One-click Railway/Render deploy, auth-protected, multi-user |
| ✏️ Edit commitments | Update deadline, importance, intent, or description after saving |
| 🔁 Recurring commitments | Daily, weekly (specific days), monthly — auto-reschedules |
| 📉 Auto-decay | Importance drops on ignores; auto-archives after 6 nudges |
| 🌅 Daily digest | Optional morning summary notification |
| 🖥️ Web dashboard | Dark-theme UI at localhost:7734 (or your hosted URL) |
| 🔍 Full explainability | Every decision logged with reasoning — "Why did you message me?" |
| 💤 Idle detection | Nudges escalate when no Claude session detected for 4+ hours |
| 📊 Adaptive policy | Learns your follow-through patterns per category, boosts flagging commitments |
| 📋 Reliability reports | Weekly Monday summary: follow-through % by category |
Architecture
Claude Desktop
│
├── Tools (save / create_from_text / get / complete / snooze /
│ update / explain / budget / digest / set_slack_webhook /
│ set_discord_webhook / list_features / enable_feature /
│ disable_feature)
└── Resources (vigil://pending · vigil://status · vigil://history)
vigil-mcp process
├── server.py — FastMCP server, tools, resources, background loop
├── policy.py — Decision engine (phase → urgency → budget → action)
├── db.py — SQLite layer (thread-local, multi-user, migrations)
├── dashboard.py — HTTP dashboard + PWA + CRUD API (localhost:7734 / $PORT)
├── api.py — FastAPI REST layer (localhost:7735) + cloud entrypoint
├── analyzer.py — Signal analysis + NL commitment parsing (Claude API)
├── webhooks.py — Slack/Discord outbound nudges + slash command handler
├── push.py — Web Push delivery (VAPID + pywebpush)
├── pwa.py — Manifest, service worker, icons
├── notify.py — Shared notification delivery (push → webhooks → desktop)
├── features.py — V3 feature flag registry (7 toggleable features)
├── logger.py — Rotating structured log at ~/.vigil/vigil.log
└── integrations/
├── __init__.py — Fan-out runner (importlib-based, fault-isolated)
├── idle_detection.py — Live: session heartbeat + idle escalation
├── adaptive_policy.py — Live: per-category follow-through learning
├── reliability_reports.py — Live: weekly Monday digest by category
├── github_integration.py — Stub: stale PR commitment creation
├── calendar_sync.py — Stub: pre-meeting commitment surfacing
├── accountability_partners.py — Stub: Slack DM to accountability partner
└── shared_commitments.py — Stub: team-visible commitments via Slack
~/.vigil/
├── commitments.db — All data (commitments, decision_log, settings)
└── vigil.log — Structured log (grep-friendly)
Tools
create_from_text | Parse natural language into a commitment automatically |
save_commitment | Capture a commitment with explicit fields (due date, intent, importance, recurrence) |
get_commitments | List all pending with phase, state, and stats |
complete_commitment | Mark done; auto-reschedules if recurring |
snooze_commitment | Push deadline to a later time |
update_commitment | Edit description, deadline, importance, intent, or summary |
explain_nudge | Full decision trace for a commitment |
set_attention_budget | Set daily nudge cap (default: 10) |
set_daily_digest_time | Morning summary notification at HH:MM |
set_slack_webhook | Route nudges to a Slack channel |
set_discord_webhook | Route nudges to a Discord channel |
list_features | Show all V3 features and their on/off state |
enable_feature | Turn on a V3 feature by name |
disable_feature | Turn off a V3 feature by name |
Resources
vigil://pending | Pending commitments grouped by phase — Claude reads this at session start |
vigil://status | System health: budget used, config, stats |
vigil://history | Completed commitments and follow-through rate |
Commitment schema
{
description: str,
due_by: ISO 8601 datetime,
ai_summary: str,
intent_strength: "hard" | "soft" | "hypothetical",
importance_score: 0.0–1.0,
confidence_score: 0.0–1.0,
state: "captured" | "scheduled" | "in_progress" | "at_risk" | "overdue" | "completed" | "abandoned",
recurrence: "none" | "daily" | "weekly" | "monthly",
recurrence_days: ["monday", "thursday"],
recurrence_time: "HH:MM",
}
V3 Features
Vigil V3 adds three directions of capability behind toggleable feature flags. All are off by default — turn them on via Claude or the dashboard.
Enable via Claude
list_features()
enable_feature("idle_detection")
enable_feature("adaptive_policy")
enable_feature("reliability_reports")
Enable at startup (env var)
VIGIL_FEATURES=idle_detection,adaptive_policy,reliability_reports vigil
Feature registry
idle_detection | Context Awareness | Live | — |
adaptive_policy | Adaptive | Live | — |
reliability_reports | Adaptive | Live | — |
github_integration | Context Awareness | Stub | GITHUB_TOKEN |
calendar_sync | Context Awareness | Stub | GOOGLE_CALENDAR_TOKEN |
accountability_partners | Multi-Person / Team | Stub | VIGIL_SLACK_BOT_TOKEN |
shared_commitments | Multi-Person / Team | Stub | VIGIL_SLACK_BOT_TOKEN |
Idle Detection
Tracks the last time Claude read vigil://pending (i.e. the last time you opened a session). If no session is detected for 4+ hours and you have overdue or at-risk commitments, Vigil fires a push/Slack/desktop nudge.
- Cooldown: 2 hours between idle nudges
- Threshold:
VIGIL_IDLE_HOURS env var (default: 4)
- Resumes normal nudge schedule once you open a new session
Adaptive Policy
Runs once per day. Looks at your completed and abandoned commitments grouped by context category. Categories with ≥ 3 resolved commitments and < 50% follow-through are marked low-reliability.
Pending commitments in those categories get their importance_score boosted 15% (capped at 0.95) so they are more likely to clear the policy engine's threshold and generate a nudge. Every boost is written to decision_log — explain_nudge shows you exactly why.
Reliability Reports
Every Monday at 09:00 (configurable via VIGIL_REPORT_HOUR), Vigil sends a summary of the past week's follow-through, broken down by category:
Past 7 days: 7/10 done (70%)
3 still pending
By category:
✓ work: 4/5 (80%)
✓ personal: 2/3 (67%)
⚠ learning: 1/3 (33%)
Categories marked ⚠ are candidates for Adaptive Policy boosting. Report is deduped by ISO week — it won't re-fire if the process restarts.
Web dashboard
A local dashboard runs at http://localhost:7734 whenever Vigil is active.
- Natural language bar at the top — type "remind me to push the PR before EOD" and press Enter
- Stats: follow-through %, completed, pending, overdue, nudges today
- Commitments grouped by phase with colour-coded left borders
- "Why?" expandable button — full policy decision trace per commitment
- Integrations panel — paste a Slack or Discord webhook URL and save
- V3 Features panel — toggle switches for all 7 features, amber warning when env var is missing
- Auto-refreshes every 30 seconds
- Installable as a PWA (mobile)
Installation
Requirements: Python 3.10+, macOS / Windows / Linux
git clone https://github.com/prodbysilky/vigil-mcp
cd vigil-mcp
python3 -m venv .venv
source .venv/bin/activate
Option A — Claude Desktop (MCP) — simplest
pip install -e .
Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS):
{
"mcpServers": {
"vigil": {
"command": "/absolute/path/to/vigil-mcp/.venv/bin/vigil-mcp"
}
}
}
Or with uvx (no venv needed):
{
"mcpServers": {
"vigil": {
"command": "uvx",
"args": ["vigil-mcp"]
}
}
}
Restart Claude Desktop (Cmd+Q, then reopen). Vigil starts automatically.
Option B — Standalone / ChatGPT / any HTTP client
pip install -e ".[api]"
vigil
The REST API runs at http://localhost:7735. Interactive docs at /docs.
The dashboard runs at http://localhost:7734.
Option C — Hosted mode (public URL, mobile push, auth-protected)
Deploy once, visit from any device, install the PWA to your home screen, get push notifications on your phone. Works on iOS 16.4+ and all Android.
1. Generate VAPID keys (one-time):
pip install -e ".[hosted]"
python -c "from vigil_mcp.push import generate_vapid_keys; \
priv, pub = generate_vapid_keys(); \
print('VIGIL_VAPID_PRIVATE_KEY=' + repr(priv)); \
print('VIGIL_VAPID_PUBLIC_KEY=' + pub)"
2. Deploy to Railway (or Render / Fly — all read $PORT):
- New project → Deploy from GitHub repo
- Set environment variables (see table below)
- Railway auto-detects
Procfile + railway.json; healthcheck hits /manifest.json
3. Set a secret token (so only you can access the dashboard):
VIGIL_SECRET_TOKEN=your-secret-here
Your dashboard URL becomes: https://your-app.up.railway.app/?token=your-secret-here
4. Install on phone:
- Open
https://your-app.up.railway.app/?token=your-secret-here in Safari (iOS) or Chrome (Android)
- "Add to Home Screen"
- Launch from home screen, tap "Enable notifications"
Environment variables
VIGIL_SECRET_TOKEN | Recommended for hosted | Bearer token for dashboard + API auth |
ANTHROPIC_API_KEY | For NL parsing + signal analysis | Powers create_from_text and auto-commitment creation |
VIGIL_VAPID_PRIVATE_KEY | For Web Push | Signs push notifications |
VIGIL_VAPID_PUBLIC_KEY | For Web Push | Sent to browsers for subscription |
VIGIL_VAPID_SUBJECT | For Web Push | mailto:you@example.com (defaults to mailto:admin@example.com) |
VIGIL_SLACK_WEBHOOK | For Slack nudges | Incoming webhook URL (alternative to setting via Claude/dashboard) |
VIGIL_DISCORD_WEBHOOK | For Discord nudges | Webhook URL (alternative to setting via Claude/dashboard) |
VIGIL_SLACK_SIGNING_SECRET | For Slack slash commands | Verifies /vigil commands come from Slack |
VIGIL_FEATURES | Optional | Comma-separated list of V3 features to auto-enable on startup |
VIGIL_IDLE_HOURS | Optional | Hours of inactivity before idle nudge fires (default: 4) |
VIGIL_REPORT_HOUR | Optional | Hour (0–23) for Monday reliability report (default: 9) |
TIMEZONE | Optional | Local timezone for recurring scheduling (default: Europe/Budapest) |
PORT | Set by Railway/Render | Cloud port — auto-detected, do not set manually |
GITHUB_TOKEN | For github_integration feature | Personal access token with repo scope |
GOOGLE_CALENDAR_TOKEN | For calendar_sync feature | OAuth token for Google Calendar API |
VIGIL_SLACK_BOT_TOKEN | For accountability/shared features | Bot token with chat:write scope |
Slack integration
Vigil sends nudges to Slack and accepts /vigil slash commands.
Outbound nudges (via webhook)
- Go to api.slack.com/apps → Create New App → From Scratch
- Incoming Webhooks → Enable → Add to Workspace → pick a channel → copy the URL
- Set in Claude:
set_slack_webhook("https://hooks.slack.com/services/...")
Or paste it in the dashboard Integrations panel.
Inbound slash commands (/vigil remind me to X)
- Slash Commands → Create New Command:
- Command:
/vigil
- Request URL:
https://your-app.up.railway.app/api/slack/command
- Short Description:
Create a Vigil commitment
- Basic Information → Signing Secret → copy it → set
VIGIL_SLACK_SIGNING_SECRET env var
Usage: /vigil remind me to push the PR before EOD
Discord integration
- In Discord: Channel Settings → Integrations → Webhooks → New Webhook → copy URL
- Set in Claude:
set_discord_webhook("https://discord.com/api/webhooks/...")
Or paste it in the dashboard Integrations panel.
Vigil sends rich embeds (amber colour) to the channel whenever a nudge fires.
Example flows
Natural language capture
You: "remind me to push this PR before EOD"
Vigil: parses → description="Push PR", due_by="today 18:00", importance=0.7
→ saved. No form filling needed.
High-importance missed deadline
You: "I'll push this to GitHub before end of day"
Vigil: saves commitment, importance=0.7, due=17:00
[17:00 — no action yet]
Policy: phase=overdue, urgency=0.72, budget=3/10
→ NOTIFY: desktop + Slack: "You said you'd push to GitHub"
[next Claude session]
Claude: "Hey — your GitHub push is overdue. Want to do it now?"
Idle detection escalation
You: "I'll review those PRs this afternoon"
Vigil: saves commitment, due=17:00
[No Claude session opened since 13:00 — 4 hours idle]
Idle: phase=overdue, no session detected
→ PUSH + Slack: "4h idle — PR review is overdue"
Adaptive policy in action
[End of day — adaptive_policy runs]
Policy: "learning" category: 1/4 resolved (25% rate)
→ 3 pending "learning" commitments boosted +15% importance
→ Next policy cycle: importance 0.5 → 0.58, clears threshold
→ Nudge fires that would have been suppressed
Recurring commitment
You: "Every Monday morning I want to review my job applications"
Vigil: saves with recurrence=weekly, recurrence_days=["monday"], recurrence_time="09:00"
[Monday 09:00] → NOTIFY
You: "Done" → complete_commitment → next Monday auto-scheduled
Weekly reliability report
[Monday 09:00]
Vigil: "Past 7 days: 7/10 done (70%)
✓ work: 4/5 (80%)
✓ personal: 2/3 (67%)
⚠ learning: 1/3 (33%)"
REST API
The REST API runs at http://localhost:7735 when fastapi + uvicorn are installed (pip install vigil-mcp[api]). Interactive OpenAPI docs at /docs.
GET | /commitments | List all pending |
POST | /commitments | Save a commitment (structured) |
POST | /commitments/from-text | Create from natural language |
GET | /commitments/{id} | Get one commitment |
PATCH | /commitments/{id} | Edit fields |
POST | /commitments/{id}/complete | Mark done |
POST | /commitments/{id}/snooze | Snooze to new time |
DELETE | /commitments/{id} | Archive |
GET | /commitments/{id}/decisions | Policy decision trace |
GET | /signals | Recent behavioral signals |
POST | /signals | Ingest a signal |
GET | /stats | Overall follow-through stats |
GET | /settings | Current settings |
PUT | /settings/budget | Set daily attention budget |
PUT | /settings/digest | Set daily digest time |
GET | /features | List V3 features |
PUT | /features/{name} | Enable/disable a V3 feature |
All endpoints accept Authorization: Bearer <VIGIL_SECRET_TOKEN> when a token is set.
Logs
tail -f ~/.vigil/vigil.log
grep "action=notify" ~/.vigil/vigil.log
grep "auto_abandoned" ~/.vigil/vigil.log
grep "commitment_id=3" ~/.vigil/vigil.log
grep "adaptive_boost" ~/.vigil/vigil.log
grep "idle_nudge_sent" ~/.vigil/vigil.log
grep "reliability_report_sent" ~/.vigil/vigil.log
Compatibility
| Claude Desktop | pip install -e . → MCP config | Plug-and-play, full tool support |
| Cursor / Cline / Zed | Same as Claude Desktop | Works out of the box |
| ChatGPT Custom GPT | Deploy hosted mode → point GPT Action at /openapi.json | Full CRUD via REST |
| iPhone / Android | Visit hosted URL → Add to Home Screen → enable notifications | PWA + Web Push, no app store |
| Slack | Incoming webhook (outbound) + slash command (inbound) | /vigil creates commitments |
| Discord | Incoming webhook | Nudges as rich embeds |
| Any web app / script | REST API at localhost:7735 or hosted URL | Standard JSON HTTP |
| No AI at all | vigil → open localhost:7734 | Full dashboard UI — add/complete/snooze without any AI |
Why this is different
- Not a reminder app — it reasons about when to interrupt you, not just what to remind you about
- Not a wrapper — the policy engine is the product
- Explainable — every decision is logged and queryable. Ask "why did you message me?" and get the full trace
- Self-tuning — adaptive policy adjusts importance scores based on your actual follow-through behavior
- Idle-aware — knows when you've been away too long and escalates accordingly
- Local-first — all data stays on your machine (SQLite in
~/.vigil/)
- Natural input — type plain English; Vigil figures out the structure
- Extensible — V3 feature flag system lets you add GitHub, calendar, and team features when you need them
Built with
- MCP Python SDK — FastMCP server
- Anthropic SDK — NL parsing via claude-haiku
- SQLite — local-first, thread-safe persistence
- Python stdlib only for webhooks — no extra dependencies for Slack/Discord delivery