Local-first cache for GitHub Project data with ad hoc and periodic sync.
Project description
gh-project-offline
Local-first cache for a GitHub Project v2 view so humans and agent tools can inspect board data without live GitHub calls on every read.
Alpha scope
This repo is now ready for alpha testing against a real board with:
- read-only sync from one configured GitHub Project v2 view into SQLite
- manual sync and periodic sync
- board item cache plus hydrated issue or pull request details
- cached issue comments, labels, milestone, assignees, state, and raw JSON payloads
- CLI commands for setup checks and offline inspection
- SQL access for human or agent workflows
Not implemented yet
This is still a CLI-first alpha. It does not yet provide:
- a GitHub-like web UI
- dark theme board rendering
- multi-project sync in one config
Quick start
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -e .[dev]
$env:GITHUB_TOKEN = "your-classic-pat"
gh-project-offline start --project-url https://github.com/users/YOUR-OWNER/projects/123/views/1
For end users after publication, prefer:
pipx install gh-project-offline
gh-project-offline start --project-url https://github.com/users/YOUR-OWNER/projects/123/views/1
start is the main onboarding command. It will:
- prompt for the project URL when needed
- prompt for the PAT when the configured env var is missing
- validate access to the target project
- perform the first sync only when the local cache does not already exist
- explicitly ask whether you want to continue into watch mode after initial setup completes
- route existing setups to an explicit next action: one-time sync, watch, or exit
- let you keep or override the sync interval before watch starts
- write runtime files under
.ghpo/
Command roles:
start: guided setup and routing command; it only performs initial load when cache does not already existsync: one manual sync run, then exitwatch: continuous periodic sync until stopped
Run periodic sync every 15 minutes:
gh-project-offline watch --interval 15m
If GITHUB_TOKEN is missing and you run sync or watch from an interactive terminal, the CLI will prompt for it once for that process.
Config
Example config:
[github]
project_url = "https://github.com/users/YOUR-OWNER/projects/123/views/1"
token_env = "GITHUB_TOKEN"
[storage]
database_path = "data/cache.db"
logs_dir = "logs"
[sync]
interval = "15m"
timeout_seconds = 30
user_agent = "gh-project-offline/0.2.0"
include_closed_items = false
You can still set owner, owner_type, project_number, and view_number explicitly, but project_url is the easiest way to get started.
CLI
gh-project-offline start --project-url <board-or-view-url>gh-project-offline start --forcegh-project-offline setupgh-project-offline init --project-url <board-or-view-url>gh-project-offline doctorgh-project-offline syncgh-project-offline watch --interval 15mgh-project-offline statusgh-project-offline summary --by statusgh-project-offline labelsgh-project-offline milestones --format jsongh-project-offline itemsgh-project-offline issuesgh-project-offline find --label bug --state open --status "Todo"gh-project-offline find --format table --sort updated --show repo,number,status,updatedgh-project-offline find --interactivegh-project-offline issue owner/repo 123gh-project-offline query "select * from cached_issue_details limit 5"gh-project-offline capabilities --format yamlgh-project-offline capabilities --format json --output .ghpo/agent-capabilities.json
The capabilities command exports the installed CLI's current commands, arguments, and usage in an agent-friendly format so a repo can reference the generated file from AGENTS.md instead of rediscovering flags from --help every time.
Cached data
The SQLite cache stores:
- project snapshot JSON
- project fields
- project views when the API exposes them
- items for the configured view
- hydrated issue or pull request details for repo-backed board items
- milestone title, due date, description, and state when GitHub provides them
- issue timestamps such as created, updated, and closed time
- issue or pull request descriptions or bodies
- issue comments
- raw JSON payloads alongside normalized columns
Runtime artifacts are isolated under one local app folder by default:
- config:
.ghpo/config.toml - SQLite cache:
.ghpo/data/cache.db - per-session logs:
.ghpo/logs/session-YYYYMMDD-HHMMSS.log
If you already used an older root-level layout during local development, run python scripts/migrate_runtime_layout.py once to move gh-project-offline.toml, data/, and logs/ into .ghpo/.
By default, sync skips closed issues and pull requests during local caching. Set include_closed_items = true in config if you want the cache to include them too.
If GitHub rate-limits a one-shot sync, the tool stops and tells you the suggested cooldown.
During watch, the default behavior is to wait until the reset window passes and then resume the normal cycle.
Use --no-rate-limit-wait with watch or start if you prefer fail-fast behavior instead.
Incremental sync also reuses cached issue/comment state when GitHub reports the item unchanged, so later syncs are much lighter than the first hydration run.
Test with your board
Use the step-by-step guide in docs/TESTING.md for setup, smoke checks, SQL examples, and troubleshooting. For a newcomer-friendly command guide, see docs/GETTING_STARTED.md.
Token note
For user-owned Project v2 view endpoints, GitHub currently documents that a compatible classic-style personal access token is required rather than a fine-grained token or GitHub App token.
For security, the app does not automatically persist the PAT into system-wide environment variables, .env files, or other repository-local files. The safer default is to prompt for it when needed and use it only in the current process unless the user explicitly chooses their own persistence method.
This is primarily a security choice. It is even more important here because the GitHub endpoints used for some user-owned Project v2 flows may require a classic PAT rather than a narrower fine-grained token.
Release docs
Credits
This CLI builds on:
License
GPL-3.0-only
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gh_project_offline-0.2.0.tar.gz.
File metadata
- Download URL: gh_project_offline-0.2.0.tar.gz
- Upload date:
- Size: 59.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4c504e45227ec7a5b25b00e1311904569fd855b3c9dfaf7077a941ad444dd2e6
|
|
| MD5 |
50f9c33e67126bbfdca4468724f14ed0
|
|
| BLAKE2b-256 |
4bdc72d50b75dca2843b54888f5bb197ec5c2d4006dcfa848c9164c0e478dabb
|
Provenance
The following attestation bundles were made for gh_project_offline-0.2.0.tar.gz:
Publisher:
python-publish.yml on Aravinth-Earth/gh-project-offline
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gh_project_offline-0.2.0.tar.gz -
Subject digest:
4c504e45227ec7a5b25b00e1311904569fd855b3c9dfaf7077a941ad444dd2e6 - Sigstore transparency entry: 1102465119
- Sigstore integration time:
-
Permalink:
Aravinth-Earth/gh-project-offline@bf7df81ab9b2575e4ca795a0f240212123b1f65b -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Aravinth-Earth
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@bf7df81ab9b2575e4ca795a0f240212123b1f65b -
Trigger Event:
release
-
Statement type:
File details
Details for the file gh_project_offline-0.2.0-py3-none-any.whl.
File metadata
- Download URL: gh_project_offline-0.2.0-py3-none-any.whl
- Upload date:
- Size: 44.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ab000dd3cbec2028e4ee622d01d218d883830105266f8afa672cf343ea50aa00
|
|
| MD5 |
af516b459a62a12e77bbe6e9c9560609
|
|
| BLAKE2b-256 |
656337db3c5ce2140a49ee90d5cf8e772f4296b8fefac1f0f680e094d22f12aa
|
Provenance
The following attestation bundles were made for gh_project_offline-0.2.0-py3-none-any.whl:
Publisher:
python-publish.yml on Aravinth-Earth/gh-project-offline
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gh_project_offline-0.2.0-py3-none-any.whl -
Subject digest:
ab000dd3cbec2028e4ee622d01d218d883830105266f8afa672cf343ea50aa00 - Sigstore transparency entry: 1102465229
- Sigstore integration time:
-
Permalink:
Aravinth-Earth/gh-project-offline@bf7df81ab9b2575e4ca795a0f240212123b1f65b -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Aravinth-Earth
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@bf7df81ab9b2575e4ca795a0f240212123b1f65b -
Trigger Event:
release
-
Statement type: