
# Tar export

`tar` adds one command, **Export as Tarball**, to a folder's context menu in the explorer and to
the command palette. Running it walks that folder and downloads it as a `.tar.gz`.

```ts
import { tar } from "codelet/extensions/tar";
import { FileSystem, Workbench } from "codelet/workbench";

const workbench = new Workbench({
  parent: document.getElementById("app")!,
  fs: new FileSystem({ "/src/index.ts": "export const hi = 1;\n" }),
  extensions: [tar],
});
```

`tar` takes no options.

## Try it

Right-click the `src` folder in the explorer and choose **Export as Tarball** — your browser
downloads `src.tar.gz`, holding `src/index.ts` and `src/greet.ts`.

::codelet-playground{mode="workbench" extensions="tar" active="src/index.ts" height="420"}

```ts [src/index.ts]
import { greet } from "./greet";

console.log(greet("codelet"));
```

```ts [src/greet.ts]
export const greet = (name: string) => `hi ${name}`;
```

```md [README.md]
# greet

Right-click `src` in the tree to take it with you.
```

::

## Where the command appears

Right-click any folder's row for that folder alone, under its own name. For the whole workspace,
as `workspace`: the button in the explorer's heading, the tree's own context menu below the last
row, or `Tar: Export as Tarball` from the palette.

## No library, either direction

Nothing is fetched and nothing is bundled. The ustar format — a 512-byte header per entry — is
written out directly, and gzip is the browser's own `CompressionStream`; a browser without one
downloads a plain `.tar` instead of failing. The archive always has a single top-level directory
named after the folder, so extracting it can't spray files over wherever you extract it.

## What lands in the archive

A `FileSystem` holds every file as text, so a file's bytes in the archive are usually its text,
UTF-8 encoded — unless that text is where the bytes actually are, the same address form
[`media`](/extensions/media) reads:

| The file holds                | Where it comes from                               | In the archive                       |
| ----------------------------- | ------------------------------------------------- | ------------------------------------ |
| `data:image/png;base64,…`     | dropping a file into the workbench                | the bytes it stands for              |
| A URL, or a path off the page | [`remote`](/extensions/remote) mirroring a binary | the bytes, fetched                   |
| One line of bare base64       | a host that seeded the tree that way              | the bytes, if they aren't valid text |

That's what makes dropping a folder of images into the workbench and exporting it again give you
the images back, and what makes exporting a remote-backed workspace give you its binaries rather
than a folder of one-line text files.

::note
The fetch for a remote-backed file is the page's own — a remote whose authentication is a
wrapped `fetch` (the `fetch` option on [`httpTransport`](/extensions/remote)) isn't reachable
from here, so its files come back as the addresses they are. A fetch that fails leaves the file
as that address and is reported in an output channel named `Tar Export`, which the
[Logs extension](/extensions/logs) shows if you're running it — the download still happens.
::

Directories are kept, including empty ones.

:read-more{to="/extensions"}
