onedrive
Manage files and folders in OneDrive and OneDrive for Business via Microsoft Graph API. Use when someone asks to "upload to OneDrive", "sync files with OneDrive", "share OneDrive files", "manage OneDrive folders", "OneDrive API integration", "backup to OneDrive", or "automate file management in OneDrive". Covers file CRUD, sharing, sync, search, large file upload, thumbnails, and delta queries for change tracking.
Usage
Getting Started
- Install the skill using the command above
- Open your AI coding agent (Claude Code, Codex, Gemini CLI, or Cursor)
- Reference the skill in your prompt
- The AI will use the skill's capabilities automatically
Example Prompts
- "Review the open pull requests and summarize what needs attention"
- "Generate a changelog from the last 20 commits on the main branch"
Documentation
Overview
This skill helps AI agents manage files in OneDrive (personal and business) via Microsoft Graph API. It covers file upload/download, folder management, sharing links, permission control, search, thumbnails, large file uploads with resumable sessions, delta queries for efficient sync, and webhook notifications.
Instructions
Authentication
// Permissions needed:
// Files.ReadWrite — user's OneDrive
// Files.ReadWrite.All — all drives (admin, SharePoint included)
// Same Azure AD auth as other Microsoft 365 skills
// graphClient setup identical to Teams/SharePoint/Outlook
File & Folder Operations
// Get user's drive info
const drive = await graphClient.api(`/users/${userId}/drive`)
.select('id,driveType,quota')
.get();
console.log(`Used: ${(drive.quota.used / 1e9).toFixed(1)} GB / ${(drive.quota.total / 1e9).toFixed(0)} GB`);
// List root folder
const root = await graphClient.api(`/users/${userId}/drive/root/children`)
.select('id,name,size,lastModifiedDateTime,folder,file,webUrl')
.orderby('name')
.get();
// List specific folder (by path)
const items = await graphClient
.api(`/users/${userId}/drive/root:/Projects/Q1-2026:/children`)
.select('id,name,size,lastModifiedDateTime,folder,file')
.get();
// Create folder
await graphClient.api(`/users/${userId}/drive/root/children`)
.post({
name: 'New Project',
folder: {},
'@microsoft.graph.conflictBehavior': 'rename', // 'fail', 'replace', or 'rename'
});
// Create nested folders (by path)
await graphClient.api(`/users/${userId}/drive/root:/Projects/Q1-2026/Reports:/children`)
.post({
name: 'March',
folder: {},
});
Upload Files
// Simple upload (< 4MB)
const fileBuffer = fs.readFileSync('/path/to/file.pdf');
const uploaded = await graphClient
.api(`/users/${userId}/drive/root:/Documents/report.pdf:/content`)
.put(fileBuffer);
console.log('Uploaded:', uploaded.webUrl);
// Large file upload (> 4MB) — resumable session
const uploadSession = await graphClient
.api(`/users/${userId}/drive/root:/LargeFiles/database-backup.zip:/createUploadSession`)
.post({
item: {
'@microsoft.graph.conflictBehavior': 'replace',
name: 'database-backup.zip',
},
});
const filePath = '/path/to/database-backup.zip';
const fileSize = fs.statSync(filePath).size;
const chunkSize = 10 * 1024 * 1024; // 10MB chunks (must be multiple of 320KB)
const file = fs.openSync(filePath, 'r');
let offset = 0;
while (offset < fileSize) {
const length = Math.min(chunkSize, fileSize - offset);
const buffer = Buffer.alloc(length);
fs.readSync(file, buffer, 0, length, offset);
const res = await fetch(uploadSession.uploadUrl, {
method: 'PUT',
headers: {
'Content-Length': `${length}`,
'Content-Range': `bytes ${offset}-${offset + length - 1}/${fileSize}`,
},
body: buffer,
});
offset += length;
console.log(`Progress: ${Math.round(offset / fileSize * 100)}%`);
}
fs.closeSync(file);
Download Files
// Download by item ID
const stream = await graphClient
.api(`/users/${userId}/drive/items/${itemId}/content`)
.getStream();
const writer = fs.createWriteStream('/path/to/output.pdf');
stream.pipe(writer);
// Download by path
const content = await graphClient
.api(`/users/${userId}/drive/root:/Documents/report.pdf:/content`)
.get();
Move, Copy, Rename, Delete
// Rename or move via PATCH
await graphClient.api(`/users/${userId}/drive/items/${itemId}`)
.patch({ name: 'new-filename.pdf', parentReference: { id: targetFolderId } });
// Copy (async — returns Location header with monitor URL)
await graphClient.api(`/users/${userId}/drive/items/${itemId}/copy`)
.post({ parentReference: { driveId, id: targetFolderId }, name: 'report-copy.pdf' });
// Delete (sends to recycle bin)
await graphClient.api(`/users/${userId}/drive/items/${itemId}`).delete();
Sharing & Permissions
// Create sharing link
const link = await graphClient
.api(`/users/${userId}/drive/items/${itemId}/createLink`)
.post({
type: 'view', // 'view', 'edit', 'embed'
scope: 'organization', // 'anonymous', 'organization', 'users'
expirationDateTime: '2026-04-01T00:00:00Z', // Optional expiry
password: 'securePassword123', // Optional password protection
});
console.log('Share link:', link.link.webUrl);
// Share with specific people
const invite = await graphClient
.api(`/users/${userId}/drive/items/${itemId}/invite`)
.post({
requireSignIn: true,
sendInvitation: true,
roles: ['read'], // 'read', 'write'
recipients: [
{ email: 'sarah@company.com' },
{ email: 'external@partner.com' },
],
message: 'Please review the attached report.',
});
// List permissions on a file
const permissions = await graphClient
.api(`/users/${userId}/drive/items/${itemId}/permissions`)
.get();
// Remove permission
await graphClient
.api(`/users/${userId}/drive/items/${itemId}/permissions/${permId}`)
.delete();
Search
// Search across OneDrive
const results = await graphClient
.api(`/users/${userId}/drive/root/search(q='quarterly report')`)
.select('id,name,webUrl,lastModifiedDateTime,size')
.top(25)
.get();
For advanced full-text search inside files, use the Microsoft Search API with entityTypes: ['driveItem'] and KQL query syntax.
Thumbnails & Preview
// Get thumbnails (small, medium, large for images, PDFs, Office docs)
const thumbs = await graphClient
.api(`/users/${userId}/drive/items/${itemId}/thumbnails`)
.get();
// Embeddable viewer URL
const preview = await graphClient
.api(`/users/${userId}/drive/items/${itemId}/preview`)
.post({});
Delta Queries (Efficient Sync)
// Initial sync — get all items
let deltaLink;
let allItems = [];
let response = await graphClient.api(`/users/${userId}/drive/root/delta`)
.select('id,name,deleted,file,folder,parentReference,lastModifiedDateTime')
.get();
allItems.push(...response.value);
// Follow @odata.nextLink for pagination
while (response['@odata.nextLink']) {
response = await graphClient.api(response['@odata.nextLink']).get();
allItems.push(...response.value);
}
// Save deltaLink for next sync
deltaLink = response['@odata.deltaLink'];
console.log(`Initial sync: ${allItems.length} items`);
// --- Later: incremental sync ---
const changes = await graphClient.api(deltaLink).get();
for (const item of changes.value) {
if (item.deleted) {
console.log('Deleted:', item.id);
} else if (item.file) {
console.log('File changed:', item.name);
} else if (item.folder) {
console.log('Folder changed:', item.name);
}
}
// Save new deltaLink
deltaLink = changes['@odata.deltaLink'];
Webhooks and Conversions
Subscribe to file changes via /subscriptions (webhook notifies something changed, then use delta query to get specifics). Convert files server-side by appending ?format=pdf to the content endpoint — works for Word, Excel, and PowerPoint.
Examples
Example 1: Upload project files and share with external partner
User prompt: "Upload the proposal.pdf and budget.xlsx files to the 'Acme Partnership' folder in OneDrive, create the folder if it doesn't exist, and generate a view-only sharing link that expires in 30 days for our partner at sarah@acmecorp.com."
The agent will first create the folder using POST /users/{userId}/drive/root/children with name: 'Acme Partnership' and conflictBehavior: 'rename'. It will then upload both files using simple PUT to /users/{userId}/drive/root:/Acme Partnership/proposal.pdf:/content and the same for budget.xlsx. Finally, it will create a sharing link with type: 'view', scope: 'users', and an expiration date 30 days from now, then send an invite to sarah@acmecorp.com with read-only permissions and a message explaining the shared documents.
Example 2: Sync local directory with OneDrive using delta queries
User prompt: "Set up an efficient sync script that tracks changes in the /Projects/Q1-2026 folder on OneDrive and downloads only files that have been added or modified since the last sync."
The agent will implement an initial delta sync using GET /users/{userId}/drive/root:/Projects/Q1-2026:/delta with select fields for id, name, deleted, file, and lastModifiedDateTime. It will paginate through all results using @odata.nextLink, store the @odata.deltaLink to a local config file, and download each file's content. On subsequent runs, it will call the stored deltaLink to get only changes since last sync, downloading new or modified files and removing locally deleted ones.
Guidelines
- Use delta queries for sync — don't re-list entire folders, track changes incrementally
- Large files (>4MB) must use upload sessions — simple PUT has size limits
@microsoft.graph.conflictBehavior— always specify ('fail', 'replace', or 'rename')- Sharing links with expiry dates and passwords for external sharing — never permanent anonymous links
- Batch requests for multiple operations — max 20 per batch
- Thumbnails are available for images, PDFs, Office docs — use for file previews in UI
?format=pdffor server-side conversion — no need for external tools- Webhook + delta query pattern: webhook notifies "something changed", delta query shows exactly what
- Rate limits: 10,000 requests per 10 min per app per tenant
- OneDrive for Business uses same API as SharePoint document libraries — they're the same service
- Personal OneDrive uses
/me/drive, Business uses/users/{id}/driveor/drives/{driveId}
Information
- Version
- 1.0.0
- Author
- terminal-skills
- Category
- Development
- License
- Apache-2.0