ITADN
README.md

olink

CI Coverage Documentation Status PyPI - Version PyPI - Python Version License - MIT GitHub Stars Latest Commit

Checked with mypy linting - Ruff OpenSSF Scorecard GitHub Tag

Downloads Downloads/Month Downloads/Week

A CLI tool that opens external URLs related to your project.


Table of Contents

Installation

uv tool install olink            # CLI only
uv tool install 'olink[tui]'     # Include the interactive TUI

Or with pipx:

pipx install olink
pipx install 'olink[tui]'

Usage

olink <target>              # Open a target URL
olink -n <target>           # Dry-run: print URL without opening
olink -d /path <target>     # Use a different project directory
olink --list                # List targets available for current project
olink --list-all            # List all targets
olink --version             # Show olink version

Available Targets

Git Targets

Automatically detects GitHub, GitLab, Bitbucket, Gitea, and Forgejo (incl. Codeberg) from your remote URL. Self-hosted instances are detected by hostname keyword matching.

TargetDescription
originOpen the remote origin URL
upstreamOpen the upstream remote URL
issuesOpen the issues page
pullsOpen pull/merge requests page
actionsOpen CI/CD page (Actions, Pipelines)
wikiOpen the wiki page
releasesOpen the releases page
branchesOpen the branches page
commitsOpen the commit history
securityOpen the security page
discussionsOpen the discussions page

Supported Platforms

PlatformIssuesPRs/MRsCI/CDWikiReleases
GitHub/issues/pulls/actions/wiki/releases
GitLab/-/issues/-/merge_requests/-/pipelines/-/wikis/-/releases
Bitbucket/issues/pull-requests/pipelines/wiki/downloads

Note: Some features are platform-specific:

  • discussions is GitHub-only
  • security is not available on Bitbucket, Gitea, or Forgejo
  • Gitea/Forgejo paths mirror GitHub (/issues, /pulls, /releases, etc.)

SSH aliases (insteadOf): olink honors [url "<rewritten>"].insteadOf = <prefix> rules in .git/config. Longest-prefix match wins, matching git's own behavior. This means shorthand remotes like github:owner/repo resolve correctly when you have:

[url "git@github.com:"]
    insteadOf = github:

Python / PyPI Targets

TargetDescriptionConfig File
pypiOpen PyPI pagepyproject.toml
inspectorOpen PyPI Inspectorpyproject.toml
pypi-jsonOpen PyPI JSON APIpyproject.toml
pepyOpen PePy download statspyproject.toml
piwheelsOpen piwheels project pagepyproject.toml
pypistatsOpen PyPI Statspyproject.toml
piptrendsOpen Pip Trendspyproject.toml
clickpyOpen ClickPy stats (ClickHouse)pyproject.toml
safety-dbOpen Safety DB vulnerabilitiespyproject.toml

Multi-Ecosystem Targets

These services support multiple ecosystems (Python, npm, Rust, Go).

TargetDescriptionEcosystems
snykOpen Snyk security advisorpypi, npm, cargo, go
libraries-ioOpen Libraries.iopypi, npm, cargo, go
depsOpen deps.dev (Google Open Source)pypi, npm, cargo, go
ecosystemsOpen ecosyste.mspypi, npm, cargo, go
socketOpen Socket.dev package healthpypi, npm, cargo, go

Suffix Notation: For projects with multiple ecosystems, use target:ecosystem:

olink snyk:pypi     # Explicit Python
olink snyk:npm      # Explicit npm
olink deps:cargo    # Explicit Rust

If only one ecosystem is detected, the suffix is optional and auto-detection is used.

npm Targets

TargetDescriptionConfig File
npmOpen npm pagepackage.json
bundlephobiaOpen Bundlephobia (bundle size)package.json
packagephobiaOpen Packagephobia (install)package.json
npm-statOpen npm-stat download chartspackage.json
jsdelivrOpen jsDelivr package pagepackage.json
unpkgOpen UNPKG package pagepackage.json
skypackOpen Skypack package pagepackage.json

Rust Targets

TargetDescriptionConfig File
cratesOpen crates.io pageCargo.toml
librsOpen lib.rs (alternative browser)Cargo.toml
docsrsOpen docs.rs API docsCargo.toml

Go Targets

TargetDescriptionConfig File
pkg-goOpen pkg.go.dev module pagego.mod
go-docsOpen pkg.go.dev documentationgo.mod

Other Ecosystem Targets

