--- title: Nextcloud icon: cloud --- The Nextcloud resource 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 uv add "mirage-ai[nextcloud]" ``` ## Config ```python import os from mirage import MountMode, Workspace from mirage.resource.nextcloud import NextcloudConfig, NextcloudResource config = NextcloudConfig( url=os.environ["NEXTCLOUD_URL"], username=os.environ["NEXTCLOUD_USERNAME"], password=os.environ["NEXTCLOUD_PASSWORD"], # Optional: # verify_ssl=True, # timeout=30, ) resource = NextcloudResource(config) ws = Workspace({"/nc/": resource}, mode=MountMode.WRITE) ``` `NextcloudResource(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 Documents/notes.md Documents/contract.pdf Photos/2024/cat.jpg ``` Then mounting at `/nc/` exposes: ```text /nc/ Documents/ notes.md contract.pdf Photos/ 2024/ cat.jpg ``` Path mapping: virtual `/nc/Documents/notes.md` issues HTTP requests against `/Documents/notes.md`. ## Cache The Nextcloud resource 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 import asyncio import os from dotenv import load_dotenv from mirage import MountMode, Workspace from mirage.resource.nextcloud import NextcloudConfig, NextcloudResource load_dotenv(".env.development") config = NextcloudConfig( url=os.environ["NEXTCLOUD_URL"], username=os.environ["NEXTCLOUD_USERNAME"], password=os.environ["NEXTCLOUD_PASSWORD"], ) resource = NextcloudResource(config) async def main() -> None: ws = Workspace({"/nc/": resource}, mode=MountMode.WRITE) r = await ws.execute("ls /nc/") print(await r.stdout_str()) r = await ws.execute("tree /nc/") print(await r.stdout_str()) r = await ws.execute("find /nc/ -name '*.md'") print(await r.stdout_str()) r = await ws.execute("cat /nc/Documents/notes.md") print(await r.stdout_str()) r = await ws.execute("grep TODO /nc/Documents/notes.md") print(await r.stdout_str()) r = await ws.execute("stat /nc/Documents/notes.md") print(await r.stdout_str()) if __name__ == "__main__": asyncio.run(main()) ``` ## Shell Commands The Nextcloud resource 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 | ### Data Format Support Commands with format-specific variants for structured data files: | Format | Extension | Variants | | ------- | ---------- | ---------------------------------------------- | | Parquet | `.parquet` | cat, head, tail, wc, stat, cut, grep, ls, file | | Feather | `.feather` | cat, head, tail, wc, stat, cut, grep, ls, file | | ORC | `.orc` | cat, head, tail, wc, stat, cut, grep, ls, file | | HDF5 | `.hdf5` | cat, head, tail, wc, stat, cut, grep, ls, file | These variants auto-detect the format by extension and convert to tabular text (CSV) for processing. ## 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.