google-agents-cli-scaffold
Project scaffolding, deployment configuration, and CI/CD setup for Google ADK agents.
beeper-mcp
Unified messaging via Beeper Desktop MCP. Search chats, send messages, manage conversations across all networks (iMessage, WhatsApp, Signal, Telegram, Discord, Slack, etc.)
Full skill instructions
Every output token must produce actionable value. Violations:
When reviewing message history:
Enforcement: If output contains summary without artifact, STOP and create the artifact first.
Access all messaging networks through Beeper's unified interface.
# Search for a chat
mcp__beeper__search "contact name"
# Send a message
mcp__beeper__send_message chatID="..." text="Hello!"
# List recent chats
mcp__beeper__search_chats limit=10
| Tool | Purpose |
|---|---|
search | Find chats, groups, or people by name |
search_chats | List/filter chats by type, inbox, activity |
search_messages | Find messages by content (literal match) |
get_chat | Get chat details and participants |
list_messages | Get messages from a specific chat |
send_message | Send text message to a chat |
archive_chat | Archive/unarchive a chat |
set_chat_reminder | Set reminder for a chat |
focus_app | Open Beeper Desktop to specific chat |
CRITICAL: Queries are LITERAL WORD MATCHING, not semantic search.
query="dinner" or query="flight"query="dinner plans tonight" or query="travel arrangements"Multiple words = ALL must match. Use single keywords.
IMPORTANT: Beeper/Matrix has TWO identifiers per user:
@username:beeper.com (permanent, searchable)Example: User @jsmith:beeper.com may have display name "John Smith"
When search finds a match:
list_messages and check senderID fieldWhen reporting search results:
list_messages to map senderID ↔ senderNameCRITICAL: Always work backwards from most recent messages to avoid:
// 1. Start with most recent (no cursor = newest first)
const recent = await list_messages(chatID, { limit: 20 });
// 2. Check if already processed (use DuckDB tracking)
const unprocessed = recent.items.filter(msg => !isProcessed(msg.id));
// 3. Process only new messages
for (const msg of unprocessed) {
await processMessage(msg);
markProcessed(msg.id);
}
// 4. If need more history, paginate backwards
if (needsMoreContext) {
const older = await list_messages(chatID, {
cursor: recent.cursor,
direction: 'before',
limit: 20
});
}
CREATE TABLE IF NOT EXISTS beeper_processed_messages (
message_id VARCHAR PRIMARY KEY,
chat_id VARCHAR,
processed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
task_extracted BOOLEAN,
issue_status VARCHAR -- 'open', 'fixed', 'duplicate'
);
CREATE INDEX idx_msg_chat ON beeper_processed_messages(chat_id, processed_at DESC);
function isAlreadyFixed(messageText) {
// Query DuckDB for similar fixed issues
const similar = db.query(`
SELECT issue_id, description
FROM fixed_issues
WHERE description % ? -- Full-text similarity
LIMIT 1
`, [messageText]);
if (similar.length > 0) {
console.warn(`⚠️ Similar issue already fixed: ${similar[0].description}`);
return true;
}
return false;
}
search "person name" - Get chatIDlist_messages chatID="..." limit=5 - Check recent messages ONLYsend_message chatID="..." text="..."list_messages chatID="..." limit=10 - Get RECENT messages only (not entire history)search_chats to get chatIDs of relevant chatssearch_messages chatIDs=[...] query="keyword" limit=20 dateAfter="2026-01-08T00:00:00Z"search_chats unreadOnly=true inbox="primary" limit=10
Use accountIDs parameter after getting accounts via get_accounts.
Messages support Markdown. Use sparingly for clarity.
single - Direct messages (1:1)group - Group chatsany - All typesprimary - Non-archived, non-low-prioritylow-priority - Low priority inboxarchive - Archived chatsNEVER pull full message history into context. Instead:
-- Store messages incrementally, query locally
CREATE TABLE IF NOT EXISTS beeper_messages (
id VARCHAR PRIMARY KEY,
chat_id VARCHAR,
sender_id VARCHAR,
sender_name VARCHAR,
text TEXT,
timestamp TIMESTAMPTZ,
processed BOOLEAN DEFAULT FALSE
);
-- Sample recent messages via random walk
SELECT * FROM beeper_messages
WHERE chat_id = ?
ORDER BY RANDOM() -- Ergodic sampling
LIMIT 5;
# Extract code blocks from messages without loading full text
tree-sitter parse --scope source.markdown message.md \
| grep -E "(fenced_code_block|code_span)"
MINUS (-1): Validate message exists in DuckDB before fetching
ERGODIC (0): Random walk sample from local cache
PLUS (+1): Fetch ONLY if not in cache, with strict limit
CONTEXT_BUDGET = 10000 # chars
current_context = 0
def safe_fetch(chat_id, limit=5):
# Check DuckDB cache first
cached = db.query("SELECT * FROM beeper_messages WHERE chat_id = ? LIMIT ?", chat_id, limit)
if len(cached) >= limit:
return cached # Zero network cost
# Fetch only missing, with limit
remaining = limit - len(cached)
fresh = mcp__beeper__list_messages(chatID=chat_id, limit=remaining)
# Enforce budget
for msg in fresh.items:
msg_size = len(msg.get('text', ''))
if current_context + msg_size > CONTEXT_BUDGET:
break
current_context += msg_size
db.insert("beeper_messages", msg)
return db.query("SELECT * FROM beeper_messages WHERE chat_id = ? LIMIT ?", chat_id, limit)
;; Don't fetch until actually needed
(define (beeper-messages chat-id)
(delay
(mcp__beeper__list_messages chatID: chat-id limit: 5)))
;; Only force when required
(define (get-latest-sender chat-id)
(let ((msgs (force (beeper-messages chat-id))))
(cdar msgs))) ; Just sender from first message
This skill operates as ERGODIC (0) in triadic compositions:
| Trit | Role | Beeper Action |
|---|---|---|
| MINUS (-1) | Validator | Check DuckDB cache, reject if stale |
| ERGODIC (0) | Coordinator | Random walk sample, enforce budget |
| PLUS (+1) | Generator | Fetch fresh data, strict limit param |
Track conversation threads as wiring diagrams - morphisms between topic states.
CREATE TABLE IF NOT EXISTS beeper_conversation_branches (
branch_id VARCHAR PRIMARY KEY,
chat_id VARCHAR NOT NULL,
parent_branch_id VARCHAR, -- NULL for root
topic VARCHAR NOT NULL,
first_message_id VARCHAR,
last_message_id VARCHAR,
status VARCHAR DEFAULT 'open', -- 'open', 'resolved', 'merged', 'stale'
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
resolved_at TIMESTAMP,
FOREIGN KEY (parent_branch_id) REFERENCES beeper_conversation_branches(branch_id)
);
CREATE TABLE IF NOT EXISTS beeper_branch_transitions (
from_branch VARCHAR,
to_branch VARCHAR,
transition_type VARCHAR, -- 'fork', 'merge', 'abandon', 'resolve'
message_id VARCHAR, -- message that triggered transition
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (from_branch, to_branch, message_id)
);
Conversation as Category:
- Objects: Topic states (branches)
- Morphisms: Message sequences that transform one topic to another
- Composition: Thread continuation
┌─────────────────┐
│ patents (open) │◄──── current focus
└────────┬────────┘
│ fork @ msg:838941332
┌───────────────┼───────────────┐
▼ ▼ ▼
┌────────┐ ┌───────────┐ ┌──────────┐
│ GF(3) │ │bisimulation│ │ toad OOM │
│resolved│ │ resolved │ │ open │
└────────┘ └───────────┘ └──────────┘
def detect_branch(messages: list) -> list[Branch]:
branches = []
current_topic = None
for msg in messages:
# Topic markers
if msg.text.startswith('**Re:') or msg.text.startswith('Re:'):
# Explicit reply = potential branch
topic = extract_topic(msg.text)
if topic != current_topic:
branches.append(Branch(
topic=topic,
fork_message=msg.id,
parent=current_topic
))
# Numbered lists often indicate parallel threads
if re.match(r'^\d+\.', msg.text):
items = extract_numbered_items(msg.text)
for item in items:
branches.append(Branch(topic=item, parent=current_topic))
# Questions create potential branches
if msg.text.strip().endswith('?'):
branches.append(Branch(
topic=f"Q: {msg.text[:50]}",
status='awaiting_response'
))
return branches
Track active branches in zigger conversation:
-- Query current branch state for a chat
SELECT
b.branch_id,
b.topic,
b.status,
COUNT(t.to_branch) as child_count
FROM beeper_conversation_branches b
LEFT JOIN beeper_branch_transitions t ON b.branch_id = t.from_branch
WHERE b.chat_id = '!NhltGRLZWLUeHEBiFT:beeper.com' -- zigger
GROUP BY b.branch_id
ORDER BY b.created_at DESC;
def get_branch_context(chat_id: str) -> dict:
"""Always call before responding to understand conversation topology."""
# Get open branches
open_branches = db.query("""
SELECT topic, status, first_message_id
FROM beeper_conversation_branches
WHERE chat_id = ? AND status = 'open'
""", chat_id)
# Get unresolved questions
questions = db.query("""
SELECT topic FROM beeper_conversation_branches
WHERE chat_id = ? AND topic LIKE 'Q:%' AND status = 'awaiting_response'
""", chat_id)
return {
'open_branches': open_branches,
'unanswered_questions': questions,
'should_address': questions[0] if questions else open_branches[0]
}
When reviewing messages, branch tracking prevents:
Update branch state as side effect of every beeper interaction.
{
"beeper": {
"command": "/bin/sh",
"args": [
"-c",
"BEEPER_ACCESS_TOKEN=$(/Users/alice/.cargo/bin/fnox get BEEPER_ACCESS_TOKEN --age-key-file /Users/alice/.age/key.txt) exec npx -y @beeper/desktop-mcp"
]
}
}
Requires:
fnox at /Users/alice/.cargo/bin/fnox/Users/alice/.age/key.txtnpx in PATHProject scaffolding, deployment configuration, and CI/CD setup for Google ADK agents.
Set up tracing, logging, and monitoring for deployed ADK agents across Cloud Trace, BigQuery, and third-party platforms.
Enterprise Azure infrastructure architect generating Bicep or Terraform from workload descriptions.
Plan and configure production-ready Azure Kubernetes Service clusters with Day-0 and Day-1 best practices.
Raw mechanical interfaces fusing Swiss typographic print with military terminal aesthetics. Rigid grids, extreme type scale contrast, utilitarian color, analog degradation effects. For data-heavy dashboards, portfolios, or editorial sites that need to feel like declassified blueprints.
Web search, scraping, extraction, crawling, and monitoring via ScrapeGraph AI CLI.
Skill for working with Firebase Hosting (Classic). Use this when you want to deploy static web apps, Single Page Apps (SPAs), or simple microservices. Do NOT use for Firebase App Hosting.
Deploy and manage web apps with Firebase App Hosting. Use this skill when deploying Next.js/Angular apps with backends.
Deploy applications and websites to Vercel. Use when the user requests deployment actions like "deploy my app", "deploy and give me the link", "push this live", or "create a preview deployment".
Build SEO-optimized pages at scale using templates, data, and proven playbook patterns.
Design and build isolated, reusable Convex backend components with clear boundaries and app-facing wrappers.
Deploy and manage projects on Vercel using token-based authentication. Use when working with Vercel CLI using access tokens rather than interactive login — e.g. "deploy to vercel", "set up vercel", "add environment variables to vercel".
Opus.ai: Revolutionize Your Web Experience
Build a no-code AI app in minutes.
An IDE for code migration from legacy to modern frameworks through coding agents.
Automate CGI animation in live-action scenes
Branded artistic QR-code concepts
Launch a website in seconds with AI.
Streamline Your Coding Experience with AI Code Helper
Convert any screenshot or design to clean code.