Drive Agent
Drop this in
~/.claude/skills/drive/SKILL.mdand Claude Code becomes your Google Drive assistant.
Bootstrap (ALWAYS Run First)
Before any Drive operation, run this bootstrap to ensure everything is set up:
#!/bin/bash
set -e
# 1. Check if atris CLI is installed
if ! command -v atris &> /dev/null; then
echo "Installing atris CLI..."
npm install -g atris
fi
# 2. Check if logged in to AtrisOS
if [ ! -f ~/.atris/credentials.json ]; then
echo "Not logged in to AtrisOS."
echo ""
echo "Option 1 (interactive): Run 'atris login' and follow prompts"
echo "Option 2 (non-interactive): Get token from https://atris.ai/auth/cli"
echo " Then run: atris login --token YOUR_TOKEN"
echo ""
exit 1
fi
# 3. Extract token
if command -v node &> /dev/null; then
TOKEN=$(node -e "console.log(require('$HOME/.atris/credentials.json').token)")
elif command -v python3 &> /dev/null; then
TOKEN=$(python3 -c "import json,os; print(json.load(open(os.path.expanduser('~/.atris/credentials.json')))['token'])")
elif command -v jq &> /dev/null; then
TOKEN=$(jq -r '.token' ~/.atris/credentials.json)
else
echo "Error: Need node, python3, or jq to read credentials"
exit 1
fi
# 4. Check Google Drive connection status
STATUS=$(curl -s "https://api.atris.ai/api/integrations/google-drive/status" \
-H "Authorization: Bearer $TOKEN")
if echo "$STATUS" | grep -q "Token expired\|Not authenticated"; then
echo "Token expired. Please re-authenticate:"
echo " Run: atris login --force"
exit 1
fi
if command -v node &> /dev/null; then
CONNECTED=$(node -e "try{console.log(JSON.parse('$STATUS').connected||false)}catch(e){console.log(false)}")
elif command -v python3 &> /dev/null; then
CONNECTED=$(echo "$STATUS" | python3 -c "import sys,json; print(json.load(sys.stdin).get('connected', False))")
else
CONNECTED=$(echo "$STATUS" | jq -r '.connected // false')
fi
if [ "$CONNECTED" != "true" ] && [ "$CONNECTED" != "True" ]; then
echo "Google Drive not connected. Getting authorization URL..."
AUTH=$(curl -s -X POST "https://api.atris.ai/api/integrations/google-drive/start" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{}')
if command -v node &> /dev/null; then
URL=$(node -e "try{console.log(JSON.parse('$AUTH').auth_url||'')}catch(e){console.log('')}")
elif command -v python3 &> /dev/null; then
URL=$(echo "$AUTH" | python3 -c "import sys,json; print(json.load(sys.stdin).get('auth_url', ''))")
else
URL=$(echo "$AUTH" | jq -r '.auth_url // empty')
fi
echo ""
echo "Open this URL to connect your Google Drive:"
echo "$URL"
echo ""
echo "After authorizing, run your command again."
exit 0
fi
echo "Ready. Google Drive is connected."
export ATRIS_TOKEN="$TOKEN"
API Reference
Base: https://api.atris.ai/api/integrations
All requests require: -H "Authorization: Bearer $TOKEN"
Get Token (after bootstrap)
TOKEN=$(node -e "console.log(require('$HOME/.atris/credentials.json').token)")
List Shared Drives
curl -s "https://api.atris.ai/api/integrations/google-drive/shared-drives" \
-H "Authorization: Bearer $TOKEN"
Returns all shared/team drives the user has access to with id and name.
List Files
curl -s "https://api.atris.ai/api/integrations/google-drive/files?page_size=20" \
-H "Authorization: Bearer $TOKEN"
List files in a folder:
curl -s "https://api.atris.ai/api/integrations/google-drive/files?folder_id=FOLDER_ID&page_size=20" \
-H "Authorization: Bearer $TOKEN"
List files in a shared drive:
curl -s "https://api.atris.ai/api/integrations/google-drive/files?shared_drive_id=DRIVE_ID&page_size=20" \
-H "Authorization: Bearer $TOKEN"
NOTE: All file operations (list, search, get, download, export) automatically include shared drive files. Use shared_drive_id only to scope results to a specific shared drive.
Search Files
curl -s "https://api.atris.ai/api/integrations/google-drive/search?q=quarterly+report&page_size=20" \
-H "Authorization: Bearer $TOKEN"
Simple queries search by file name. For advanced queries, use Drive query syntax:
name contains 'budget'— name searchmimeType = 'application/vnd.google-apps.spreadsheet'— only sheetsmimeType = 'application/vnd.google-apps.document'— only docsmodifiedTime > '2026-01-01'— recently modified
Get File Metadata
curl -s "https://api.atris.ai/api/integrations/google-drive/files/{file_id}" \
-H "Authorization: Bearer $TOKEN"
Download File
curl -s "https://api.atris.ai/api/integrations/google-drive/files/{file_id}/download" \
-H "Authorization: Bearer $TOKEN"
Returns base64-encoded content. For Google Docs/Sheets/Slides, use export instead.
Export Google Docs/Sheets/Slides
curl -s "https://api.atris.ai/api/integrations/google-drive/files/{file_id}/export?mime_type=text/plain" \
-H "Authorization: Bearer $TOKEN"
Export formats:
text/plain— plain text (default, good for Docs)text/html— HTMLapplication/pdf— PDFtext/csv— CSV (for Sheets)
Upload File
curl -s -X POST "https://api.atris.ai/api/integrations/google-drive/files" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "notes.txt",
"content": "File content here",
"mime_type": "text/plain"
}'
Upload to a specific folder:
curl -s -X POST "https://api.atris.ai/api/integrations/google-drive/files" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "report.txt",
"content": "File content here",
"mime_type": "text/plain",
"folder_id": "FOLDER_ID"
}'
Update Existing File
curl -s -X PUT "https://api.atris.ai/api/integrations/google-drive/files/{file_id}" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"content": "Updated file content here",
"mime_type": "text/plain"
}'
Update content and rename:
curl -s -X PUT "https://api.atris.ai/api/integrations/google-drive/files/{file_id}" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"content": "New content",
"mime_type": "text/plain",
"name": "renamed-file.txt"
}'
Delete / Trash File
# Move to trash (recoverable)
curl -s -X DELETE "https://api.atris.ai/api/integrations/google-drive/files/{file_id}?trash=true" \
-H "Authorization: Bearer $TOKEN"
# Permanently delete (irreversible)
curl -s -X DELETE "https://api.atris.ai/api/integrations/google-drive/files/{file_id}" \
-H "Authorization: Bearer $TOKEN"
Copy File
curl -s -X POST "https://api.atris.ai/api/integrations/google-drive/files/{file_id}/copy" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Copy of Document", "folder_id": "OPTIONAL_FOLDER_ID"}'
Works with Docs, Sheets, Slides — creates a full copy.
Share File
# Share with a specific user
curl -s -X POST "https://api.atris.ai/api/integrations/google-drive/files/{file_id}/share" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com", "role": "writer", "notify": true}'
# Share with anyone who has the link
curl -s -X POST "https://api.atris.ai/api/integrations/google-drive/files/{file_id}/share" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"anyone": true, "role": "reader"}'
Roles: reader, writer, commenter
Create Folder
curl -s -X POST "https://api.atris.ai/api/integrations/google-drive/folders" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Project Files", "parent_id": "OPTIONAL_PARENT_FOLDER_ID"}'
Move File
curl -s -X POST "https://api.atris.ai/api/integrations/google-drive/files/{file_id}/move" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"new_parent_id": "TARGET_FOLDER_ID"}'
Pagination
List and search endpoints return next_page_token when there are more results. Pass it to get the next page:
curl -s "https://api.atris.ai/api/integrations/google-drive/files?page_size=20&page_token=NEXT_PAGE_TOKEN" \
-H "Authorization: Bearer $TOKEN"
Works on: /files, /search, /shared-drives
Google Docs
Native Google Docs creation and editing. Uses the same Drive OAuth connection.
List Google Docs
curl -s "https://api.atris.ai/api/integrations/google-docs/documents?page_size=20" \
-H "Authorization: Bearer $TOKEN"
Create a New Google Doc
curl -s -X POST "https://api.atris.ai/api/integrations/google-docs/documents" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"title": "Q1 2026 Report"}'
Returns documentId and url (direct link to edit in browser).
Read a Google Doc
curl -s "https://api.atris.ai/api/integrations/google-docs/documents/{document_id}" \
-H "Authorization: Bearer $TOKEN"
Returns full document structure (body, paragraphs, text runs, styles).
Insert Text into a Doc
curl -s -X POST "https://api.atris.ai/api/integrations/google-docs/documents/{document_id}/batch-update" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"requests": [
{
"insertText": {
"location": {"index": 1},
"text": "Hello, this is the first paragraph.\n\nSecond paragraph here.\n"
}
}
]
}'
Text is inserted at a character index. Index 1 = start of document body. Newlines create paragraphs.
Replace Placeholders in a Doc Template
curl -s -X POST "https://api.atris.ai/api/integrations/google-docs/documents/{document_id}/batch-update" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"requests": [
{
"replaceAllText": {
"containsText": {"text": "{{client_name}}", "matchCase": true},
"replaceText": "Acme Corp"
}
},
{
"replaceAllText": {
"containsText": {"text": "{{date}}", "matchCase": true},
"replaceText": "March 5, 2026"
}
}
]
}'
Format Text (Bold, Italic, Font Size, Color)
curl -s -X POST "https://api.atris.ai/api/integrations/google-docs/documents/{document_id}/batch-update" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"requests": [
{
"updateTextStyle": {
"range": {"startIndex": 1, "endIndex": 20},
"textStyle": {"bold": true, "fontSize": {"magnitude": 18, "unit": "PT"}},
"fields": "bold,fontSize"
}
}
]
}'
Insert a Table
curl -s -X POST "https://api.atris.ai/api/integrations/google-docs/documents/{document_id}/batch-update" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"requests": [
{
"insertTable": {
"rows": 3,
"columns": 2,
"location": {"index": 1}
}
}
]
}'
Export Doc as PDF
curl -s "https://api.atris.ai/api/integrations/google-docs/documents/{document_id}/export" \
-H "Authorization: Bearer $TOKEN"
Returns base64-encoded PDF.
Export Doc as Plain Text
curl -s "https://api.atris.ai/api/integrations/google-docs/documents/{document_id}/text" \
-H "Authorization: Bearer $TOKEN"
Google Sheets
Full read/write access to Google Sheets.
Create a Spreadsheet
curl -s -X POST "https://api.atris.ai/api/integrations/google-drive/sheets" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"title": "Q1 Revenue Tracker"}'
Returns spreadsheetId and url (direct link to edit in browser).
Get Spreadsheet Info
curl -s "https://api.atris.ai/api/integrations/google-drive/sheets/{spreadsheet_id}" \
-H "Authorization: Bearer $TOKEN"
Returns sheet names, title, and metadata.
Read Cells
curl -s "https://api.atris.ai/api/integrations/google-drive/sheets/{spreadsheet_id}/values?range=Sheet1" \
-H "Authorization: Bearer $TOKEN"
Range uses A1 notation:
Sheet1— entire sheetSheet1!A1:D10— specific rangeSheet1!A:A— entire column ASheet1!1:1— entire row 1
Update Cells
curl -s -X PUT "https://api.atris.ai/api/integrations/google-drive/sheets/{spreadsheet_id}/values" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"range": "Sheet1!A1:B2",
"values": [
["Name", "Score"],
["Alice", 95]
]
}'
Append Rows
curl -s -X POST "https://api.atris.ai/api/integrations/google-drive/sheets/{spreadsheet_id}/append" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"range": "Sheet1",
"values": [
["Bob", 88],
["Carol", 92]
]
}'
Format Cells (batchUpdate)
Apply formatting, merges, conditional formatting, charts, and other structural changes.
curl -s -X POST "https://api.atris.ai/api/integrations/google-drive/sheets/{spreadsheet_id}/batchUpdate" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"requests": [
{
"repeatCell": {
"range": {"sheetId": 0, "startRowIndex": 0, "endRowIndex": 1},
"cell": {
"userEnteredFormat": {
"textFormat": {"bold": true},
"backgroundColor": {"red": 0.9, "green": 0.9, "blue": 0.9}
}
},
"fields": "userEnteredFormat(textFormat,backgroundColor)"
}
}
]
}'
Common request types:
repeatCell— format a range (bold, colors, font size, alignment)mergeCells— merge a range into one cellupdateBorders— add borders to cellsautoResizeDimensions— auto-fit column widthsaddConditionalFormatRule— highlight cells based on rulesaddChart— embed a chartaddSheet/deleteSheet— manage sheets/tabssortRange— sort rows by a column
Range format: {"sheetId": 0, "startRowIndex": 0, "endRowIndex": 1, "startColumnIndex": 0, "endColumnIndex": 3} — sheetId 0 = first tab, indices are 0-based.
Color format: RGB floats 0-1, e.g. {"red": 0.2, "green": 0.6, "blue": 1.0}
You can send multiple requests in one call — they execute in order.
Workflows
"Create a Google Doc with content"
- Run bootstrap
- Create doc:
POST /google-docs/documentswith{"title": "..."} - Insert text:
POST /google-docs/documents/{id}/batch-updatewithinsertTextrequests - Return the edit URL to user
"Fill a doc template"
- Run bootstrap
- Copy template:
POST /files/{template_id}/copywith{"name": "Client Proposal"} - Replace placeholders:
POST /google-docs/documents/{new_id}/batch-updatewithreplaceAllTextrequests - Share if needed:
POST /files/{id}/share - Return URL
"Find a file in my Drive"
- Run bootstrap
- Search:
GET /google-drive/search?q=QUERY - Display: name, type, modified date for each result
"Read a Google Doc"
- Run bootstrap
- Search for the doc:
GET /google-drive/search?q=DOC_NAME - Export as text:
GET /google-drive/files/{id}/export?mime_type=text/plain - Display content
"Read a spreadsheet"
- Run bootstrap
- Search for the sheet:
GET /google-drive/search?q=SHEET_NAME - Get sheet info:
GET /google-drive/sheets/{id}(to see sheet names) - Read values:
GET /google-drive/sheets/{id}/values?range=Sheet1 - Display as a table
"Add rows to a spreadsheet"
- Run bootstrap
- Find the sheet
- Read current data to understand the columns:
GET /google-drive/sheets/{id}/values?range=Sheet1!1:1 - Show user what will be appended, get approval
- Append:
POST /google-drive/sheets/{id}/append
"Browse a shared drive"
- Run bootstrap
- List shared drives:
GET /google-drive/shared-drives - Display drive names and IDs
- List files in chosen drive:
GET /google-drive/files?shared_drive_id=DRIVE_ID
"Find a file across all drives"
- Run bootstrap
- Search:
GET /google-drive/search?q=QUERY(automatically searches My Drive + all shared drives) - Display results
"Format a spreadsheet"
- Run bootstrap
- Find the sheet, get its
spreadsheetId - Build requests array — bold headers, colors, borders, auto-resize, etc.
- Show user what formatting will be applied, get approval
- Apply:
POST /google-drive/sheets/{id}/batchUpdatewith{"requests": [...]}
"Create a spreadsheet with data"
- Run bootstrap
- Create:
POST /google-drive/sheetswith{"title": "..."} - Write headers + data:
PUT /google-drive/sheets/{id}/valueswith range + values - Format headers:
POST /google-drive/sheets/{id}/batchUpdate(bold, background color) - Return the URL
"Share a file"
- Run bootstrap
- Find the file
- Ask user: share with specific email or anyone with link?
- Share:
POST /google-drive/files/{id}/share
"Organize files into folders"
- Run bootstrap
- Create folder:
POST /google-drive/folderswith{"name": "..."} - Move files:
POST /google-drive/files/{id}/movewith{"new_parent_id": "FOLDER_ID"}
"Copy a template"
- Run bootstrap
- Find the template file
- Copy:
POST /google-drive/files/{id}/copywith{"name": "New Name"} - If it's a Doc, replace placeholders via
/google-docs/documents/{new_id}/batch-update - Share if needed
"Delete files"
- Run bootstrap
- Find the files
- Confirm with user — show file names
- Trash (recoverable):
DELETE /google-drive/files/{id}?trash=true - Or permanent delete:
DELETE /google-drive/files/{id}
"Upload a file to Drive"
- Run bootstrap
- Read the local file content
- Confirm with user: "Upload {filename} to Drive?"
- Upload:
POST /google-drive/fileswith{name, content, mime_type}
"Edit a file on Drive"
- Run bootstrap
- Find the file:
GET /google-drive/search?q=FILENAME - Read current content:
GET /google-drive/files/{id}/export?mime_type=text/plain - Make edits
- Show user the changes for approval
- Update:
PUT /google-drive/files/{id}with{content, mime_type}
Error Handling
| Error | Meaning | Solution |
|-------|---------|----------|
| Token expired | AtrisOS session expired | Run atris login |
| Google Drive not connected | OAuth not completed | Re-run bootstrap |
| 401 Unauthorized | Invalid/expired token | Run atris login |
| 400 Drive not connected | No Drive credentials | Complete OAuth via bootstrap |
| 429 Rate limited | Too many requests | Wait 60s, retry |
| Invalid grant | Google revoked access | Re-connect via bootstrap |
Security Model
- Local token (
~/.atris/credentials.json): Your AtrisOS auth token, stored locally with 600 permissions. - Drive credentials: Google Drive refresh token is stored server-side in AtrisOS encrypted vault.
- Access control: AtrisOS API enforces that you can only access your own Drive.
- OAuth scopes: Only requests necessary Drive permissions (read, write files).
- HTTPS only: All API communication encrypted in transit.
Quick Reference
# Setup (one time)
npm install -g atris && atris login
# Get token
TOKEN=$(node -e "console.log(require('$HOME/.atris/credentials.json').token)")
# Check connection
curl -s "https://api.atris.ai/api/integrations/google-drive/status" -H "Authorization: Bearer $TOKEN"
# List shared drives
curl -s "https://api.atris.ai/api/integrations/google-drive/shared-drives" -H "Authorization: Bearer $TOKEN"
# List files (includes shared drive files)
curl -s "https://api.atris.ai/api/integrations/google-drive/files" -H "Authorization: Bearer $TOKEN"
# Search files
curl -s "https://api.atris.ai/api/integrations/google-drive/search?q=budget" -H "Authorization: Bearer $TOKEN"
# Read a Google Doc as text
curl -s "https://api.atris.ai/api/integrations/google-drive/files/{file_id}/export?mime_type=text/plain" -H "Authorization: Bearer $TOKEN"
# Read a spreadsheet
curl -s "https://api.atris.ai/api/integrations/google-drive/sheets/{id}/values?range=Sheet1" -H "Authorization: Bearer $TOKEN"
# Append rows to a sheet
curl -s -X POST "https://api.atris.ai/api/integrations/google-drive/sheets/{id}/append" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"range":"Sheet1","values":[["Alice",95]]}'
# Upload a new file
curl -s -X POST "https://api.atris.ai/api/integrations/google-drive/files" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"name":"notes.txt","content":"Hello world","mime_type":"text/plain"}'
# Create a folder
curl -s -X POST "https://api.atris.ai/api/integrations/google-drive/folders" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"name":"Project Files"}'
# Copy a file
curl -s -X POST "https://api.atris.ai/api/integrations/google-drive/files/{file_id}/copy" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"name":"Copy of Doc"}'
# Share with email
curl -s -X POST "https://api.atris.ai/api/integrations/google-drive/files/{file_id}/share" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"email":"user@example.com","role":"writer"}'
# Move file to folder
curl -s -X POST "https://api.atris.ai/api/integrations/google-drive/files/{file_id}/move" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"new_parent_id":"FOLDER_ID"}'
# Trash a file
curl -s -X DELETE "https://api.atris.ai/api/integrations/google-drive/files/{file_id}?trash=true" \
-H "Authorization: Bearer $TOKEN"
# Create a spreadsheet
curl -s -X POST "https://api.atris.ai/api/integrations/google-drive/sheets" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"title":"New Sheet"}'
# Format cells (bold header row)
curl -s -X POST "https://api.atris.ai/api/integrations/google-drive/sheets/{id}/batchUpdate" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"requests":[{"repeatCell":{"range":{"sheetId":0,"startRowIndex":0,"endRowIndex":1},"cell":{"userEnteredFormat":{"textFormat":{"bold":true}}},"fields":"userEnteredFormat.textFormat.bold"}}]}'
# Update an existing file
curl -s -X PUT "https://api.atris.ai/api/integrations/google-drive/files/{file_id}" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"content":"Updated content","mime_type":"text/plain"}'
# Create a Google Doc
curl -s -X POST "https://api.atris.ai/api/integrations/google-docs/documents" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"title":"New Doc"}'
# Insert text into a Doc
curl -s -X POST "https://api.atris.ai/api/integrations/google-docs/documents/DOC_ID/batch-update" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"requests":[{"insertText":{"location":{"index":1},"text":"Hello world\n"}}]}'
微信扫一扫