skills/google-drive-knowledge-bank/SKILL.md
Build and query a knowledge bank from Google Docs meeting notes. Use when the user wants to ingest meeting notes from Google Drive, or when answering questions about previously ingested meeting notes. Trigger on phrases like "ingest my meeting notes", "load meeting notes from folder", "what did we discuss about X" (after ingestion), "find information about Y in meeting notes", "build knowledge base from meetings". Always use this skill when working with a corpus of meeting notes that needs to be searchable.
npx skillsauth add agentlyhq/skills google-drive-knowledge-bankInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Transform a folder of Google Docs meeting notes into a queryable knowledge bank. This skill ingests meeting notes, parses them into structured format, and stores them for fast, accurate retrieval when answering questions.
Pull meeting notes from Google Drive, parse their content, and store as structured data.
Search the stored knowledge bank to answer questions accurately, always grounding responses in the actual meeting content.
This skill requires the Google Workspace CLI (gws):
# Check if installed
gws --version
# If not installed
npm install -g @googleworkspace/cli
# Authenticate
gws auth login
# Verify access
gws drive files list --max-results 5
Ask the user for their meeting notes folder. They can provide:
Find folder by name:
gws drive files search \
--query "name = 'Meeting Notes' and mimeType = 'application/vnd.google-apps.folder'" \
--format json
Extract folder ID from URL:
URL format: https://drive.google.com/drive/folders/FOLDER_ID
# Get all Google Docs in the folder
gws drive files list \
--parent-id "FOLDER_ID" \
--query "mimeType = 'application/vnd.google-apps.document'" \
--format json > /tmp/meeting_files_list.json
# Parse to see what we got
cat /tmp/meeting_files_list.json | jq -r '.files[] | "\(.name) | \(.id) | \(.modifiedTime)"'
# Create knowledge bank directory
mkdir -p /tmp/knowledge_bank
# Parse file list and export each document
FILE_IDS=($(cat /tmp/meeting_files_list.json | jq -r '.files[].id'))
for file_id in "${FILE_IDS[@]}"; do
# Get file metadata
FILE_NAME=$(cat /tmp/meeting_files_list.json | jq -r ".files[] | select(.id == \"$file_id\") | .name")
MODIFIED=$(cat /tmp/meeting_files_list.json | jq -r ".files[] | select(.id == \"$file_id\") | .modifiedTime")
# Export as plain text
echo "Ingesting: $FILE_NAME"
gws drive files export \
--file-id "$file_id" \
--mime-type "text/plain" \
--output-file "/tmp/knowledge_bank/${file_id}.txt"
# Store metadata
echo "$file_id|$FILE_NAME|$MODIFIED" >> /tmp/knowledge_bank/metadata.txt
done
echo "✓ Ingested ${#FILE_IDS[@]} meeting notes"
For each meeting note, extract structured information:
# Create parsed knowledge base
mkdir -p /tmp/knowledge_bank/parsed
for file in /tmp/knowledge_bank/*.txt; do
if [ "$file" = "/tmp/knowledge_bank/metadata.txt" ]; then
continue
fi
FILE_ID=$(basename "$file" .txt)
# Read full content
CONTENT=$(cat "$file")
# Parse metadata from content (filename pattern: "Meeting Type - YYYY-MM-DD")
METADATA=$(grep "$FILE_ID" /tmp/knowledge_bank/metadata.txt)
FILE_NAME=$(echo "$METADATA" | cut -d'|' -f2)
MODIFIED=$(echo "$METADATA" | cut -d'|' -f3)
# Extract meeting date from filename if present
MEETING_DATE=$(echo "$FILE_NAME" | grep -oE '[0-9]{4}-[0-9]{2}-[0-9]{2}' || echo "unknown")
# Create structured JSON entry
cat > "/tmp/knowledge_bank/parsed/${FILE_ID}.json" <<EOF
{
"file_id": "$FILE_ID",
"filename": "$FILE_NAME",
"meeting_date": "$MEETING_DATE",
"modified_time": "$MODIFIED",
"content": $(echo "$CONTENT" | jq -Rs .),
"word_count": $(echo "$CONTENT" | wc -w),
"indexed_at": "$(date --iso-8601=seconds)"
}
EOF
done
echo "✓ Parsed and structured all meeting notes"
Build a searchable index with keywords:
# Create index file
echo "# Meeting Notes Knowledge Bank Index" > /tmp/knowledge_bank/INDEX.md
echo "Generated: $(date)" >> /tmp/knowledge_bank/INDEX.md
echo "" >> /tmp/knowledge_bank/INDEX.md
# List all meetings
echo "## Meetings Indexed" >> /tmp/knowledge_bank/INDEX.md
echo "" >> /tmp/knowledge_bank/INDEX.md
for json_file in /tmp/knowledge_bank/parsed/*.json; do
FILE_NAME=$(jq -r '.filename' "$json_file")
MEETING_DATE=$(jq -r '.meeting_date' "$json_file")
WORD_COUNT=$(jq -r '.word_count' "$json_file")
FILE_ID=$(jq -r '.file_id' "$json_file")
echo "- **$FILE_NAME** ($MEETING_DATE) - $WORD_COUNT words - ID: $FILE_ID" >> /tmp/knowledge_bank/INDEX.md
done
echo "" >> /tmp/knowledge_bank/INDEX.md
echo "Total meetings: $(ls /tmp/knowledge_bank/parsed/*.json | wc -l)" >> /tmp/knowledge_bank/INDEX.md
cat /tmp/knowledge_bank/INDEX.md
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "✓ KNOWLEDGE BANK READY"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Location: /tmp/knowledge_bank/"
echo "Meetings indexed: $(ls /tmp/knowledge_bank/parsed/*.json | wc -l)"
echo "Ready to answer questions!"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
Tell the user: "I've ingested and indexed your meeting notes. You can now ask me questions about them!"
Always follow this workflow:
if [ ! -d "/tmp/knowledge_bank/parsed" ]; then
echo "ERROR: Knowledge bank not found. Please run ingestion first."
exit 1
fi
if [ $(ls /tmp/knowledge_bank/parsed/*.json 2>/dev/null | wc -l) -eq 0 ]; then
echo "ERROR: Knowledge bank is empty. Please ingest meeting notes first."
exit 1
fi
Search by keyword in content:
# User asks: "What did we decide about API redesign?"
KEYWORD="API redesign"
# Search all parsed notes
grep -l "$KEYWORD" /tmp/knowledge_bank/*.txt 2>/dev/null | while read file; do
FILE_ID=$(basename "$file" .txt)
if [ -f "/tmp/knowledge_bank/parsed/${FILE_ID}.json" ]; then
FILE_NAME=$(jq -r '.filename' "/tmp/knowledge_bank/parsed/${FILE_ID}.json")
MEETING_DATE=$(jq -r '.meeting_date' "/tmp/knowledge_bank/parsed/${FILE_ID}.json")
echo "Found in: $FILE_NAME ($MEETING_DATE) - ID: $FILE_ID"
fi
done
Search by meeting date:
# User asks: "What happened in the March 1st meeting?"
TARGET_DATE="2026-03-01"
for json_file in /tmp/knowledge_bank/parsed/*.json; do
MEETING_DATE=$(jq -r '.meeting_date' "$json_file")
if [ "$MEETING_DATE" = "$TARGET_DATE" ]; then
FILE_NAME=$(jq -r '.filename' "$json_file")
FILE_ID=$(jq -r '.file_id' "$json_file")
echo "Found: $FILE_NAME - ID: $FILE_ID"
fi
done
Search by meeting type:
# User asks: "Show me all engineering syncs"
MEETING_TYPE="Engineering Sync"
for json_file in /tmp/knowledge_bank/parsed/*.json; do
FILE_NAME=$(jq -r '.filename' "$json_file")
if echo "$FILE_NAME" | grep -q "$MEETING_TYPE"; then
MEETING_DATE=$(jq -r '.meeting_date' "$json_file")
FILE_ID=$(jq -r '.file_id' "$json_file")
echo "Found: $FILE_NAME ($MEETING_DATE) - ID: $FILE_ID"
fi
done
Once you've identified relevant meetings, read their FULL content:
# Read from parsed JSON
CONTENT=$(jq -r '.content' "/tmp/knowledge_bank/parsed/${FILE_ID}.json")
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Reading: $(jq -r '.filename' "/tmp/knowledge_bank/parsed/${FILE_ID}.json")"
echo "Date: $(jq -r '.meeting_date' "/tmp/knowledge_bank/parsed/${FILE_ID}.json")"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "$CONTENT"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
CRITICAL RULES:
Response Format:
**Answer**: [Direct answer from meeting content]
**Source**: [Meeting Name] - [Meeting Date]
**Full Context**: [Relevant excerpt from notes]
**File ID**: [file_id for reference]
If multiple meetings discuss the topic:
# Find all relevant meetings
RELEVANT_IDS=()
for file in /tmp/knowledge_bank/*.txt; do
if grep -q "$KEYWORD" "$file"; then
FILE_ID=$(basename "$file" .txt)
RELEVANT_IDS+=("$FILE_ID")
fi
done
echo "Found ${#RELEVANT_IDS[@]} meetings discussing '$KEYWORD'"
# Read and synthesize
for file_id in "${RELEVANT_IDS[@]}"; do
FILE_NAME=$(jq -r '.filename' "/tmp/knowledge_bank/parsed/${file_id}.json")
MEETING_DATE=$(jq -r '.meeting_date' "/tmp/knowledge_bank/parsed/${file_id}.json")
CONTENT=$(jq -r '.content' "/tmp/knowledge_bank/parsed/${file_id}.json")
echo "═══════════════════════════════════════════════"
echo "$FILE_NAME - $MEETING_DATE"
echo "═══════════════════════════════════════════════"
echo "$CONTENT"
echo ""
done
Then synthesize across all meetings chronologically.
User: "What was decided about pricing?"
Workflow:
1. Search for "pricing" in all meeting notes
2. Find matching meetings
3. Read full content
4. Extract decision statements
5. Cite source meeting(s)
User: "How did the API discussion evolve?"
Workflow:
1. Search for "API" across all notes
2. Sort matches by meeting date
3. Read each in chronological order
4. Show progression of discussion
5. Cite each meeting in timeline
User: "What are my action items?"
Workflow:
1. Search for "action" OR "@" OR "TODO" across notes
2. Extract lines mentioning user's name
3. Group by meeting
4. List with source and date
User: "Summarize discussions about hiring"
Workflow:
1. Search for "hiring" OR "recruitment" across notes
2. Read all matching meetings
3. Synthesize key points
4. Cite each source
When new meetings are added:
# Re-run ingestion to pull new notes
# It will overwrite existing files with same ID
# New files will be added
echo "Knowledge Bank Status:"
echo "Location: /tmp/knowledge_bank/"
echo "Total meetings: $(ls /tmp/knowledge_bank/parsed/*.json 2>/dev/null | wc -l)"
echo "Last updated: $(stat -c %y /tmp/knowledge_bank/INDEX.md 2>/dev/null)"
echo ""
echo "Recent meetings:"
ls -t /tmp/knowledge_bank/parsed/*.json | head -5 | while read file; do
jq -r '"\(.filename) - \(.meeting_date)"' "$file"
done
# Show most common keywords
cat /tmp/knowledge_bank/*.txt | tr '[:space:]' '\n' | \
tr '[:upper:]' '[:lower:]' | \
grep -v '^$' | \
sort | uniq -c | sort -rn | head -20
if [ ! -d "/tmp/knowledge_bank" ]; then
echo "⚠ Knowledge bank not initialized."
echo "Please run: 'ingest my meeting notes from [folder]'"
exit 1
fi
if [ ${#RELEVANT_IDS[@]} -eq 0 ]; then
echo "No meetings found discussing '$KEYWORD'"
echo ""
echo "Try:"
echo " - Alternative keywords"
echo " - Broader search terms"
echo " - Checking meeting date range"
echo ""
echo "Available meetings:"
cat /tmp/knowledge_bank/INDEX.md | grep "^- "
fi
"I found partial information about X in the [date] meeting, but the
discussion appears incomplete. The notes mention [what's there] but
don't include [what's missing]."
Before answering any question:
# ═══════════════════════════════════════════════════
# PHASE 1: INGESTION
# ═══════════════════════════════════════════════════
User: "Ingest my meeting notes from the 'Team Meetings' folder"
Claude:
$ gws drive files search --query "name = 'Team Meetings' and mimeType = 'application/vnd.google-apps.folder'" --format json
# Found folder ID: abc123xyz
$ gws drive files list --parent-id "abc123xyz" --query "mimeType = 'application/vnd.google-apps.document'" --format json > /tmp/meeting_files_list.json
# Found 23 meeting notes
$ mkdir -p /tmp/knowledge_bank/parsed
# Exporting all 23 documents...
# [Shows progress]
✓ Knowledge bank built with 23 meeting notes
✓ Ready to answer questions!
# ═══════════════════════════════════════════════════
# PHASE 2: QUERYING
# ═══════════════════════════════════════════════════
User: "What was decided about the Q2 roadmap?"
Claude:
$ grep -l "Q2 roadmap" /tmp/knowledge_bank/*.txt
# Found in 3 meetings
$ # Reading Engineering Sync - 2026-02-15
$ jq -r '.content' /tmp/knowledge_bank/parsed/file123.json
$ # Reading Product Planning - 2026-02-20
$ jq -r '.content' /tmp/knowledge_bank/parsed/file456.json
$ # Reading All Hands - 2026-03-01
$ jq -r '.content' /tmp/knowledge_bank/parsed/file789.json
**Answer**: The Q2 roadmap was finalized with three priorities:
1. Mobile app redesign (priority #1)
2. API v2 launch (priority #2)
3. Analytics dashboard (moved to Q3)
**Sources**:
- Engineering Sync - February 15, 2026
- Product Planning - February 20, 2026
- All Hands - March 1, 2026
**Timeline**:
- Feb 15: Initial proposal discussed
- Feb 20: Priorities debated, mobile chosen as #1
- Mar 1: Final roadmap announced to company
**Key Decision**: Analytics dashboard deprioritized due to
resource constraints (noted in Feb 20 meeting).
Knowledge bank stored at: /tmp/knowledge_bank/
Structure:
/tmp/knowledge_bank/
├── metadata.txt # File ID to name mapping
├── INDEX.md # Human-readable index
├── *.txt # Raw exported content
└── parsed/
└── *.json # Structured parsed notes
Note: This is in /tmp/ for session storage. For persistent storage across sessions, use a different location or implement saving/loading.
🎯 Core Principle: This skill is a two-phase system:
The knowledge bank is your source of truth. Always read from it, never make things up.
tools
Use this skill whenever the user wants to summarize, digest, recap, or get a briefing from WhatsApp group chats using the `wacli` CLI. Trigger on any mention of WhatsApp summaries, group chat digests, catching up on WhatsApp, or briefing from chats. Also trigger when user wants to export or save WhatsApp chat history. Always use `wacli` — no exceptions, never use other methods.
development
Process NEW meeting folders with transcript files and generate executive meeting notes in Google Docs. Use when the user wants to transcribe meetings, process meeting folders, create meeting notes from transcripts, or convert raw transcripts into formatted Google Docs. Trigger on phrases like "transcribe my meetings", "process meeting folders", "create meeting notes from transcripts", "convert transcripts to docs", or when user provides a meetings folder to process. Always use this skill when working with a folder structure containing meeting transcripts that need to be formatted into professional meeting notes.
tools
Design and build CLI tools optimized for AI agent consumption. Use this skill when creating a new CLI command, refactoring an existing CLI for agent compatibility, or reviewing whether a CLI follows agent-friendly design principles.
development
Maintainer-only workflow for handling GitHub Secret Scanning alerts on OpenClaw. Use when Codex needs to triage, redact, clean up, and resolve secret leakage found in issue comments, issue bodies, PR comments, or other GitHub content.