Skill flagged — suspicious patterns detected

ClawHub Security flagged this skill as suspicious. Review the scan results before using.

Nate Jones Second Brain

v1.0.2

Set up and operate a personal knowledge system using Supabase (pgvector) and OpenRouter. Five structured tables — thoughts (inbox log), people, projects, ide...

0· 753·1 current·2 all-time
byLimited Edition Jonathan@justfinethanku
Security Scan
VirusTotalVirusTotal
Suspicious
View report →
OpenClawOpenClaw
Benign
medium confidence
Purpose & Capability
The name/description (Supabase + pgvector + OpenRouter) matches the declared requirements and instructions. SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY and OPENROUTER_API_KEY are exactly what the documented pipeline needs (REST calls to Supabase and API calls to OpenRouter). No unrelated credentials, binaries, or installs are requested.
Instruction Scope
SKILL.md and reference docs contain explicit runtime instructions (curl commands) to: create embeddings and call the LLM at openrouter.ai, insert rows into Supabase, run upserts/patches, and update audit rows. The instructions do not attempt to read other files or unrelated env vars, but they do send user-captured text to OpenRouter (external). The docs warn about this, but it remains a privacy/data-exfiltration consideration.
Install Mechanism
Instruction-only skill with no install spec and no code files. Lowest install risk — nothing is written to disk by the skill package itself.
!
Credentials
Only three env vars are required and they are relevant, but SUPABASE_SERVICE_ROLE_KEY is a full privileged key (can bypass Row Level Security and access/modify all database data). The README justifies its use for a single-user server-side flow, but exposing that key to an agent runtime or storing it in an agent config increases blast radius if the agent or environment is compromised. OPENROUTER_API_KEY sends data to a third party; the docs note this but users must accept that captured content will leave their environment.
Persistence & Privilege
The skill does not request permanent platform-wide inclusion (always:false) and does not modify other skills or system settings. Autonomous invocation is enabled (default) which is expected for skills; combined with a privileged service_role key it increases potential impact, but autonomy alone is not unusual.
Assessment
This skill appears to be what it says, but take these precautions before installing: - Treat the Supabase service_role key as highly sensitive. Prefer not to expose it directly to client/agent runtimes. Instead host a small server-side proxy or function that holds the service_role key and exposes only the minimal endpoints the agent needs (or use anon key + strict RLS if feasible). - Use a dedicated Supabase project for this skill (do not put production or sensitive databases behind the same key). Rotate/revoke the service_role key after testing. - Remember captured text is sent to OpenRouter. Avoid sending sensitive PII, secrets, or confidential content unless you accept the third-party handling. - Test the full pipeline with non-sensitive test data first and verify RLS and access patterns in Supabase. Confirm OpenRouter model/data retention/privacy settings match your requirements. - If you cannot run a server-side proxy, at minimum limit the agent’s environment access, lock down storage of keys (avoid committing to repos), and consider short-lived keys/automated rotation. If any of the above concerns are unacceptable to you, do not install or run this skill.

Like a lobster shell, security has layers — review code before you run it.

Runtime requirements

EnvSUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY, OPENROUTER_API_KEY
latestvk978vvcsskwhhkxtv4yrbnrwen81bj8b
753downloads
0stars
3versions
Updated 15h ago
v1.0.2
MIT-0

Nate Jones Second Brain

When intelligence is abundant, context becomes the scarce resource. This skill is context architecture — a persistent, searchable knowledge layer that turns your agent into a personal knowledge manager.

Two opinionated primitives:

  • Supabase — your database, and so much more. PostgreSQL + pgvector. Stores thoughts, people, projects, ideas, and tasks as structured data with vector embeddings. REST API built in. Your data, your infrastructure. Models come and go; your context persists. And once you have a Supabase project, you've unlocked the foundation for everything else you'll want to build — the Second Brain is just the beginning.
  • OpenRouter — your AI gateway. One API key, every model. Embeddings and LLM calls for classification and routing. Swap models by changing a string. Future-proof by design.

