gist-neko 1.27
CLI for downloading all gists from a specified user.
Requires Python: >=3.10
Keywords: python, gist downloader, downloader, gist, gist-neko, kuroneko

# gist-neko

CLI for downloading all gists from a specified user.

## Installation

### Via PyPI (Recommended)

#### With pip (Basic)

```sh
pip install gist-neko
```

#### With pipx (Isolated)

```sh
pipx install gist-neko
```

#### With uv (Best)

The most efficient way to install or run gist-neko.

```sh
# Permanent isolated installation
uv tool install gist-neko

# Run once without installing
uvx gist-neko -u <username>

# Run in scripts or ad-hoc environments
uv run --with gist-neko gist-neko -u <username> -t <token>
```

### From Source (Development)

```sh
# Clone the repository and navigate to it
git clone git@github.com:NecRaul/gist-neko.git
cd gist-neko

# Install environment and all development dependencies (mandatory and optional)
uv sync --dev

# Install pre-commit hook
uv run pre-commit install

# Optional: Run all linters and type checkers manually
uv run pre-commit run --all-files

# Run the local version
uv run gist-neko -e -g
```

## Usage

`gist-neko` acts as a sync tool. If a gist folder doesn't exist, it clones it, if it does, it updates it.

```sh
# Download/Sync public gists with `requests`
gist-neko -u <github-username>

# Download/Sync public and private gists with `requests` (using a token)
gist-neko -u <github-username> -t <github-personal-access-token>

# Use 'git clone/pull' instead of 'requests' (preserves history, branches and submodules)
gist-neko -u <github-username> -g

# Use 'git' with a token for private gist syncing
gist-neko -u <github-username> -t <github-personal-access-token> -g
```

### Environment Variables

You can save your credentials to environment variables to avoid passing them manually in every command.

For persistence, add these exports to your shell configuration file (e.g., `~/.bashrc`, `~/.zshrc`, or `~/.bash_profile`).

```sh
# Set your credentials as environment variables
export GITHUB_USERNAME="NecRaul"
export GITHUB_PERSONAL_ACCESS_TOKEN="ghp_necraul"

# Run using the stored environment variables
gist-neko -e

# Run using environment variables with the git engine
gist-neko -e -g

# Pass environment variables directly within the command
GITHUB_USERNAME="NecRaul" GITHUB_PERSONAL_ACCESS_TOKEN="ghp_necraul" gist-neko -e
```

### Options

```sh
-u, --username      USERNAME    GitHub username to download gists from
-t, --token         TOKEN       GitHub personal access token (required for private gists)
-e, --environment   -           Use stored environment variables for username and token
-g, --git           -           Use git engine instead of requests (handles history/branches/submodules)
```

> [!TIP]
> The `-e` and `-g` flags are a boolean toggle.

## Dependencies

* [requests](https://github.com/psf/requests): fetch data from the GitHub API and handle downloads.

## How it works

The tool queries the `https://api.github.com/users/{username}/gists` endpoint. It retrieves public Gists when unauthenticated, or both public and private Gists when an authentication token is provided.

Once the gist list is retrieved, `gist-neko` automates the synchronization process using one of two engines:

* Requests Engine (Default): Fetches the gist as a compressed snapshot. This is fast but does not include **history**, **branches** or **submodules**.
* Git Engine (via `-g` or `--git` flag): Uses your local **git** installation to perform a full **clone** or **pull** This preserves the complete **history**, **branches** and **submodules**.

### The Manual Way

Without this tool, you would need to manually parse JSON responses, manage authentication headers, and write logic to differentiate between new clones and existing updates:

```sh
# A simplified version of the logic gist-neko automates
# It fetches the id and description, then loops through them
curl -s -H "Authorization: token $GITHUB_PERSONAL_ACCESS_TOKEN" https://api.github.com/users/NecRaul/gists |
    jq -r '.[] | "\(.description // .id) \(.id)"' | while read -r name id; do
    if [ ! -d "$name" ]; then
        git clone --recursive "git@gist.github.com:$id.git" "$name"
    else
        echo "Pulling '$name'..."
        git -C "$name" pull --recurse-submodules
    fi
done
```

### The gist-neko way

* Dynamic API Routing: Automatically identifies the correct GitHub endpoint. It uses `/users/{username}/gists` for browsing, ensuring that when authenticated, you get the full list of both public and private gists you have permission to view.
* State-Aware Syncing: Instead of a simple download, it checks your local file system using the gist's description or ID as the folder name. If a gist already exists, it intelligently switches to an "update" mode (using `git pull` or overwriting via `requests`) to keep your local mirror current.
* Hybrid Engine Support:
  * Lightweight Mode: Uses `requests` to pull gist snapshots quickly without needing `git` installed or **SSH keys** configured.
  * Developer Mode (`-g`): Interfaces directly with your local `git` binary to handle **full history**, **branch tracking**, and **submodule recursion**.
* Subprocess Management: Uses `Python`'s `subprocess` and `os` modules to provide a robust bridge between the `GitHub API` and your local shell, handling directory navigation and command execution automatically.`