TargetDescriptionConfig File
packagistOpen Packagist (PHP)composer.json
pubOpen pub.dev (Dart)pubspec.yaml
gemsOpen RubyGems*.gemspec
rubygems-statsOpen RubyGems download stats*.gemspec
open-vsxOpen the Open VSX extension pagepackage.json
mavenOpen Maven Central artifact pagepom.xml
hackageOpen Hackage package page*.cabal
cpanOpen MetaCPAN module pageMakefile.PL, dist.ini, or lib/*.pm
hexOpen hex.pm (Elixir)mix.exs
nugetOpen NuGet (.NET)*.csproj

Service Targets

TargetDescription
codecovOpen Codecov page
coverallsOpen Coveralls page

Examples

# Open the GitHub repo for your project
olink origin

# Open issues page
olink issues

# Check the PyPI page for your package
olink pypi

# View download stats on PePy
olink pepy

# Check security vulnerabilities on Snyk
olink snyk

# In a monorepo with Python + npm, use explicit ecosystem
olink snyk:pypi      # Check Python package on Snyk
olink deps:npm       # View npm deps on deps.dev
olink socket:npm     # Check npm package health on Socket.dev

# View dependency graph on deps.dev
olink deps

# Check npm bundle size
olink bundlephobia

# Open releases page
olink releases

# Open code coverage
olink codecov

# Preview URL without opening browser
olink -n pulls

# Open origin for a different project
olink -d ~/projects/other-project origin

# See which targets work for your project
olink --list

Interactive TUI

Launch the interactive target browser with:

olink                # Open TUI (requires [tui] extra)

The TUI lets you browse, search, open, and pin targets interactively. Keybindings:

  • Tab — toggle view (available/all)
  • j/k — navigate up/down
  • / — search targets
  • o — open the highlighted target
  • c — copy target URL
  • p — pin/unpin the highlighted target. Pinned targets are marked with and float to the top of the list in every project. Pins are stored in $XDG_CONFIG_HOME/olink/pins.json (default ~/.config/olink/pins.json).
  • q — quit

Limitations

  • olink must be run from the project root directory. Running from a subdirectory (e.g. src/) is not supported.

Requirements

  • Python 3.14+

Motivation

The metadata for any project already lives in files you keep in the repo — the git remote in .git/config, the package name in pyproject.toml, package.json, Cargo.toml, and friends. Yet the pages you actually want to visit (the PyPI page, the issue tracker, download stats, a security advisor) are scattered across dozens of hosts, each with its own URL shape. olink reads those files directly and opens the right page for you — no bookmarks to maintain, no URLs to memorize, and it works the same way in every project you cd into.

Features

  • Zero configuration: Detects your platform and package name from files already in the repo (.git/config, pyproject.toml, package.json, Cargo.toml, go.mod, …).
  • Wide platform coverage: GitHub, GitLab, Bitbucket, Gitea, and Forgejo (incl. Codeberg), with self-hosted instances detected by hostname.
  • Many ecosystems: Python, npm, Rust, Go, PHP, Dart, Ruby, Java/Maven, Haskell, Perl, Elixir, and .NET package registries and stats services.
  • Interactive TUI: Browse, search, open, copy, and pin targets from a Textual terminal interface (via the [tui] extra).
  • File I/O over subprocess: Reads config files directly instead of shelling out to git/npm, so it is fast and dependency-light.
  • Type Safety: Full type hints checked by mypy and basedpyright.
  • Modern Python: uv for dependency management, hatch for building.

Support :heart:

If you have any questions or need help, feel free to open an issue on the GitHub repository.

Analysis

Contributing :heart:

Any contributions are welcome! Please follow the Contributing Guidelines to contribute to this project.

Development :toolbox:

Clone the repository and cd into the project directory:

git clone https://github.com/hasansezertasan/olink
cd olink

Install

Install the dependencies:

uv sync

Style

Run the style checks:

uv run --locked tox run -e style

Hooks

Run the prek hooks (a separate CI job, not part of tox run). The ghalint hook runs the mise-managed binary, so install the mise tools first — exactly as the CI hooks job does:

mise install
uv run --locked tox run -e prek

CI

Run the test pipeline (the style, cli, and 3.14 tox environments):

uv run --locked tox run

To reproduce the full CI locally, run the hooks command above as well — CI runs prek hooks in a separate job.

Docs

Build the documentation site:

uv run --locked tox run -e docs-build

Start the live-reloading docs server:

uv run --locked tox run -e docs-server

Releasing

Versioning and releases are automated with release-please, driven by Conventional Commit PR titles squash-merged into main. release-please maintains a release PR that bumps the version and CHANGELOG.md; merging it tags the release and publishes to PyPI. See the Contributing Guidelines for the commit conventions and the one-time Repository setup (squash-merge settings, Actions permissions, release immutability, and PyPI trusted publishing).

Author :person_with_crown:

This project is maintained by Hasan Sezer Taşan. It's me :wave:

Credits

This package was created with Copier and the hasansezertasan/copier-pyproject project template.

License :scroll:

This project is licensed under the MIT License.

Changelog :memo:

For a detailed list of changes, please refer to the CHANGELOG.