Voxta.Packaging 1.10.0

Prefix Reserved
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package Voxta.Packaging --version 1.10.0
                    
NuGet\Install-Package Voxta.Packaging -Version 1.10.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Voxta.Packaging" Version="1.10.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Voxta.Packaging" Version="1.10.0" />
                    
Directory.Packages.props
<PackageReference Include="Voxta.Packaging" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Voxta.Packaging --version 1.10.0
                    
#r "nuget: Voxta.Packaging, 1.10.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Voxta.Packaging@1.10.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Voxta.Packaging&version=1.10.0
                    
Install as a Cake Addin
#tool nuget:?package=Voxta.Packaging&version=1.10.0
                    
Install as a Cake Tool

Voxta Packaging

Reader and writer for .voxpak, the single-file container Voxta ships characters, scenarios and content packages in.

No dependencies, and none on Voxta: this is the format on its own, for anyone hosting or serving Voxta content. The full on-disk format is documented in docs/VOXPAK_SPECIFICATION.md inside the package — complete enough to write an independent reader or writer in another language.

Why not a zip

  • Content addressing. Blobs are keyed by the hash of their contents, so the same asset stored under two paths is written once.
  • Random access. Each blob is split into independently compressed blocks, so seeking into the middle of a 20GB model costs one block decompress rather than a scan from the start.
  • Encryption that keeps it. Blocks are sealed individually with AES-256-GCM, so an encrypted pack is still seekable.

Writing

await using var builder = new VoxPakBuilder(new VoxPakTempFileProvider());

await builder.AddFileAsync("character.json", "/path/to/character.json", ct);
await builder.AddFileAsync("assets/model.vrm", "/path/to/model.vrm", ct);

// Hands back the finished container, rewound. Ownership transfers to you.
await using var pak = await builder.CompleteAsync(ct);
await using var file = File.Create("character.voxpak");
await pak.CopyToAsync(file, ct);

Pass a VoxPakKey to encrypt:

var key = VoxPakKey.Create(new VoxPakSecret.Passphrase("correct horse battery staple"));
await using var builder = new VoxPakBuilder(new VoxPakTempFileProvider(), key);

VoxPakTempFileProvider writes scratch files to the OS temp directory. Packages run to tens of gigabytes and that is often the wrong volume — implement IVoxPakTempFileProvider to put them somewhere with room.

Reading

await using var reader = await VoxPakReader.OpenFileAsync("character.voxpak", secret: null, ct);

foreach (var entry in reader.Entries)
    Console.WriteLine($"{entry.Path} ({reader.GetLength(entry.Path)} bytes)");

// Seekable, decompressed on demand a block at a time. Several may be open at once.
await using var model = reader.OpenRead("assets/model.vrm");

Ask before committing, when you may be handed either kind:

var header = await VoxPakReader.ReadHeaderAsync(stream, ct);
var secret = header.IsEncrypted ? new VoxPakSecret.Passphrase(await PromptAsync()) : null;
await using var reader = await VoxPakReader.OpenAsync(stream, leaveOpen: true, secret, ct);

Reading files from strangers

Opening a container validates it against itself before any entry is read: declared counts are checked against the bytes that could hold them, block tables must cover the length they claim, blobs must lie inside the container and not overlap, and entry paths must be relative and free of traversal. A file that fails any of it is refused at open with an InvalidDataException rather than part-way through serving an asset. The bounds are in VoxPakLimits; §11.1 of the specification states them as requirements, so an independent reader can match.

Entry paths are validated, not sanitised. A consumer writing entries out to disk still owes its own platform-specific checks — reserved device names, trailing dots, case-insensitive collisions.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Voxta.Packaging:

Package Downloads
Voxta.Storage.VoxPak

Storage-side integration for Voxta packages — serves a resource's assets straight out of the .voxpak it was imported from, with the pack cache, scratch-file provider and DI registration that goes with it.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.11.0-beta.1 59 9/23/2026
1.10.0 132 9/4/2026
1.10.0-beta.1 70 9/4/2026
1.10.0-alpha.3 78 8/26/2026
1.10.0-alpha.2 70 8/26/2026
1.10.0-alpha.1 91 8/25/2026