Skip to main content

projscan

Python 3.9+ Version Downloads

Scanner for local git repositories and uv tools installed from git.
Answers one simple question: am I up to date?

Quick start

No installation needed — run directly with uvx:

uvx  projscan repos .
uvx  projscan tools

Installation

uv tool install projscan

Or in development mode:

git clone ...
cd projscan
uv sync
uv run projscan --help

Commands

projscan repos [PATHS]...

Recursively scans one or more directories and displays the status of each git repository.

╭──────────────────────┬─────────┬─────────┬─────────────────────┬────────┬────────────────────┬─────────────╮
│ Name                 │ Version │ Branch  │ Status              │ Commit │ Message            │ When        │
├──────────────────────┼─────────┼─────────┼─────────────────────┼────────┼────────────────────┼─────────────┤
│ my-api               │ 2.1.0   │ main    │ behind (↓3)         │ a4f2c1 │ fix: timeout retry │ 2 days ago  │
│ my-dashboard         │ 1.0.0   │ main    │ diverged (↓1 ↑2)    │ b8e3d9 │ feat: dark mode    │ 5 hours ago │
│ projscan             │ 0.1.0   │ main    │ up to date          │ c1a2b3 │ initial commit     │ 1 hour ago  │
╰──────────────────────┴─────────┴─────────┴─────────────────────┴────────┴────────────────────┴─────────────╯
3 repos, 1 up to date, 2 to update

Options:

Option Description
--no-fetch Skip git fetch — use local cache (fast)
--depth INTEGER Max recursion depth (default: 3)
--json Machine-readable JSON output
--concurrency INTEGER Parallel scans (default: 16)
# Scan ~/code and ~/work
projscan repos ~/code ~/work

# Fast, no network
projscan repos --no-fetch ~/code

# Pipe JSON to jq
projscan repos --no-fetch --json ~/code | jq '.[] | select(.status != "up to date")'

projscan tools

Scans tools installed via uv tool install git+https://... and checks whether updates are available (via git ls-remote, without cloning).

╭────────────────┬─────────┬───────────────────────────────┬────────┬──────────┬────────────────╮
│ Name           │ Version │ Source                        │ Ref    │ Commit   │ Status         │
├────────────────┼─────────┼───────────────────────────────┼────────┼──────────┼────────────────┤
│ my-tool        │ 1.2.0   │ github.com/org/my-tool.git    │ main   │ f10c2123 │ update avail.  │
│ other-tool     │ 0.9.1   │ github.com/org/other-tool.git │ main   │ fc9e74c5 │ up to date     │
╰────────────────┴─────────┴───────────────────────────────┴────────┴──────────┴────────────────╯
2 tools, 1 up to date, 1 to update

Options:

Option Description
--tool-dir PATH uv tools root directory (auto-detected by default)
--no-remote List locally without checking remotes
--json Machine-readable JSON output
projscan tools
projscan tools --no-remote --json
projscan tools --tool-dir ~/.local/share/uv/tools

Exit codes

Code Meaning
0 Everything is up to date
1 At least one item needs updating (or has an error)
2 Fatal execution error
130 Keyboard interrupt (Ctrl-C)

Useful in scripts or CI:

projscan repos --no-fetch ~/code || echo "Some repos are behind!"

Status colors

Status Color Meaning
up to date green In sync with upstream
behind (↓N) red N remote commits not yet pulled
ahead (↑N) cyan N local commits not yet pushed
diverged (↓N ↑M) magenta Branches have diverged
update avail. yellow New version of the tool available
no upstream grey No tracking branch configured
not git grey Tool installed from PyPI, not git
unknown grey Remote unreachable (offline, auth…)
error bold red Error during scan

Usage as a library

projscan is designed to be imported in a Textual app or any other async code.

from pathlib import Path
from projscan import scan_paths, scan_tools, RepoInfo, ToolInfo

# Scan git repositories
repos: list[RepoInfo] = await scan_paths(
    [Path("~/code")],
    fetch=True,
    max_depth=3,
    concurrency=16,
)

for repo in repos:
    print(f"{repo.name}: {repo.status}")

# Scan uv tools
tools: list[ToolInfo] = await scan_tools(check_remote=True)

for tool in tools:
    if tool.status == "update avail.":
        print(f"Update available: {tool.name}")

Dataclasses expose an .as_dict() method for JSON serialization:

import json
print(json.dumps([r.as_dict() for r in repos], ensure_ascii=False))

Full public API:

from projscan import (
    # Git
    RepoInfo, scan_paths, scan_repo, find_repos,
    # UV tools
    ToolInfo, scan_tools, scan_tool, uv_tool_dir,
)

Development

uv sync
uv run pytest           # 52 tests, ~5s
uv run projscan repos . # real-world test
uv run projscan tools   # real-world test

Metadata

Release files for projscan 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for projscan 0.1.2
File Size Uploaded Provenance Actions
projscan-0.1.2.tar.gz 29.6 kB Without provenance Details for projscan-0.1.2.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for projscan 0.1.2
File Interpreter ABI Platform Actions
projscan-0.1.2-py3-none-any.whl Python 3 none any Details for projscan-0.1.2-py3-none-any.whl

Total release size: 44.5 kB

Release files / projscan-0.1.2.tar.gz

Download URL projscan-0.1.2.tar.gz
Size 29.6 kB
Tags Source
SHA-256 checksum
How to use checksums
908e83801fc17e54fd55fa6e5e4f091cf893601cf7298022399885ff8b1565c3
BLAKE2b-256 checksum
How to use checksums
cce21505bba979126945db28d8c57e0939917e1bef6144c32906d9d63cf2ed42
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.24 {"installer":{"name":"uv","version":"0.11.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / projscan-0.1.2-py3-none-any.whl

Download URL projscan-0.1.2-py3-none-any.whl
Size 15.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2b2034cbaded0e0b8a1de8b2482d31654c1992828d172caa986d104e01dccdeb
BLAKE2b-256 checksum
How to use checksums
9bcc8d03eb9bc55e64b1cadc5113e7f8080999e715e16df705b24923bc751488
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.24 {"installer":{"name":"uv","version":"0.11.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for projscan 0.1.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page