atris/skills/drive/SKILL.md
Google Drive integration via AtrisOS API. Full file management (upload, copy, share, move, delete), Google Docs (create, edit, format, templates), Google Sheets (read, write, format, charts). Use when user asks about Drive, files, docs, sheets, or spreadsheets.
npx skillsauth add atrislabs/atris driveInstall 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.
Drop this in
~/.claude/skills/drive/SKILL.mdand Claude Code becomes your Google Drive assistant.
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"
Base: https://api.atris.ai/api/integrations
All requests require: -H "Authorization: Bearer $TOKEN"
TOKEN=$(node -e "console.log(require('$HOME/.atris/credentials.json').token)")
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.
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.
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 modifiedcurl -s "https://api.atris.ai/api/integrations/google-drive/files/{file_id}" \
-H "Authorization: Bearer $TOKEN"
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.
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)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"
}'
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"
}'
# 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"
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 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": "[email protected]", "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
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"}'
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"}'
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
Native Google Docs creation and editing. Uses the same Drive OAuth connection.
curl -s "https://api.atris.ai/api/integrations/google-docs/documents?page_size=20" \
-H "Authorization: Bearer $TOKEN"
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).
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).
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.
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"
}
}
]
}'
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"
}
}
]
}'
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}
}
}
]
}'
curl -s "https://api.atris.ai/api/integrations/google-docs/documents/{document_id}/export" \
-H "Authorization: Bearer $TOKEN"
Returns base64-encoded PDF.
curl -s "https://api.atris.ai/api/integrations/google-docs/documents/{document_id}/text" \
-H "Authorization: Bearer $TOKEN"
Full read/write access to Google Sheets.
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).
curl -s "https://api.atris.ai/api/integrations/google-drive/sheets/{spreadsheet_id}" \
-H "Authorization: Bearer $TOKEN"
Returns sheet names, title, and metadata.
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 1curl -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]
]
}'
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]
]
}'
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 columnRange 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.
POST /google-docs/documents with {"title": "..."}POST /google-docs/documents/{id}/batch-update with insertText requestsPOST /files/{template_id}/copy with {"name": "Client Proposal"}POST /google-docs/documents/{new_id}/batch-update with replaceAllText requestsPOST /files/{id}/shareGET /google-drive/search?q=QUERYGET /google-drive/search?q=DOC_NAMEGET /google-drive/files/{id}/export?mime_type=text/plainGET /google-drive/search?q=SHEET_NAMEGET /google-drive/sheets/{id} (to see sheet names)GET /google-drive/sheets/{id}/values?range=Sheet1GET /google-drive/sheets/{id}/values?range=Sheet1!1:1POST /google-drive/sheets/{id}/appendGET /google-drive/shared-drivesGET /google-drive/files?shared_drive_id=DRIVE_IDGET /google-drive/search?q=QUERY (automatically searches My Drive + all shared drives)spreadsheetIdPOST /google-drive/sheets/{id}/batchUpdate with {"requests": [...]}POST /google-drive/sheets with {"title": "..."}PUT /google-drive/sheets/{id}/values with range + valuesPOST /google-drive/sheets/{id}/batchUpdate (bold, background color)POST /google-drive/files/{id}/sharePOST /google-drive/folders with {"name": "..."}POST /google-drive/files/{id}/move with {"new_parent_id": "FOLDER_ID"}POST /google-drive/files/{id}/copy with {"name": "New Name"}/google-docs/documents/{new_id}/batch-updateDELETE /google-drive/files/{id}?trash=trueDELETE /google-drive/files/{id}POST /google-drive/files with {name, content, mime_type}GET /google-drive/search?q=FILENAMEGET /google-drive/files/{id}/export?mime_type=text/plainPUT /google-drive/files/{id} with {content, mime_type}| 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 |
~/.atris/credentials.json): Your AtrisOS auth token, stored locally with 600 permissions.# 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":"[email protected]","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"}}]}'
testing
Detects AI slop and fixes it, especially in memos, docs, READMEs, messages, PRDs, and other written output. Based on Wikipedia's AI Cleanup patterns plus memo-specific anti-slop rules. Triggers on "copy edit", "review writing", "humanize", "deslopper", "ai patterns", "make it sound human", "AI slop", "anti-slop", "memo".
tools
Use when an agent needs to inspect or send local macOS iMessage through Atris CLI. Triggers on iMessage, Messages.app, local text messages, chat.db, or texting someone from the user's Mac.
databases
Submit, list, resolve, close, or delete Atris customer feedback. Use when user types /feedback or asks to triage the feedback queue.
development
Fast research sweep — arxiv, semantic scholar, github, web. Finds papers, scores relevance, extracts actionable insights, stores to wiki. Triggers on: research search, find papers, latest research, arxiv, what's new in, sweep papers, research sweep.