Claude-skills google-gemini-file-search
Google Gemini File Search for managed RAG with 100+ file formats. Use for document Q&A, knowledge bases, or encountering immutability errors, quota issues, polling failures. Supports Gemini 3 Pro/Flash (Gemini 2.5 legacy).
git clone https://github.com/secondsky/claude-skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/secondsky/claude-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/google-gemini-file-search/skills/google-gemini-file-search" ~/.claude/skills/secondsky-claude-skills-google-gemini-file-search && rm -rf "$T"
plugins/google-gemini-file-search/skills/google-gemini-file-search/SKILL.mdGoogle Gemini File Search
Status: Production Ready | Last Verified: 2025-11-18
What Is File Search?
Google Gemini File Search is fully managed RAG (Retrieval-Augmented Generation):
- Upload documents → Automatic chunking + embeddings + vector search + citations
- No vector database setup required
- 100+ file formats supported (PDF, Word, Excel, code, Markdown, JSON, etc.)
- Built-in grounding with citation metadata
- Cost-effective: $0.15/1M tokens (one-time indexing), free storage + queries
Key difference from other RAG:
- Cloudflare Vectorize: You manage chunking/embeddings
- OpenAI Files API: Tied to Assistants API threads
- File Search: Fully managed, standalone RAG
Quick Start (5 Minutes)
1. Get API Key & Install
Get API key: https://aistudio.google.com/apikey (Free tier: 1 GB storage, 1,500 requests/day)
bun add @google/genai
Version: 0.21.0+ | Node.js: 18+
2. Basic Example
import { GoogleGenerativeAI } from '@google/genai'; import fs from 'fs'; const ai = new GoogleGenerativeAI(process.env.GOOGLE_AI_API_KEY); // Create store const fileStore = await ai.fileSearchStores.create({ config: { displayName: 'my-knowledge-base' } }); // Upload document const operation = await ai.fileSearchStores.uploadToFileSearchStore({ name: fileStore.name, file: fs.createReadStream('./manual.pdf'), config: { displayName: 'Installation Manual', chunkingConfig: { whiteSpaceConfig: { maxTokensPerChunk: 500, maxOverlapTokens: 50 } } } }); // Poll until done while (!operation.done) { await new Promise(resolve => setTimeout(resolve, 1000)); operation = await ai.operations.get({ name: operation.name }); } // Query documents const model = ai.getGenerativeModel({ model: 'gemini-2.5-pro', // Only 2.5 Pro/Flash supported tools: [{ fileSearchTool: { fileSearchStores: [fileStore.name] } }] }); const result = await model.generateContent('How do I install the product?'); console.log(result.response.text()); // Get citations const grounding = result.response.candidates[0].groundingMetadata; if (grounding) { console.log('Sources:', grounding.groundingChunks); }
Load
for complete walkthrough with batch uploads, error handling, and production checklist.references/setup-guide.md
Critical Rules
Always Do
- Use delete + re-upload for updates (documents are immutable)
- Calculate 3x storage (embeddings + metadata = ~3x file size)
- Configure chunking (500 tokens for technical docs, 800 for prose)
- Poll operations until
(with timeout)done: true - Use force: true when deleting stores with documents
- Use Gemini 2.5 models only (2.5-pro or 2.5-flash)
- Keep metadata under 20 fields per document
- Estimate indexing costs ($0.15/1M tokens one-time)
Never Do
- Never try to update documents (no PATCH API exists)
- Never assume storage = file size (it's 3x)
- Never skip chunking config (defaults may not be optimal)
- Never upload without polling (operation may still be processing)
- Never delete without force if store has documents
- Never use Gemini 1.5 models (File Search requires 2.5)
- Never exceed 20 metadata fields (hard limit)
- Never upload large files without cost estimate
Top 3 Errors Prevented
Error 1: Document Immutability
Problem: Trying to update existing document
Solution: Delete + re-upload pattern
// Find and delete old version const docs = await ai.fileSearchStores.documents.list({ parent: fileStore.name }); const oldDoc = docs.documents.find(d => d.displayName === 'manual.pdf'); if (oldDoc) { await ai.fileSearchStores.documents.delete({ name: oldDoc.name, force: true }); } // Upload new version await ai.fileSearchStores.uploadToFileSearchStore({ name: fileStore.name, file: fs.createReadStream('manual-v2.pdf'), config: { displayName: 'manual.pdf' } });
Error 2: Storage Quota Exceeded
Problem: Storage calculation wrong (3x multiplier)
Solution: Estimate before upload
const fileSize = fs.statSync('data.pdf').size; const estimatedStorage = fileSize * 3; // Embeddings + metadata if (estimatedStorage > 1e9) { console.warn('⚠️ May exceed free tier 1 GB limit'); }
Error 3: Model Compatibility
Problem: Using wrong model version
Solution: Use Gemini 2.5 only
// ✅ CORRECT const model = ai.getGenerativeModel({ model: 'gemini-2.5-pro', // or gemini-2.5-flash tools: [{ fileSearchTool: { fileSearchStores: [storeName] } }] }); // ❌ WRONG const model = ai.getGenerativeModel({ model: 'gemini-1.5-pro', // Not supported! tools: [{ fileSearchTool: { fileSearchStores: [storeName] } }] });
Load
for all 8 errors with detailed solutions including chunking, operation polling, metadata limits, and force delete requirements.references/error-catalog.md
When to Use File Search
Use File Search When:
- Want fully managed RAG (no vector DB)
- Cost predictability matters (one-time indexing)
- Need 100+ file format support
- Citations are important (built-in grounding)
- Simple deployment is priority
- Documents are relatively static
Use Alternatives When:
Cloudflare Vectorize - Global edge performance, custom embeddings, real-time R2 updates OpenAI Files API - Assistants API, conversational threads, very large collections (10,000+)
Common Patterns
Pattern 1: Customer Support Knowledge Base
// Upload support docs with metadata await ai.fileSearchStores.uploadToFileSearchStore({ name: fileStore.name, file: fs.createReadStream('troubleshooting.pdf'), config: { displayName: 'Troubleshooting Guide', customMetadata: { doc_type: 'support', category: 'troubleshooting', language: 'en' } } });
Pattern 2: Batch Document Upload
const files = ['doc1.pdf', 'doc2.md', 'doc3.docx']; const uploadPromises = files.map(file => ai.fileSearchStores.uploadToFileSearchStore({ name: fileStore.name, file: fs.createReadStream(file), config: { displayName: file } }) ); const operations = await Promise.all(uploadPromises); // Poll all operations for (const op of operations) { let operation = op; while (!operation.done) { await new Promise(resolve => setTimeout(resolve, 1000)); operation = await ai.operations.get({ name: operation.name }); } console.log('✅', operation.response.displayName); }
Pattern 3: Document Update Flow
// 1. List existing documents const docs = await ai.fileSearchStores.documents.list({ parent: fileStore.name }); // 2. Delete old version const oldDoc = docs.documents.find(d => d.displayName === 'manual.pdf'); if (oldDoc) { await ai.fileSearchStores.documents.delete({ name: oldDoc.name, force: true }); } // 3. Upload new version const operation = await ai.fileSearchStores.uploadToFileSearchStore({ name: fileStore.name, file: fs.createReadStream('manual-v2.pdf'), config: { displayName: 'manual.pdf', customMetadata: { version: '2.0', updated_at: new Date().toISOString() } } }); // 4. Poll until done while (!operation.done) { await new Promise(resolve => setTimeout(resolve, 1000)); operation = await ai.operations.get({ name: operation.name }); }
Load
for additional patterns including code documentation search and internal knowledge bases.references/setup-guide.md
When to Load References
Load references/setup-guide.md
when:
references/setup-guide.md- First-time File Search setup
- Need step-by-step walkthrough with all configuration options
- Configuring batch upload strategies
- Production deployment checklist
- Complete API initialization patterns
Load references/error-catalog.md
when:
references/error-catalog.md- Encountering any of 8 common errors
- Need detailed error solutions with code examples
- Prevention checklist required
- Troubleshooting upload/query issues
- Understanding chunking, metadata, or cost calculation problems
Supported File Formats
100+ formats including:
- Documents: PDF, Word (.docx), Excel (.xlsx), PowerPoint (.pptx)
- Text: Markdown (.md), Plain text (.txt), JSON, CSV
- Code: Python, JavaScript, TypeScript, Java, C++, Go, Rust, etc.
Not supported: Images in PDFs (text extraction only), Audio files, Video files
Pricing
Indexing (one-time): $0.15 per 1M tokens Storage: Free (10 GB - 1 TB depending on tier) Query embeddings: Free (retrieved context counts as input tokens)
Example: 1,000-page document ≈ 500k tokens → Indexing cost: $0.075 → Storage: ~1.5 GB (3x multiplier)
Chunking Guidelines
Technical docs: 500 tokens/chunk, 50 overlap Prose: 800 tokens/chunk, 80 overlap Legal: 300 tokens/chunk, 30 overlap
chunkingConfig: { whiteSpaceConfig: { maxTokensPerChunk: 500, // Smaller = more precise maxOverlapTokens: 50 // 10% overlap recommended } }
Resources
References (
references/):
- Complete setup walkthrough (authentication, store creation, file upload, batch patterns, production checklist)setup-guide.md
- All 8 documented errors with solutions (immutability, storage, chunking, metadata, costs, polling, force delete, model compatibility)error-catalog.md
Official Documentation:
- File Search Overview: https://ai.google.dev/api/file-search
- API Reference: https://ai.google.dev/api/file-search/documents
- Blog Post: https://blog.google/technology/developers/file-search-gemini-api/
Questions? Issues?
- Check
for complete setupreferences/setup-guide.md - Review
for all 8 errorsreferences/error-catalog.md - Verify model version (must be Gemini 2.5)
- Check storage calculation (3x file size)