███████╗██╗ ██╗ ██████╗ ██████╗ ████████╗██╗ ██╗ █████╗ ███╗ ██╗██████╗ ███╗ ███╗███████╗███╗ ███╗
██╔════╝██║ ██║██╔═══██╗██╔══██╗╚══██╔══╝██║ ██║██╔══██╗████╗ ██║██╔══██╗ ████╗ ████║██╔════╝████╗ ████║
███████╗███████║██║ ██║██████╔╝ ██║ ███████║███████║██╔██╗ ██║██║ ██║ ██╔████╔██║█████╗ ██╔████╔██║
╚════██║██╔══██║██║ ██║██╔══██╗ ██║ ██╔══██║██╔══██║██║╚██╗██║██║ ██║ ██║╚██╔╝██║██╔══╝ ██║╚██╔╝██║
███████║██║ ██║╚██████╔╝██║ ██║ ██║ ██║ ██║██║ ██║██║ ╚████║██████╔╝ ██║ ╚═╝ ██║███████╗██║ ╚═╝ ██║
╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
<p align="center"><strong>Semantic compression for Claude — backed by a local MCP server</strong></p> <p align="center">60–80% fewer tokens · persistent library · diff, merge, summarise · four document domains</p>
<p align="center"> <a href="SKILL.md">Skill Docs</a> · <a href="shorthand-mem.skill">Install Skill</a> · <a href="https://github.com/jai2010/shorthand-mem/issues">Issues</a> </p>
---
What It Does
shorthand-mem compresses verbose documents into a structured symbolic notation (SHM), stores them in a local library, and reconstructs them on demand. It runs as a Claude skill in Claude.ai, backed by a local MCP server that handles all compression, retrieval, and library operations.
The skill itself is a thin routing layer — you type commands in Claude.ai, the skill calls your local MCP server, the server does the work, the result comes back to Claude.
Claude.ai (you type commands here)
│
▼
shorthand-mem MCP server ← runs on your machine
│
├── SQUEEZE → Claude Haiku (compression)
├── EXPAND → Haiku / Sonnet / Opus (your choice, remembered)
├── DIFF → structural token comparison
├── MERGE → combine multiple squeezes
└── SUMMARISE → 5-bullet plain English via Haiku
---
⚠️ What You Need
| Requirement | Why | |---|---| | Claude.ai subscription | To use the skill in chat | | Anthropic API key | The MCP server calls Haiku/Sonnet directly from your machine | | Python 3.10+ | To run the MCP server |
The API key is set once as an environment variable — never stored in any file you push to GitHub. SQUEEZE always uses Haiku (~$0.0003 per 1 000-token document). EXPAND uses your chosen model.
---
Installation
1. Clone and install
git clone https://github.com/jai2010/shorthand-mem.git
cd shorthand-mem
pip install -e .
2. Set your API key
cp .env.example .env
# Edit .env and add your key:
# ANTHROPIC_API_KEY=sk-ant-...
source .env
Or set it permanently in your shell profile: ``bash echo 'export ANTHROPIC_API_KEY=sk-ant-your-key' >> ~/.zshrc ``
3. Register the MCP server with Claude
python install.py
This writes the server config to ~/.claude/claude_desktop_config.json (Claude Desktop) and ~/.config/claude/mcp.json (Claude Code). Restart Claude after running.
To uninstall: ``bash python install.py uninstall ``
4. Install the skill in Claude.ai
- Download
shorthand-mem.skill - Go to Claude.ai → Settings → Skills
- Click Install Skill and upload the file
---
Commands
| Command | What It Does | Model | |---|---|---| | SQUEEZE PRD \| CODE \| PAPER \| MEETING <text> | Compress document into SHM notation | Haiku (always) | | EXPAND [label or SHM block] | Reconstruct full prose | Your preference | | SET MODEL haiku \| sonnet \| opus | Save EXPAND model preference | — | | LIST SQUEEZES | Show library with compression stats | — | | RECALL [label] | Retrieve a saved squeeze | — | | SEARCH [keyword or RISK( or REQ:] | Search library — keyword or token-level | — | | DELETE [label] | Remove a squeeze (asks for confirmation) | — | | EXPORT ALL | Dump full library to .shm file | — | | DIFF [label1] [label2] | Structural diff between two versions | — | | MERGE [label1] [label2] ... | Combine squeezes under SCOPE headers | — | | SUMMARISE [label] | 5-bullet executive summary (lossy) | Haiku (always) |
---
Token Reference
Universal — All Domains
| Token | Meaning | |---|---| | OBJ(Name) | Core entity, system, module, or actor | | SCOPE: Name | Module or domain boundary | | GOAL(Action) | Primary intent | | REQ: action() | Strict functional mandate | | RULE: constraint | Business logic, rate limit, or guardrail | | DEP(X) | Dependency — ++ for hard/critical | | RISK(Factor) | Failure mode — ++ for high severity | | ERR(Type) → THROW(Behaviour) | Failure boundary |
Conditional syntax: `` IF (condition) → THEN (action) ! EXCEPT (override_condition) ELSE → (fallback_action) ``
PAPER Domain
| HYP | METH | RESULT | LIMIT | |---|---|---|---| | Hypothesis | Methodology | Outcome | Limitation |
MEETING Domain
| Token | Meaning | |---|---| | DEC(Decision) | Decision made | | ACT(Owner → Action → Date) | Action item with owner and due date | | ESC(Risk → Owner) | Escalation raised | | BLOCK(Item → Blocker → ETA) | Blocker with expected resolution |
---
Full Example: PRD Compression
Input (~880 tokens)
The Notification Delivery Service (NDS) routes alerts across in-app, email, and push. Critical notifications must be delivered within 5 seconds; Standard within 60 seconds. Email is routed through SendGrid — on a 5xx error or 3-second timeout, retry up to 3 times with exponential backoff starting at 500ms. After 3 failures, write to DeadLetterQueue and page PagerDuty. Push via FCM — if
push_enabled=false, skip silently. If FCM returns token-expired, delete the stale token from UserDevices and skip. Hard dependency on UserPreferences — if unavailable, suspend all dispatches and queue for replay. Soft dependency on Analytics — if unavailable, send notification but drop the delivery event with a warning log. Rate limit: 50 notifications/user/hr across all channels. Excess: silently dropped + EventLog entry. Critical delivery failures must escalate to the engineering lead immediately.
SQUEEZE PRD output (~195 tokens — 78% reduction)
@ASSET:PRD | @TARGET:60-80% | @CCR:a3f2b1c9 | @DATE:2025-06-24
OBJ(Notification_Delivery_Svc)
GOAL: Multi_channel_alert_routing(in-app, email, push)
IF (priority == Critical) → THEN (deliver <= 5s)
IF (priority == Standard) → THEN (deliver <= 60s)
REQ: Email_via_SendGrid
ERR(SendGrid_5xx || timeout>3s) → RETRY x3 | backoff(500ms, exponential)
IF (retry_count == 3 && fail) → WRITE(DeadLetterQueue) + PAGE(PagerDuty)
RULE: user.push_enabled == false → SKIP silently
ERR(FCM_token_expired) → DELETE(UserDevices.token) + SKIP
DEP(UserPreferences_Svc)++ → IF (unavailable) → SUSPEND_ALL + QUEUE_replay
RULE: NO notification WITHOUT confirmed_preference_lookup
DEP(Analytics_Svc) → IF (unavailable) → SEND + DROP(delivery_event) + WARN_LOG
REQ: RateLimit == 50 notifications/user/hr (all channels)
IF (rate_exceeded) → DROP silently + WRITE(EventLog.RateLimitExceeded)
RISK(Critical_delivery_failure)++ → ESCALATE(engineering_lead)
📊 Compression: ~880 → ~195 tokens (78% reduction) 🎯 Fidelity: 📅 0/0 dates · 💰 2/2 amounts · 🚦 0/0 statuses · 👤 6/6 entities
---
MEETING Domain Example
SQUEEZE MEETING
Attendees: Jai, Priya, Rohan
Decision: Migrate billing to Stripe by Q3 2025.
Action: Rohan to complete API contract by Jul 15.
Action: Priya to sign off on compliance review by Jul 10.
Blocker: Legal approval pending — ETA Jul 8.
Escalation: Stripe SLA risk escalated to CTO.
@ASSET:MEETING | @TARGET:60-80% | @CCR:b7e3d2f1 | @DATE:2025-06-24
OBJ(Billing_Migration_Meeting)
DEC(Migrate billing to Stripe by Q3 2025)
ACT(Rohan → Complete API contract → Jul 15)
ACT(Priya → Sign off compliance review → Jul 10)
BLOCK(Legal_approval → Pending → Jul 8)
ESC(Stripe_SLA_risk → CTO)
📊 Compression: ~196 → ~42 tokens (79% reduction) 🎯 Fidelity: 📅 3/3 dates · 💰 0/0 amounts · 🚦 0/0 statuses · 👤 3/3 entities
---
DIFF Example
Track what changed week-over-week in a SteerCo doc:
DIFF MEETING_steerco_2025-06-17 MEETING_steerco_2025-06-24
Summary: 🟢 2 added · 🔴 1 removed · 🟡 1 changed · ⚪ 8 unchanged
🟢 Added
+ ACT(Priya → Sign off compliance review → Jul 10)
+ ESC(Stripe_SLA_risk → CTO)
🔴 Removed
- BLOCK(Procurement → Vendor shortlist → Jun 28)
🟡 Changed
before: DEC(Evaluate Stripe migration)
after: DEC(Migrate billing to Stripe by Q3 2025)
---
Token-Level SEARCH
Search your entire library for all instances of a specific token type:
SEARCH RISK( → all risks across all squeezes
SEARCH DEC( → all decisions across all meetings
SEARCH REQ: → all requirements across all PRDs
SEARCH ACT(Rohan → all actions assigned to Rohan
---
Persistence & Library
LIST SQUEEZES
| # | Label | Domain | Date | Original | Compressed | Saved |
|---|-----------------------------------|---------|------------|------------|------------|-------|
| 1 | PRD_notification_delivery_2025-06 | PRD | 2025-06-24 | ~880 tok | ~195 tok | 78% |
| 2 | MEETING_billing_migration_2025-06 | MEETING | 2025-06-24 | ~196 tok | ~42 tok | 79% |
| 3 🧩 | PRD_large_spec_2025-06-24 | PRD | 2025-06-24 | ~12,400 tok| ~890 tok | 93% |
🧩 = document was automatically chunked (exceeded single-context limit)
All squeezes stored at ~/.shorthand-mem/library.json. Original documents cached at ~/.shorthand-mem/ccr/ for lossless retrieval.
---
File Structure
shorthand-mem/
├── SKILL.md ← Skill instructions (install in Claude.ai)
├── shorthand-mem.skill ← Packaged skill file
├── install.py ← One-command MCP registration
├── requirements.txt
├── setup.py
├── .env.example ← API key template
└── server/
├── main.py ← MCP server entry point (FastMCP)
├── store.py ← Library, Settings, CCR store
├── utils.py ← Chunking, fidelity, labelling, SHA-8
└── tools/
├── squeeze.py ← Haiku compression + chunking + fidelity
├── expand.py ← Model-selectable expansion
├── library.py ← LIST, RECALL, SEARCH, DELETE, EXPORT
├── diff.py ← Structural token diff
├── merge.py ← Multi-block merge
└── summarise.py ← 5-bullet executive summary
---
Cost Reference
| Operation | Model | Approx. cost per 1 000-token doc | |---|---|---| | SQUEEZE | Haiku | ~$0.0003 | | EXPAND | Haiku | ~$0.0003 | | EXPAND | Sonnet | ~$0.003 | | EXPAND | Opus | ~$0.015 | | SUMMARISE | Haiku | ~$0.0001 |
Once compressed, RECALL, SEARCH, LIST, DIFF, and MERGE are free (no API calls).
---
License
MIT











