# Build a template downloader

> Download repository files and reuse the saved copy.

## What you'll build

A Bun script that downloads a repository, reports its files, and reuses the cached copy.

### Before you start

- Bun, Git, and the system tar, cp, and mkdir commands.
- An empty working directory and network access to a public repository.

Write a script that downloads a repository into `downloaded-template/`. Run it twice to see how the cache works.

## 1. Create the project

In an empty directory, initialize a package:

### Install with bun

```sh
bun init -y
```

### Install with npm

```sh
npm init -y
```

### Install with pnpm

```sh
pnpm init
```

### Install with yarn

```sh
yarn init -y
```

Install the downloader:

### Install with bun

```sh
bun add @hulla/gittar@0.0.4
```

### Install with npm

```sh
npm install @hulla/gittar@0.0.4
```

### Install with pnpm

```sh
pnpm add @hulla/gittar@0.0.4
```

### Install with yarn

```sh
yarn add @hulla/gittar@0.0.4
```

## 2. Copy the repository

Create `download.ts` at the project root. Keeping the cache in this project makes it easy to inspect the two directories:

```ts filename="download.ts"
import gittar from '@hulla/gittar'
import { resolve } from 'node:path'

const snapshot = await gittar({
  url: 'hulladev/gittar',
  branch: 'master',
  cacheDir: resolve('.cache/gittar/master'),
  outDir: resolve('downloaded-template'),
})

console.log(snapshot.fromCache ? 'Used cache' : 'Downloaded')
console.log(`Copied ${snapshot.files.length} files to ${snapshot.outDir}`)
```

`url` selects the repository. `branch` selects the ref to download. `outDir` keeps the editable copy separate from the [cache](https://hulla.dev/docs/gittar/caching.md).

> **Warning: Choose an empty destination**
>
> Copying uses `cp -R` and can replace files with matching names. Use a new directory for this tutorial. Repeated copies don't remove files that disappeared upstream.

## 3. Run it twice

Run the script with Bun, even if you used another package manager to install it:

```sh
bun download.ts
```

The first run prints `Downloaded` and a file count. Open `downloaded-template/package.json`: it should name `@hulla/gittar`. The cache directory contains the full extracted repository and its metadata.

Run the same command again. If the remote branch hasn't changed and the cache is intact, it prints `Used cache`. The default policy still contacts the remote to check the commit; a cache hit doesn't mean an offline run.

## 4. Change the policy

Add this property to the same config object when you want to reuse the local snapshot without a remote freshness check:

```ts
update: 'never',
```

Run `bun download.ts` again. It uses the existing cache. On a fresh machine, `never` still downloads because no snapshot exists yet.

You now have the download stage of a scaffolding tool. Next, [copy one folder or handle stale snapshots](https://hulla.dev/docs/gittar/caching.md). For command-line options such as `--destination`, add an [`@hulla/args` parser](https://hulla.dev/guides/args/quick-start.md) around this script.