Everything else — how you capture thoughts, how you retrieve them, what you build on top — is application layer. The skill covers the foundation.

If the tables don't exist yet, see {baseDir}/references/setup.md

Building Blocks

These are the operational concepts behind the system. Understanding them helps you operate correctly.

BlockWhat It DoesImplementation
Drop BoxOne frictionless capture pointEverything goes to thoughts first
SorterAI classification + routingLLM classifies type, then routes to structured table
FormConsistent data contractsEach table has a defined schema
Filing CabinetSource of truth per categorypeople, projects, ideas, admin tables
BouncerConfidence thresholdconfidence < 0.6 = don't route, stay in inbox
ReceiptAudit trailthoughts row logs what came in, where it went
Tap on the ShoulderProactive surfacingDaily digest queries (application layer)
Fix ButtonAgent-mediated correctionsMove records between tables on user request

Full conceptual framework: {baseDir}/references/concepts.md

Five Tables

TableRoleKey Fields
thoughtsInbox Log / audit trailcontent, embedding, metadata (type, topics, people, confidence, routed_to)
peopleRelationship trackingname (unique), context, follow_ups, tags, embedding
projectsWork trackingname, status, next_action, notes, tags, embedding
ideasInsight capturetitle, summary, elaboration, topics, embedding
adminTask managementname, due_date, status, notes, embedding

Every table has semantic search via its own match_* function. Cross-table search via search_all.

Routing Rules

When a thought is classified:

TypeRouteAction
person_notepeopleUpsert: create person or append to existing context
taskadminInsert new task (status=pending)
ideaideasInsert new idea
observationnoneStays in thoughts only
referencenoneStays in thoughts only

If confidence < 0.6, don't route. Leave in thoughts, tell user.

Quick Start

Capture a thought (full pipeline)

