olink
A CLI tool that opens external URLs related to your project.
Table of Contents
- Installation
- Usage
- Available Targets
- Examples
- Interactive TUI
- Limitations
- Requirements
- Motivation
- Features
- Support
- Analysis
- Contributing
- Development
- Releasing
- Author
- Credits
- License
- Changelog
- Contributors
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]'
Install with Homebrew (macOS/Linux):
brew install hasansezertasan/tap/olink
Install with Scoop (Windows):
scoop bucket add hasansezertasan https://github.com/hasansezertasan/scoop-bucket
scoop install hasansezertasan/olink
Usage
olink open <target> # Open a target URL in the browser
olink url <target> # Print the URL without opening it
olink list # List targets available for current project
olink list --all # List all targets
olink interactive # Launch the TUI (needs the `tui` extra)
olink info # Version, Python and platform details
olink --version # Show olink version
Every command accepts -d/--directory to use a different project directory, and
open, url, list, version and info accept --json for scripts and agents:
olink url pypi --json # {"target": "pypi", "url": "https://pypi.org/project/olink/"}
olink list --json # {"scope": "available", "count": 26, "targets": [...]}
Under --json, stdout is always exactly one JSON document, including errors
({"error": {"type": "UnknownTargetError", "message": "..."}}). Failures exit
with a distinct code: 1 generic, 3 unknown target, 4 bad directory,
5 not a git repo, 6 no remote, 7 missing project metadata,
8 unsupported on this platform, 9 unknown git host. Bare olink prints help.
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.
| Target | Description |
|---|---|
origin |
Open the remote origin URL |
upstream |
Open the upstream remote URL |
issues |
Open the issues page |
pulls |
Open pull/merge requests page |
actions |
Open CI/CD page (Actions, Pipelines) |
wiki |
Open the wiki page |
releases |
Open the releases page |
branches |
Open the branches page |
commits |
Open the commit history |
security |
Open the security page |
discussions |
Open the discussions page |
Supported Platforms
| Platform | Issues | PRs/MRs | CI/CD | Wiki | Releases |
|---|---|---|---|---|---|
| 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:
discussionsis GitHub-onlysecurityis 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
| Target | Description | Config File |
|---|---|---|
pypi |
Open PyPI page | pyproject.toml |
inspector |
Open PyPI Inspector | pyproject.toml |
pypi-json |
Open PyPI JSON API | pyproject.toml |
pepy |
Open PePy download stats | pyproject.toml |
piwheels |
Open piwheels project page | pyproject.toml |
pypistats |
Open PyPI Stats | pyproject.toml |
piptrends |
Open Pip Trends | pyproject.toml |
clickpy |
Open ClickPy stats (ClickHouse) | pyproject.toml |
safety-db |
Open Safety DB vulnerabilities | pyproject.toml |
Multi-Ecosystem Targets
These services support multiple ecosystems (Python, npm, Rust, Go).
| Target | Description | Ecosystems |
|---|---|---|
snyk |
Open Snyk security advisor | pypi, npm, cargo, go |
libraries-io |
Open Libraries.io | pypi, npm, cargo, go |
deps |
Open deps.dev (Google Open Source) | pypi, npm, cargo, go |
ecosystems |
Open ecosyste.ms | pypi, npm, cargo, go |
socket |
Open Socket.dev package health | pypi, npm, cargo, go |
Suffix Notation: For projects with multiple ecosystems, use target:ecosystem:
olink open snyk:pypi # Explicit Python
olink open snyk:npm # Explicit npm
olink open deps:cargo # Explicit Rust
If only one ecosystem is detected, the suffix is optional and auto-detection is used.
npm Targets
| Target | Description | Config File |
|---|---|---|
npm |
Open npm page | package.json |
bundlephobia |
Open Bundlephobia (bundle size) | package.json |
packagephobia |
Open Packagephobia (install) | package.json |
npm-stat |
Open npm-stat download charts | package.json |
jsdelivr |
Open jsDelivr package page | package.json |
unpkg |
Open UNPKG package page | package.json |
skypack |
Open Skypack package page | package.json |
Rust Targets
| Target | Description | Config File |
|---|---|---|
crates |
Open crates.io page | Cargo.toml |
librs |
Open lib.rs (alternative browser) | Cargo.toml |
docsrs |
Open docs.rs API docs | Cargo.toml |
Go Targets
| Target | Description | Config File |
|---|---|---|
pkg-go |
Open pkg.go.dev module page | go.mod |
go-docs |
Open pkg.go.dev documentation | go.mod |
Other Ecosystem Targets
| Target | Description | Config File |
|---|---|---|
packagist |
Open Packagist (PHP) | composer.json |
pub |
Open pub.dev (Dart) | pubspec.yaml |
gems |
Open RubyGems | *.gemspec |
rubygems-stats |
Open RubyGems download stats | *.gemspec |
open-vsx |
Open the Open VSX extension page | package.json |
maven |
Open Maven Central artifact page | pom.xml |
hackage |
Open Hackage package page | *.cabal |
cpan |
Open MetaCPAN module page | Makefile.PL, dist.ini, or lib/*.pm |
hex |
Open hex.pm (Elixir) | mix.exs |
nuget |
Open NuGet (.NET) | *.csproj |
Service Targets
| Target | Description |
|---|---|
codecov |
Open Codecov page |
coveralls |
Open Coveralls page |
Examples
# Open the GitHub repo for your project
olink open origin
# Open issues page
olink open issues
# Check the PyPI page for your package
olink open pypi
# View download stats on PePy
olink open pepy
# Check security vulnerabilities on Snyk
olink open snyk
# In a monorepo with Python + npm, use explicit ecosystem
olink open snyk:pypi # Check Python package on Snyk
olink open deps:npm # View npm deps on deps.dev
olink open socket:npm # Check npm package health on Socket.dev
# View dependency graph on deps.dev
olink open deps
# Check npm bundle size
olink open bundlephobia
# Open releases page
olink open releases
# Open code coverage
olink open codecov
# Preview URL without opening browser
olink url pulls
# Open origin for a different project
olink open origin -d ~/projects/other-project
# See which targets work for your project
olink list
Interactive TUI
Launch the interactive target browser with:
olink interactive # 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 targetso— open the highlighted targetc— copy target URLp— 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 ❤️
If you have any questions or need help, feel free to open an issue on the GitHub repository.
Analysis
- Snyk Python Package Health Analysis
- Libraries.io - PyPI
- Safety DB
- PePy Download Stats
- PyPI Download Stats
- Pip Trends Download Stats
- PyPI Map Dependency Graph
Contributing ❤️
Any contributions are welcome! Please follow the Contributing Guidelines to contribute to this project.
Development 🧰
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 Repository setup guide for one-time configuration and optional post-launch integrations such as a social preview, downstream packaging, and Repology.
Pause merges that change .github/workflows/, including Renovate action-pin updates, from merging a release PR until the entire Release run finishes. Workflow differences between the release commit and current main can block tag or release creation with a 403 when using GITHUB_TOKEN. See Release recovery for prevention and recovery steps.
For adoption or template-update reconciliation, ask your agent to "audit this
template adoption/update against our existing project behavior".
The shipped template-adoption skill
also supports audits after an update was applied. It compares workflow behavior,
required checks, custom tooling, and documentation, and asks before consequential
cleanup. Its prek-workflow example shows why duplicate commands alone do not
justify removing a workflow. Use the sibling repo-setup skill for repository
settings and release setup.
Author 🫅
This project is maintained by Hasan Sezer Taşan. It's me 👋
Credits
This package was created with Copier and the hasansezertasan/copier-pyproject project template.
License 📜
This project is licensed under the MIT License.
Changelog 📝
For a detailed list of changes, please refer to the CHANGELOG.
Contributors
Thanks goes to these wonderful people (emoji key). This project follows the all-contributors specification — contributions of any kind welcome! Add a contributor with the bot (@all-contributors please add @user for code) or the CLI.
Hasan Sezer Taşan 🚧 💻 📖 ⚠️ 🤔 |
Metadata
Release files for olink 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| olink-0.3.0.tar.gz | 79.2 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| olink-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 118.2 kB
Release files / olink-0.3.0.tar.gz
| Download URL | olink-0.3.0.tar.gz |
|---|---|
| Size | 79.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b12d70582c482884354c2dc182f5fa25af60732ed4c035d7cec0ab4b7d118f54
|
|
BLAKE2b-256 checksum How to use checksums |
630d5bd93b5832d60035150ca0b97c707f63ae95a26d036eb29698b962df1fdd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.
Transparency logRelease files / olink-0.3.0-py3-none-any.whl
| Download URL | olink-0.3.0-py3-none-any.whl |
|---|---|
| Size | 39.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
24a5dce882bd49838931101db658e0e4ec39ef9e422566a931ff75e400274e1e
|
|
BLAKE2b-256 checksum How to use checksums |
24d33c0f3af4e102d01d002038273ca0476326981a99988739d1337e50999f13
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.
Transparency logSecurity for olink 0.3.0
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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for olink-0.3.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.
Transparency logA 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.