Metadata-Version: 2.4
Name: starmap-gh
Version: 0.1.0
Summary: Organize your GitHub starred repos with AI-assisted categorization
Project-URL: Homepage, https://github.com/AndriiSonsiadlo/starmap
Project-URL: Repository, https://github.com/AndriiSonsiadlo/starmap
Project-URL: Issues, https://github.com/AndriiSonsiadlo/starmap/issues
Author-email: Andrii Sonsiadlo <andrii.sonsiadlo@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: ai,cli,github,organization,starred-repos,stars
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Utilities
Requires-Python: >=3.11
Requires-Dist: anthropic>=0.30
Requires-Dist: httpx>=0.27
Requires-Dist: pyyaml>=6.0
Requires-Dist: rich>=13.0
Requires-Dist: textual>=0.70
Requires-Dist: typer>=0.12
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Provides-Extra: gemini
Requires-Dist: google-genai>=1.0; extra == 'gemini'
Provides-Extra: groq
Requires-Dist: groq>=0.9; extra == 'groq'
Provides-Extra: ollama
Requires-Dist: openai>=1.0; extra == 'ollama'
Provides-Extra: openai
Requires-Dist: openai>=1.0; extra == 'openai'
Description-Content-Type: text/markdown

# starmap

[![CI](https://github.com/AndriiSonsiadlo/starmap/actions/workflows/ci.yml/badge.svg)](https://github.com/AndriiSonsiadlo/starmap/actions/workflows/ci.yml)
[![PyPI](https://img.shields.io/pypi/v/starmap-gh.svg)](https://pypi.org/project/starmap-gh/)

Organize your GitHub starred repos with AI-assisted categorization, right
from the command line.

`starmap` fetches everything you've starred on GitHub, asks an LLM to group
it into a small number of broad, meaningful categories, and lets you review,
rename, merge, and move repos between categories before anything is saved.
It can also read from and write to GitHub's native Lists feature
(github.com/stars), so it works whether you're starting from scratch or
already curate lists there.

Nothing is ever deleted or overwritten silently: every write is backed up,
and AI suggestions are staged separately until you explicitly approve them.

## Features

- Fetches your starred repos via the GitHub API and stores them locally
- Uses an LLM to suggest a small number of broad categories (not a new list
  for every 3-5 repos) - supports Anthropic, OpenAI, Gemini, Groq, and Ollama
- Interactive terminal UI to approve, reject, rename, merge, and move repos
  between categories before anything is saved
- Reads and writes GitHub's native Lists feature (github.com/stars) via its
  GraphQL API, so you can build on lists you already curate there
- Exports your organized stars to Markdown
- Automatic backups before every write; nothing is lost by re-running a command

## Installation

```bash
pip install starmap-gh
```

The PyPI package is named `starmap-gh` (the short name was already taken),
but it installs a command called `starmap`.

To install from source:

```bash
git clone https://github.com/AndriiSonsiadlo/starmap
cd starmap
pip install -e .
```

## Quick start

```bash
# 1. Fetch your starred repos (requires a GitHub token)
export GITHUB_TOKEN=ghp_yourtoken
starmap sync

# 2. Ask an LLM to suggest categories
starmap suggest --provider anthropic

# 3. Review the suggestions: approve, reject, rename, merge, or move repos
#    between categories. Nothing is written until you save.
starmap organize

# 4. Browse the results
starmap list
starmap list "Machine Learning"
starmap list --uncategorized

# 5. Export to Markdown
starmap export
```

## Commands

| Command | Description |
| --- | --- |
| `starmap sync` | Fetch starred repos from GitHub and save them locally |
| `starmap suggest` | Ask an LLM to suggest categories for uncategorized/all repos |
| `starmap organize` | Interactive TUI to review, rename, merge, and move repos between categories |
| `starmap list [category]` | List repos, optionally filtered by category |
| `starmap export` | Export categorized repos to a Markdown file |
| `starmap fetch-lists` | Import your real GitHub Lists as the approved categories |
| `starmap push-lists` | Push approved categories to GitHub Lists |
| `starmap version` | Show the installed version |

Run `starmap <command> --help` for the full set of options for any command.

## AI providers

`starmap suggest --provider <name>` supports:

| Provider | Flag value | Requires | Notes |
| --- | --- | --- | --- |
| Anthropic | `anthropic` | `ANTHROPIC_API_KEY` | Default provider |
| OpenAI | `openai` | `OPENAI_API_KEY` | `pip install starmap-gh[openai]` |
| Google Gemini | `gemini` | `GEMINI_API_KEY` | Free tier available; `pip install starmap-gh[gemini]` |
| Groq | `groq` | `GROQ_API_KEY` | Free tier available; `pip install starmap-gh[groq]` |
| Ollama | `ollama` | A local Ollama server | Fully free/offline; `pip install starmap-gh[ollama]` |

The AI prompt is deliberately biased toward a small number of broad,
durable categories (e.g. "Web Frameworks", "DevOps & Infra", "Data &
Machine Learning") instead of a new category for every handful of repos, so
your stars stay easy to browse instead of fragmenting into dozens of
near-empty lists. If a very large star list causes a response to come back
truncated, lower the batch size with `--chunk-size`/`-c`.

## How your data is kept safe

- `starmap sync` never wipes out local edits: if a repo you already have is
  fetched again, its notes/category fields are carried over.
- `starmap suggest` never overwrites your approved categories. It writes to
  a separate staging file, and tells the AI about your existing categories
  so it reuses them instead of creating near-duplicates. Nothing is final
  until you review it in `starmap organize`.
- Every write to your local data files makes a rolling backup first, so you
  can always recover the previous version.
- `starmap push-lists` makes no changes to your GitHub account unless you
  pass `--experimental`; by default it writes a checklist for you to apply
  by hand.

## `starmap organize` keyboard reference

| Key | Action |
| --- | --- |
| `a` | Approve the selected category |
| `u` | Unapprove the selected category |
| `r` | Rename the selected category (renaming it to an existing category's name merges the two) |
| `m` | Move the selected repo to a different category (typing a new name creates it) |
| `s` | Save approved categories and exit |
| `q` | Quit without saving |

## Working with GitHub Lists (github.com/stars)

GitHub's Lists feature has no REST API, but it is part of GitHub's official
GraphQL schema (`UserList`, `createUserList`, `updateUserListsForItem`, and
so on, added in 2023 - see
[the GraphQL reference](https://docs.github.com/en/graphql/reference/users)).
Two commands build on that:

- **`starmap fetch-lists`** treats your real GitHub Lists as the source of
  truth: it fetches every list and its repos and saves them as your approved
  categories. Run this before `suggest`/`organize` if you already curate
  lists on github.com/stars and want to build on that instead of starting over.
- **`starmap push-lists`** pushes your approved categories back to GitHub.
  By default it writes a checklist you apply by hand and makes no API calls.
  Pass `--experimental` to create/update lists automatically via GraphQL. A
  repo is only added to its target list and removed from other lists
  starmap already knows about that it no longer belongs to; memberships in
  lists outside what was fetched are never touched.

Both commands require a **classic Personal Access Token with the `user`
scope** - broader than the read-only scope `sync` needs, since Lists have no
REST equivalent and live behind GraphQL mutations that require it.

## Configuration

starmap stores its data in `~/.starmap/`:

| File | Contents |
| --- | --- |
| `repos.yaml` | Synced starred repos (`.bak` backup kept alongside) |
| `categories.yaml` | Approved categories (`.bak` backup kept alongside) |
| `categories.suggested.yaml` | Pending AI suggestions awaiting review |

Set `GITHUB_TOKEN` in your environment to avoid passing `--token` on every
command.

## Development

```bash
git clone https://github.com/AndriiSonsiadlo/starmap
cd starmap
uv sync --all-extras
uv run pytest
```

## License

Released under the [MIT License](LICENSE).