# 1. Embed
EMBEDDING=$(curl -s -X POST "https://openrouter.ai/api/v1/embeddings" \
  -H "Authorization: Bearer $OPENROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "openai/text-embedding-3-small", "input": "Sarah mentioned she is thinking about leaving her job to start consulting"}' \
  | jq -c '.data[0].embedding')

# 2. Classify (run in parallel with step 1)
METADATA=$(curl -s -X POST "https://openrouter.ai/api/v1/chat/completions" \
  -H "Authorization: Bearer $OPENROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "openai/gpt-4o-mini", "response_format": {"type": "json_object"}, "messages": [{"role": "system", "content": "Extract metadata from the captured thought. Return JSON with: type (observation/task/idea/reference/person_note), topics (1-3 tags), people (array), action_items (array), dates_mentioned (array), confidence (0-1), suggested_route (people/projects/ideas/admin/null), extracted_fields (structured data for destination table)."}, {"role": "user", "content": "Sarah mentioned she is thinking about leaving her job to start consulting"}]}' \
  | jq -r '.choices[0].message.content')

# 3. Store in thoughts (the Receipt)
curl -s -X POST "$SUPABASE_URL/rest/v1/thoughts" \
  -H "apikey: $SUPABASE_SERVICE_ROLE_KEY" \
  -H "Authorization: Bearer $SUPABASE_SERVICE_ROLE_KEY" \
  -H "Content-Type: application/json" \
  -H "Prefer: return=representation" \
  -d "[{\"content\": \"Sarah mentioned she is thinking about leaving her job to start consulting\", \"embedding\": $EMBEDDING, \"metadata\": $METADATA}]"

# 4. Route based on classification (if confidence >= 0.6)

Full pipeline with routing logic: {baseDir}/references/ingest.md

Semantic search (single table)

QUERY_EMBEDDING=$(curl -s -X POST "https://openrouter.ai/api/v1/embeddings" \
  -H "Authorization: Bearer $OPENROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "openai/text-embedding-3-small", "input": "career changes"}' \
  | jq -c '.data[0].embedding')

curl -s -X POST "$SUPABASE_URL/rest/v1/rpc/match_thoughts" \
  -H "apikey: $SUPABASE_SERVICE_ROLE_KEY" \
  -H "Authorization: Bearer $SUPABASE_SERVICE_ROLE_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"query_embedding\": $QUERY_EMBEDDING, \"match_threshold\": 0.5, \"match_count\": 10, \"filter\": {}}"

Cross-table search

curl -s -X POST "$SUPABASE_URL/rest/v1/rpc/search_all" \
  -H "apikey: $SUPABASE_SERVICE_ROLE_KEY" \
  -H "Authorization: Bearer $SUPABASE_SERVICE_ROLE_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"query_embedding\": $QUERY_EMBEDDING, \"match_threshold\": 0.5, \"match_count\": 20}"

Returns table_name, record_id, label, detail, similarity, created_at from all tables.

List active projects

curl -s "$SUPABASE_URL/rest/v1/projects?status=eq.active&select=name,next_action,notes&order=updated_at.desc" \
  -H "apikey: $SUPABASE_SERVICE_ROLE_KEY" \
  -H "Authorization: Bearer $SUPABASE_SERVICE_ROLE_KEY"

List pending tasks

curl -s "$SUPABASE_URL/rest/v1/admin?status=eq.pending&select=name,due_date,notes&order=due_date.asc" \
  -H "apikey: $SUPABASE_SERVICE_ROLE_KEY" \
  -H "Authorization: Bearer $SUPABASE_SERVICE_ROLE_KEY"

Ingest Pipeline

When content arrives from any source:

  1. Embed the text via OpenRouter (1536-dim vector)
  2. Classify via OpenRouter LLM (type, topics, people, confidence, suggested route)
  3. Log in thoughts (the Receipt — always, regardless of routing)
  4. Bounce check — if confidence < 0.6, stop here
  5. Route to structured table based on type (the Sorter)
  6. Confirm to the user what was captured and where it was filed

Full pipeline details: {baseDir}/references/ingest.md

Metadata Schema

Every thought gets classified with:

FieldTypeValues
typestringobservation, task, idea, reference, person_note
topicsstring[]1-3 short topic tags (always at least one)
peoplestring[]People mentioned (empty if none)
action_itemsstring[]Implied to-dos (empty if none)
dates_mentionedstring[]Dates in YYYY-MM-DD format (empty if none)
sourcestringWhere it came from: slack, signal, cli, manual, etc.
confidencefloatLLM classification confidence (0-1). The Bouncer uses this.
routed_tostringWhich table the thought was filed into (null if unrouted)
routed_idstringUUID of the record in the destination table (null if unrouted)

References

  • Conceptual framework: {baseDir}/references/concepts.md
  • First-time setup: {baseDir}/references/setup.md
  • Database schema (SQL): {baseDir}/references/schema.md
  • Ingest pipeline details: {baseDir}/references/ingest.md
  • Retrieval operations: {baseDir}/references/retrieval.md
  • OpenRouter API patterns: {baseDir}/references/openrouter.md

Env Vars

VariableService
SUPABASE_URLSupabase project REST base URL
SUPABASE_SERVICE_ROLE_KEYSupabase auth (full access)
OPENROUTER_API_KEYOpenRouter API key

Security Notes

Why service_role key? Supabase provides two keys: anon (public, respects RLS) and service_role (full access, bypasses RLS). This skill uses service_role because:

  • This is a single-user personal knowledge base, not a multi-tenant app
  • Your agent IS the trusted server-side component
  • The RLS policy restricts access to service_role only — the most restrictive option
  • Using the anon key would require loosening RLS to allow anonymous access to your thoughts, which is worse

Data sent to OpenRouter: All captured text (thoughts, names, action items) is sent to OpenRouter for embedding and classification. This is inherent to the design — you need AI to understand meaning. Don't capture highly sensitive information unless you accept OpenRouter's data handling policies.

Key handling: Store SUPABASE_SERVICE_ROLE_KEY and OPENROUTER_API_KEY securely. Never commit them to public repos. Rotate periodically. In OpenClaw, store them in openclaw.json under skills.entries or as environment variables.


Built by Limited Edition Jonathan • natebjones.com

Comments

Loading comments...