> ## 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.

# Nextcloud

> Mount Nextcloud over WebDAV as a filesystem and read or write your files with shell commands.

The Nextcloud VFS mounts a [WebDAV](http://www.webdav.org/specs/rfc4918.html)
server (Nextcloud, ownCloud, Hetzner Storage Share, or any generic WebDAV
endpoint) at some prefix such as `/nc/`. Reads are async and streaming, with
range requests for partial reads.

For credential setup, see [Nextcloud Setup](/home/setup/nextcloud).

## Install

```bash theme={null}
uv add "mirage-ai[nextcloud]"
```

## Config

```python theme={null}
import os

from mirage import MountMode, Workspace
from mirage.vfs.nextcloud import NextcloudConfig, NextcloudVFS

config = NextcloudConfig(
    url=os.environ["NEXTCLOUD_URL"],
    username=os.environ["NEXTCLOUD_USERNAME"],
    password=os.environ["NEXTCLOUD_PASSWORD"],
    # Optional:
    # verify_ssl=True,
    # timeout=30,
)
vfs = NextcloudVFS(config)
ws = Workspace({"/nc/": vfs}, mode=MountMode.WRITE)
```

`NextcloudVFS(config)` takes a `NextcloudConfig` object with the
WebDAV URL plus optional Basic Auth credentials. Both `READ` and `WRITE`
modes are supported. Use an **app password** (Settings → Security in
Nextcloud) rather than your account password.

## Filesystem Layout

WebDAV resources map directly to virtual paths under the mount prefix.

For example, if your Nextcloud root contains:

```text theme={null}
Documents/notes.md
Documents/contract.pdf
Photos/2024/cat.jpg
```

Then mounting at `/nc/` exposes:

```text theme={null}
/nc/
  Documents/
    notes.md
    contract.pdf
  Photos/
    2024/
      cat.jpg
```

Path mapping: virtual `/nc/Documents/notes.md` issues HTTP requests
against `<NEXTCLOUD_URL>/Documents/notes.md`.

## Cache

The Nextcloud VFS uses `IndexCacheStore`. Directory listings come
from a single `PROPFIND Depth: 1` and populate file size, type, and
ETag entries that `stat` reads via a fast path, so a `readdir` followed
by per-entry `stat` calls (which is what `ls`, FUSE `getattr`, and most
shell commands trigger) costs one HTTP request instead of N.

## Fingerprinting and Snapshots

`supports_snapshot = True`. Per-file fingerprints come from the WebDAV
`getetag` property, so snapshot drift detection works automatically:
when a remote file changes, its ETag changes, and Mirage notices on the
next access.

## Example

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

from dotenv import load_dotenv

from mirage import MountMode, Workspace
from mirage.vfs.nextcloud import NextcloudConfig, NextcloudVFS

load_dotenv(".env.development")

config = NextcloudConfig(
    url=os.environ["NEXTCLOUD_URL"],
    username=os.environ["NEXTCLOUD_USERNAME"],
    password=os.environ["NEXTCLOUD_PASSWORD"],
)
vfs = NextcloudVFS(config)


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

    r = await ws.shell("ls /nc/")
    print(await r.stdout_str())

    r = await ws.shell("tree /nc/")
    print(await r.stdout_str())

    r = await ws.shell("find /nc/ -name '*.md'")
    print(await r.stdout_str())

    r = await ws.shell("cat /nc/Documents/notes.md")
    print(await r.stdout_str())

    r = await ws.shell("grep TODO /nc/Documents/notes.md")
    print(await r.stdout_str())

    r = await ws.shell("stat /nc/Documents/notes.md")
    print(await r.stdout_str())


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

## Shell Commands

The Nextcloud VFS supports the full set of shell commands since it
operates on real file content (text, binary, JSON, CSV, etc.). Reads
benefit from HTTP `Range` requests so commands like `head -c BYTES`
don't pull the whole file.

### 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 |

### Text Processing

| Command | Notes |
| - | - |
| `awk` | Pattern scanning and processing |
| `sed` | Stream editor |
| `tr` | Translate or delete characters |
| `sort` | Sort lines |
| `uniq` | Remove duplicate lines |
| `cut` | Extract fields/columns |
| `join` | Join lines on a common field |
| `paste` | Merge lines side by side |
| `column` | Columnate output |
| `fold` | Wrap lines to a specified width |
| `expand` | Convert tabs to spaces |
| `unexpand` | Convert spaces to tabs |
| `fmt` | Simple text formatter |
| `rev` | Reverse lines |
| `tac` | Concatenate and print in reverse |
| `look` | Display lines beginning with a given string |
| `shuf` | Shuffle lines |
| `tsort` | Topological sort |
| `comm` | Compare two sorted files |
| `cmp` | Compare two files byte by byte |
| `diff` | Compare files line by line |
| `patch` | Apply a diff patch |
| `iconv` | Character encoding conversion |

### File Operations

| Command | Notes |
| - | - |
| `cp` | Copy files (WebDAV `COPY` method) |
| `mv` | Move/rename files (WebDAV `MOVE` method) |
| `rm` | Remove files (WebDAV `DELETE`; recursive for directories) |
| `mkdir` | Create directories (WebDAV `MKCOL`) |
| `touch` | Create empty file or update timestamp |
| `ln` | Create symbolic links |
| `tee` | Write stdin to file and stdout |
| `mktemp` | Create temporary file |
| `split` | Split file into pieces |
| `csplit` | Split file by context |

### Path Utilities

| Command | Notes |
| - | - |
| `basename` | Strip directory from path |
| `dirname` | Strip filename from path |
| `realpath` | Resolve path |
| `readlink` | Print symbolic link target |
| `ls` | List directory contents |

### Compression

| Command | Notes |
| - | - |
| `gzip` | Compress files |
| `gunzip` | Decompress gzip files |
| `zip` | Create zip archives |
| `unzip` | Extract zip archives |
| `tar` | Archive files |
| `zcat` | Cat compressed files |
| `zgrep` | Grep compressed files |

### Encoding

| Command | Notes |
| - | - |
| `base64` | Base64 encode/decode |

## Streaming

* **Reads**: streamed in chunks. Downstream commands like `head -n 1`
  early-cancel, so you only pay for the first chunk over the wire.
* **Range reads**: `head -c BYTES` and other partial reads issue HTTP
  `Range` requests that Nextcloud and most WebDAV servers honor.
* **Writes**: buffer the payload before upload. Streaming uploads
  (Nextcloud's `uploads/` resumable protocol) are a possible future
  follow-up.

## Use Cases

* **AI agents accessing personal cloud storage**: Mount Nextcloud so
  agents can read documents, notes, and structured data on a self-hosted
  cloud.
* **Self-hosted alternative to Dropbox/Box**: Same shell-command surface,
  with full read+write support.
* **Multi-protocol WebDAV**: Works against any RFC 4918-compliant server,
  not just Nextcloud.
* **FUSE mounting**: Expose Nextcloud through a virtual FUSE mount for
  external tools.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.