> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mirage.strukto.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# OneDrive

> Mount Microsoft OneDrive or SharePoint document libraries as a Mirage filesystem with async access, versioning, and shell commands.

The OneDrive VFS mounts a Microsoft OneDrive (or SharePoint document
library) at some prefix such as `/onedrive/`. All operations involve network
I/O to Microsoft Graph. Files are served as raw bytes (no Office filetype
conversion). Uses aiohttp for async Graph access.

Compatible with: personal OneDrive, OneDrive for Business, and SharePoint
document libraries (driveItems on Microsoft Graph v1.0).

For credential setup (tokens, drive ids, app vs delegated auth), see the
[OneDrive Setup](/home/setup/onedrive) guide.

## Config

```python theme={null}
import os

from mirage import MountMode, Workspace
from mirage.vfs.onedrive import OneDriveVFS, OneDriveConfig

config = OneDriveConfig(
    access_token=os.environ["MS_GRAPH_DRIVE_TOKEN"],
    # Optional:
    # Name at most one drive:
    # drive_id="b!...",        # target a specific drive (required for app-only tokens)
    # site_id="contoso.sharepoint.com,...",  # a SharePoint site's default drive
    # group_id="...",          # a Teams / Microsoft 365 group's library
    # user_id="user@contoso.com",  # another user's drive (app-only)
    # graph_base_url="https://graph.microsoft.us/v1.0",  # non-worldwide root
    # key_prefix="Documents/",  # mount a sub-folder as the root
    # timeout=30,
)

vfs = OneDriveVFS(config)
ws = Workspace({"/onedrive": vfs}, mode=MountMode.WRITE)
```

`OneDriveVFS(config)` takes an `OneDriveConfig` object with a Microsoft
Graph bearer token and optional drive/site targeting. Both `READ` and `WRITE`
modes are supported.

### Config Reference

| Field            | Required | Description                                                            |
| ---------------- | -------- | ---------------------------------------------------------------------- |
| `access_token`   | Yes      | Microsoft Graph OAuth2 bearer token                                    |
| `drive_id`       | No       | Target a specific drive. Required for app-only tokens (no `/me/drive`) |
| `site_id`        | No       | A SharePoint site's default drive                                      |
| `group_id`       | No       | A Teams / Microsoft 365 group's document library                       |
| `user_id`        | No       | Another user's drive, by id or UPN (app-only auth)                     |
| `graph_base_url` | No       | Full service root, for any deployment but the worldwide one            |
| `key_prefix`     | No       | Mount a sub-folder of the drive as the root                            |
| `timeout`        | No       | Request timeout in seconds (default `30`)                              |

### Naming the drive

`drive_id`, `site_id`, `group_id` and `user_id` are four ways of saying which
drive the mount is, so set **at most one**. Setting two raises at config time
rather than silently addressing whichever came first, which otherwise surfaces
much later as an unexplained 404. Setting none means `/me/drive`, the
signed-in user's own drive, which is the only form that needs no extra
identifier and the only one unavailable to an app-only token.

### The service root

Mounts address `https://graph.microsoft.com/v1.0` unless `graph_base_url` says
otherwise. Set it to reach anything else: a sovereign cloud, a private
endpoint, or a test server. Give the full root including the version segment,
for example `https://graph.microsoft.us/v1.0`.

This matters most for the sovereign deployments, which are network-isolated
instances rather than regions: a token minted for one is rejected by the
others, so a mount pointed at the wrong root fails outright rather than
degrading. mirage does not ship a table of their hostnames, since it has no
way to verify one; take the root from Microsoft's national cloud
documentation for your tenant.

Because the root is read from the config rather than a module constant, two
mounts in one process can address different deployments.

## Filesystem Layout

The OneDrive VFS maps Graph driveItems (path-addressed) to virtual paths
under the mount prefix. Folders are real driveItems, so the tree matches what
you see in OneDrive.

For example, if the drive contains:

```text theme={null}
Documents/file.txt
Documents/config.json
Reports/q1.csv
Reports/q2.csv
```

Then mounting at `/onedrive/` exposes:

```text theme={null}
/onedrive/
  Documents/
    file.txt
    config.json
  Reports/
    q1.csv
    q2.csv
```

Path mapping: virtual `/onedrive/Documents/file.txt` maps to the driveItem at
`/root:/Documents/file.txt`.

## Versioning and Snapshots

