---
title: "Getting started with OneArchive"
url: https://recursiveai.org/onearchive/docs/getting-started/
description: "Install the OneArchive and OneCompress previews for .NET 10, compress a buffer with Zstandard, then create, list, read and safely extract a .tar.zst…"
version: "0.7.0-preview.1"
---

# Getting started with OneArchive

Install the OneArchive and OneCompress previews for .NET 10, compress a buffer with Zstandard, then create, list, read and safely extract a `.tar.zst` archive, all in managed code with no native libraries.

## Install

Both packages target `net10.0`, so you need the .NET 10 SDK. They are previews: this guide uses 0.7.0-preview.1 of both, and the API may change between previews.

```shell
dotnet new console -o OneArchiveStart
cd OneArchiveStart
dotnet add package RecursiveAI.OneArchive --version 0.7.0-preview.1
```

`RecursiveAI.OneArchive` brings in `RecursiveAI.OneCompress`, the codecs. Use OneCompress on its own if you only need codecs and checksums.

## Opt in to the preview APIs

Every codec and the archive layer carry `[Experimental]` until they meet their speed targets, so using one is a compiler error until you opt in. Each has its own diagnostic ID: Zstandard is `ONECOMPRESS001`, Deflate, zlib and gzip `ONECOMPRESS003`, the archive layer `ONEARCHIVE001` (the full table is in [the overview](https://recursiveai.org/onearchive/docs/overview/#preview-codecs)). Add the ones you use to the project file:

```xml
<PropertyGroup>
  <NoWarn>$(NoWarn);ONECOMPRESS001;ONEARCHIVE001</NoWarn>
</PropertyGroup>
```

## A first program

The program compresses a buffer, then archives an `assets/` folder (three JSON level files) and `notes.txt`:

```csharp
using System.Text;
using RecursiveAI.OneArchive;
using RecursiveAI.OneCompress.Zstd;

// One codec call: compress and decompress a buffer.
byte[] data = Encoding.UTF8.GetBytes(string.Concat(Enumerable.Repeat("level=3 tiles=64x64 seed=42\n", 2000)));
byte[] packed = Zstd.Compress(data, new ZstdCompressionOptions { Level = 19 });
byte[] again = Zstd.Decompress(packed);
Console.WriteLine($"zstd: {data.Length:N0} -> {packed.Length:N0} bytes, round trip {again.AsSpan().SequenceEqual(data)}");

// Create an archive: format and compression come from the extension.
Archive.Create("backup.tar.zst").Add("assets/").Add("notes.txt", "docs/notes.txt").Save();
Console.WriteLine($"backup.tar.zst: {new FileInfo("backup.tar.zst").Length:N0} bytes");

// List it, and read one entry by name.
using (var archive = Archive.Open("backup.tar.zst"))
{
    foreach (var e in archive.Entries) Console.WriteLine($"  {e.Kind,-9} {e.Size,7:N0}  {e.Name}");
    using var s = archive.OpenEntry(archive.Find("docs/notes.txt")!);
    Console.WriteLine($"docs/notes.txt says: {new StreamReader(s).ReadToEnd().Trim()}");
}

// Extract it: safe by default, nothing is written outside "out".
Archive.Extract("backup.tar.zst", "out");
Console.WriteLine($"extracted {Directory.GetFiles("out", "*", SearchOption.AllDirectories).Length} files");
```

```text
zstd: 56,000 -> 48 bytes, round trip True
backup.tar.zst: 4,846 bytes
  Directory       0  assets
  Directory       0  assets/levels
  File       20,632  assets/levels/level1.json
  File       20,632  assets/levels/level2.json
  File       20,632  assets/levels/level3.json
  File           15  docs/notes.txt
docs/notes.txt says: Read me first.
extracted 4 files
```

## What each part does

- **`Zstd.Compress` and `Zstd.Decompress`** are one call each; `Level` runs from negative fast levels to 22. Every codec has the same shape: `Lz4`, `Deflate`, `GZip`, `ZLib`, `BZip2`, `Xz`, `Brotli` and the rest, plus stream types for data that doesn’t fit in memory.
- **`Archive.Create(path)`** picks the format and compression from the extension: `.tar`, `.tar.zst`, `.tar.gz`, `.tar.xz`, `.tar.lz4`, `.tar.lz`, `.zip`, `.cfb`, or `.gz`, `.zst`, `.lz4`, `.xz` and `.lz` for one compressed file. `Add(folder)` adds a directory tree; `Add(file, name)` stores a file under another name.
- **`Archive.Open`** finds the format from the bytes, not the name. `Entries` lists them, and `OpenEntry` reads one by random access when the source can seek.
- **`Archive.Extract`** is safe by default: nothing is written outside the target, links can’t escape it, and limits on size, ratio, entry count and path length are on. See [Extract untrusted archives](https://recursiveai.org/onearchive/cookbook/safe-extraction/).

## What it reads and writes

Read and written: tar, zip (with WinZip AES), 7z (with AES-256), cpio, ar, ISO 9660 with Joliet and Rock Ridge, and Microsoft compound files. Read only: cab, and RAR 5 (listing, metadata and stored entries). The compressed bytes are identical on every platform, with and without hardware intrinsics, at any thread count and in WebAssembly.

## Next

- [Extract untrusted archives](https://recursiveai.org/onearchive/cookbook/safe-extraction/)
- [Zip files with AES encryption](https://recursiveai.org/onearchive/cookbook/zip-encryption/)
- [Zstandard dictionaries for small messages](https://recursiveai.org/onearchive/cookbook/zstd-dictionaries/)
- [Archives and safety](https://recursiveai.org/onearchive/docs/archive/): the model, the safety rules and the limits.
