Metadata-Version: 2.4
Name: olink
Version: 0.1.0
Summary: A CLI tool that opens external URLs related to your project.
Project-URL: Homepage, https://github.com/hasansezertasan/olink
Project-URL: Repository, https://github.com/hasansezertasan/olink
Project-URL: Issues, https://github.com/hasansezertasan/olink/issues
Project-URL: Changelog, https://github.com/hasansezertasan/olink/releases
Author-email: Hasan Sezer Taşan <hasansezertasan@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: bitbucket,cli,developer-tools,git,github,gitlab,npm,open-url,pypi,tui
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development
Classifier: Topic :: Software Development :: Version Control :: Git
Classifier: Topic :: Utilities
Classifier: Typing :: Typed
Requires-Python: >=3.14
Requires-Dist: defusedxml>=0.7.1
Requires-Dist: typer==0.26.7
Provides-Extra: tui
Requires-Dist: pyperclip==1.11.0; extra == 'tui'
Requires-Dist: textual>=3.0.0; extra == 'tui'
Description-Content-Type: text/markdown

# olink

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

## Installation

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

Or with `pipx`:

```bash
pipx install olink
pipx install 'olink[tui]'
```

## Usage

```bash
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.

| 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:

- `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:

```ini
[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`:

```bash
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

| 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

```bash
# 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
```

## Limitations

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

## Requirements

- Python 3.14+

## Development

See `JOURNAL.md` for a chronological record of decisions, attempts (including failures), and outcomes.

## License

MIT