OneDrive keeps per-file version history. The VFS exposes it the same way
the S3 backend does:

* **Fingerprint** is the driveItem `cTag`, so normal reads and `stat` reflect
  the current content without extra Graph calls.
* **Snapshots** pin each path to a Graph driveItem version id. Replaying a
  snapshot reads `/versions/{id}/content`, giving time-travel to the exact
  bytes captured at snapshot time.
* **Restore** writes a previous version back as the current one.

This makes the OneDrive VFS `SUPPORTS_SNAPSHOT = True`.

## Cache

The OneDrive VFS caches directory listings via `IndexCacheStore` to reduce
repeated Graph calls during traversal.

## Example

```python theme={null}
import asyncio
import os

from mirage import MountMode, Workspace
from mirage.vfs.onedrive import OneDriveVFS, OneDriveConfig

config = OneDriveConfig(
    access_token=os.environ["MS_GRAPH_DRIVE_TOKEN"],
    drive_id=os.environ.get("MS_GRAPH_DRIVE_ID") or None,
)

vfs = OneDriveVFS(config)


async def main() -> None:
    ws = Workspace({"/onedrive/": vfs}, mode=MountMode.WRITE)

    r = await ws.execute("ls /onedrive/")
    print(await r.stdout_str())

    await ws.execute("echo 'hello from mirage' > /onedrive/note.txt")

    r = await ws.execute("cat /onedrive/note.txt")
    print(await r.stdout_str())

    r = await ws.execute("stat /onedrive/note.txt")
    print(await r.stdout_str())

    r = await ws.execute("tree /onedrive/")
    print(await r.stdout_str())


if __name__ == "__main__":
    asyncio.run(main())
```

A runnable version lives at `examples/python/onedrive/onedrive.py`.

## Shell Commands

The OneDrive VFS supports the full set of shell commands since it operates
on real file content (text, binary, JSON, CSV, etc.). Large files benefit from
range reads to avoid downloading entire items.

### Read Commands

| Command         | Notes                                      |
| --------------- | ------------------------------------------ |
| `cat`           | Read file content                          |
| `head` / `tail` | First/last N lines                         |
| `grep` / `rg`   | Pattern search (file or directory level)   |
| `jq`            | Query JSON fields                          |
| `wc`            | Line/word/byte counts                      |
| `stat`          | File metadata (name, size, type, modified) |
| `find`          | Recursive search with `-name`, `-maxdepth` |
| `tree`          | Directory tree view                        |
| `nl`            | Number lines                               |
| `du`            | Disk usage summary                         |
| `file`          | Detect file type                           |
| `strings`       | Extract printable strings from binary      |
| `xxd`           | Hex dump                                   |
| `md5`           | MD5 checksum                               |
| `sha256sum`     | SHA-256 checksum                           |

### File Operations

| Command | Notes                                 |
| ------- | ------------------------------------- |
| `cp`    | Copy files                            |
| `mv`    | Move/rename files                     |
| `rm`    | Remove files                          |
| `mkdir` | Create directories                    |
| `touch` | Create empty file or update timestamp |
| `tee`   | Write stdin to file and stdout        |

### Path Utilities

| Command    | Notes                     |
| ---------- | ------------------------- |
| `basename` | Strip directory from path |
| `dirname`  | Strip filename from path  |
| `realpath` | Resolve path              |
| `ls`       | List directory contents   |

## Use Cases

* **AI agents accessing org documents**: Mount OneDrive/SharePoint for agents to read and process files
* **Versioned document workflows**: Snapshot and replay exact file states over time
* **Sandboxed access**: Restrict agent operations to a specific drive and sub-folder via `key_prefix`
* **FUSE mounting**: Expose a OneDrive through a virtual FUSE mount for external tools

## Scoping a VFS to a folder

Pass `key_prefix: str | None = None` to `OneDriveConfig` to transparently scope
every operation to a sub-folder of the drive:

```python theme={null}
OneDriveVFS(OneDriveConfig(
    access_token=token,
    drive_id=drive_id,
    key_prefix=f"users/{user_id}/",
))
```

When set, every read/write/list/stat/copy/rename/delete operation is scoped to
that sub-folder. Agents see clean paths like `/data/notes.md`; the underlying
driveItem is `users/{user_id}/data/notes.md`. Useful for multi-tenant systems.

**Normalization:** leading slashes are stripped and a trailing slash is added
automatically. Both `None` and an empty string are treated as "no prefix."
