---
title: Keep a local cache
description: Have your AI keep a copy of your tzTrack space's issues on your computer with curl and tar, and refresh it with only what changed.
slug: /guides/keep-a-local-cache
order: 7
visibility: public
redirects_from: []
---

# Keep a local cache

Prompt:

> Keep a local copy of our open issues so you can search them quickly.

Also works: "Cache the tzTrack issues on this machine." "Refresh the issue cache."

## What your tool does

- Finds the cache folder for the project, and reads the instant at the top of its `index.md` if there is one.
- Calls `cache` for a fresh link, downloads the archive with `curl`, and unpacks it with `tar` over the folder.
- Refreshes by asking `cache` what changed since that instant, deleting the files of the numbers no longer answered, and unpacking the changed issues with a fresh index.
- Searches the cache with its own file tools first, and reads an issue live with `read` before it changes it.

## What you need

- A tool that runs commands on your computer, such as Claude Code or Codex. The chat in Claude and ChatGPT cannot reach files on your computer, so it keeps no cache. There, your AI reads the space live. In the Claude desktop app, the Code tab can.

## Before your AI starts

This section is for your AI coding tool: what it checks and gathers before it begins. You don't need to do these steps yourself.

- A shell with `curl` and `tar`, as Claude Code and Codex have. Both ship with Windows 10 and later, macOS, and Linux. Without one, as in Claude or ChatGPT, skip the cache and read live.
- The cache folder. In a Git repository, it is `local/tztrack/cache/` under the folder `git rev-parse --git-common-dir` prints; elsewhere it is `.tztrack/cache/`.
- Whether the cache's `index.md` gives another writer on its second line. If it does, only read that cache, and never download into it.

## Steps

### 1. Find the folder

In a Git repository, print the common folder:

```text
git rev-parse --git-common-dir
```

The cache is `local/tztrack/cache/` under the folder it prints. Elsewhere, the cache is `.tztrack/cache/` in the project's folder. Create the folder if it does not exist.

### 2. Fill it

Call `cache` for a fresh link. The link is yours alone and lasts ten minutes. Download the archive and unpack it over the folder, with the link in place of `<link>` and the folder in place of `<cache folder>`:

```text
curl -fsS -o tztrack-cache.tar.gz "<link>"
tar -xzf tztrack-cache.tar.gz -C "<cache folder>"
```

Delete the downloaded file once it is unpacked. The archive holds `index.md` last, so a partial unpack only looks old.

### 3. Refresh it

Read the instant on the first line of `index.md`, and call `cache` with that instant as `since`. The answer gives the count, the numbers changed, and the numbers no longer answered. Delete `issues/<number>.md` for each number no longer answered. Then download and unpack the link's archive of the changed issues and a fresh index, as in step 2.

### 4. Read it

Search `index.md` and the `issues/` files with your own file tools first. The first line of each issue's file is its state, so `grep -L "^state: closed"` over a search's answers keeps the open ones. Read an issue live with `read` before you change it.

## Expected result

The cache folder holds `index.md`, with its instant on its first line, `writer: tztrack` on its second, and the open issues under their areas. It holds one `issues/<number>.md` per issue, its state on its first line. A refresh changes only the files of the issues that changed, and replaces the index.

## Refusals

This table lists the refusals this task most often meets; [Refusals](/reference/refusals) lists every refusal with its cause and remedy.

| Refusal | Status | Cause | Remedy |
| --- | --- | --- | --- |
| `rate_limited` | 429 | Too many calls within the minute: into the space, from your account on calls that work no space, or from one address with no valid sign-in. The detail names which. Each download counts in the space's rate. | Wait for the minute to turn, then repeat the call. |
| `invalid_request` | 400 | Input is malformed or missing, or names something the server does not take. The detail names the member. In `cache`, it can be a `since` that is not an instant as `index.md` writes it. | Correct the member the detail names, then repeat the call. For `since`, pass the first line's instant as written. |
| `space_mismatch` | 403 | The space named is not one your account owns or is a member of. | Name a space your account owns or is a member of, or leave `space` out. |
| `credential_required` | 401 | The call carried no sign-in, or the sign-in did not finish. | Sign in again through your tool. |

A link older than ten minutes no longer answers: `curl` reports a 401. Call `cache` for a fresh one.

## Related

- [The cache](/concepts/the-cache) explains what the cache holds and why `index.md` comes last.
- [The tools](/reference/the-tools) lists `cache` and `read`.
- [Refusals](/reference/refusals) lists every refusal.
