# no-hyperlinks — Full Documentation

> A simple convention for controlling OSC 8 terminal hyperlinks with NO_HYPERLINKS and FORCE_HYPERLINKS.

---

## FAQ | no-hyperlinks

Source: https://no-hyperlinks.org/faq

Background

# FAQ

Short answers for maintainers, terminal nerds, and suspicious users.

## What is OSC 8?

OSC 8 is the escape-sequence convention commonly used by modern terminal software to represent clickable hyperlinks in terminal output.

## Is this a formal standard?

No. This project is a de facto convention for ecosystem adoption. It borrows the clarity of RFC-style writing without claiming ECMA, ISO, or IETF authority.

## Why not rely only on auto-detection?

Auto-detection helps, but it cannot express user preference, accessibility needs, screen-reader issues, auditability, or environments where support exists but is hard to detect reliably.

## Why define both disable and force-enable?

The disable switch gives users a global kill switch. The force-enable switch helps in terminals or pass-through setups where OSC 8 support exists but tool heuristics are conservative.

## Why does NO_HYPERLINKS win over FORCE_HYPERLINKS?

The convention favors predictable user protection and explicit suppression when both variables are present, similar to the general expectation that a negative safety-style override should be easier to reason about.

## Does this apply to terminal emulators too?

Mostly the normative behavior is for emitters. Terminal-side software matters for compatibility, so the guidance asks emulators, multiplexers, and pagers to preserve, strip, or document behavior consistently.

## What problems does this solve?

It gives users and maintainers a common vocabulary for security review, accessibility, plain-text output, debugging, and support conversations across tools.

## How should projects announce support?

Add a short note to CLI help, docs, or changelogs stating that hyperlink behavior honors `NO_HYPERLINKS` and `FORCE_HYPERLINKS`, and specify any local override flags.

---

## NO_HYPERLINKS | A de facto terminal hyperlink convention

Source: https://no-hyperlinks.org/

v1 Draft Convention

# Terminal hyperlinks should respect user intent.

`NO_HYPERLINKS` disables OSC 8 hyperlinks globally. `FORCE_HYPERLINKS` enables them when local heuristics would otherwise hold back. Together they provide a small, predictable control surface for CLI tools, shared output libraries, terminal emulators, multiplexers, and pagers.

[Read the specification](https://no-hyperlinks.org/spec)
[See adoption guidance](https://no-hyperlinks.org/adopt)

## The convention

If `NO_HYPERLINKS` is present and non-empty, emitters do not write OSC 8 sequences. If `FORCE_HYPERLINKS` is present and non-empty, emitters should write OSC 8 sequences unless a stronger local override says otherwise.

## The point

Users already have global knobs for color. Hyperlinks deserve the same clarity for accessibility, privacy, security review, and plain old preference.

## Simple precedence

Explicit CLI or config settings win first. Then `NO_HYPERLINKS`. Then `FORCE_HYPERLINKS`. After that, tools may fall back to normal support detection.

## Emitter-centered

The normative behavior targets applications and libraries that generate terminal output. Terminal-side software is encouraged to preserve and document compatible behavior.

## Adoption-first

This is a de facto convention, not an ECMA, ISO, or IETF standard. It becomes real through consistent implementation and public documentation.

Normative summary

## Recommended decision flow

- Respect explicit command-line or application config overrides first.

- If `NO_HYPERLINKS` is set and non-empty, disable OSC 8 emission.

- Else if `FORCE_HYPERLINKS` is set and non-empty, enable OSC 8 emission.

- Else apply normal TTY and capability detection.

- When disabled, render user-relevant destinations as readable plain text rather than hyperlink-only labels.

For tool authors

## Expose a local override too

The recommended interface is `--hyperlinks=auto|always|never` or an equivalent config setting. This gives users a per-tool escape hatch without undermining the global convention.

For terminal-side software

## Stay predictable

Emulators, multiplexers, and pagers should either preserve OSC 8 sequences, ignore them safely, or document the conditions under which they are stripped or transformed.

---

## Specification | no-hyperlinks

Source: https://no-hyperlinks.org/spec

Version 1

# Specification

This document defines a de facto convention for controlling OSC 8 hyperlink emission in terminal-oriented software.

## 1. Terminology

The key words **MUST**, **SHOULD**, and **MAY** in this document are to be interpreted as requirement language for this convention. They are used in the ordinary RFC-style sense for clarity, but this document is not an IETF standard.

An **emitter** is any application, library, or other component that writes OSC 8 hyperlinks to a terminal stream. Terminal emulators, multiplexers, and pagers are considered **terminal-side software**.

## 2. Environment Variables

### `NO_HYPERLINKS`

If `NO_HYPERLINKS` is present in the environment and its value is not the empty string, emitters **MUST NOT** emit OSC 8 hyperlink sequences unless explicitly overridden by a higher-precedence local control.

### `FORCE_HYPERLINKS`

If `FORCE_HYPERLINKS` is present in the environment and its value is not the empty string, and `NO_HYPERLINKS` does not apply, emitters **SHOULD** emit OSC 8 hyperlink sequences even when automatic detection would otherwise disable them.

## 3. Precedence

Implementations **SHOULD** apply controls in the following order:

- Explicit command-line flags or application config.

- `NO_HYPERLINKS`.

- `FORCE_HYPERLINKS`.

- Automatic support and TTY detection.

If both environment variables are set to non-empty values, `NO_HYPERLINKS` **MUST** take precedence.

## 4. Local Overrides

Emitters **SHOULD** expose a local control such as `--hyperlinks=auto|always|never` or an equivalent config setting.

If an implementation offers local overrides, those controls **MUST** be documented as higher precedence than the environment variables defined here. This keeps behavior explicit and debuggable.

## 5. Fallback Rendering

When hyperlinks are disabled, emitters **SHOULD** render the destination URL in plain text when the destination is relevant to the user. Hyperlink-only labels that hide a meaningful destination should be avoided in disabled mode.

## 6. Terminal-Side Software

Terminal emulators, multiplexers, and pagers are not the primary normative target of this convention, but they play a practical interoperability role.

Terminal-side software **SHOULD** do one of the following predictably:

- Preserve OSC 8 sequences when configured to pass through styled output.

- Ignore or strip OSC 8 sequences safely without corrupting visible text.

- Document relevant behavior and any user-facing controls that affect hyperlinks.

## 7. Governance

This convention begins as **v1**. Feedback should be gathered through public issue tracking and cross-project adoption discussion. Future revisions **SHOULD** be additive where possible and **MUST** clearly describe any breaking semantic changes.

## 8. Reference Implementation

This section is non-normative. [`ansispeck`](https://github.com/kjanat/ansispeck) implements this convention and is available [on npm](https://npm.im/ansispeck) and [JSR](https://jsr.io/@kjanat/ansispeck):

```
npm install ansispeck
# or
deno add jsr:@kjanat/ansispeck
```

---

## Adoption Guide | no-hyperlinks

Source: https://no-hyperlinks.org/adopt

Implementation guide

# Adoption

The fastest path to adoption is consistent emitter behavior, clear local overrides, and documentation that users can actually reason about.

## For CLI tools

- Check local flags or config before reading environment variables.

- Honor `NO_HYPERLINKS` as a non-empty disable switch.

- Honor `FORCE_HYPERLINKS` as a non-empty force-enable switch.

- Fall back to normal support detection when neither variable applies.

- When disabled, print a useful visible URL instead of a link-only label.

## For shared libraries

- Offer one small decision function so downstream tools inherit consistent behavior.

- Keep the decision surface narrow: local mode, env vars, auto-detection result.

- Document exact precedence so application authors do not invent their own variants.

## Suggested interface

Recommended tool-facing behavior uses `auto`, `always`, and `never`. This model maps cleanly onto the convention:

| Local mode | Behavior                                                   |
| ---------- | ---------------------------------------------------------- |
| `never`    | Disable hyperlinks regardless of environment or detection. |
| `always`   | Enable hyperlinks regardless of environment or detection.  |
| `auto`     | Apply environment precedence, then capability detection.   |

## Pseudocode

```
if local_mode == "never":
    return disabled
if local_mode == "always":
    return enabled
if env.NO_HYPERLINKS is non-empty:
    return disabled
if env.FORCE_HYPERLINKS is non-empty:
    return enabled
return detect_hyperlink_support()
```

## For terminal emulators, multiplexers, and pagers

- Preserve OSC 8 pass-through behavior when your styled-output mode allows it.

- Strip safely when hyperlinks are unsupported or disabled.

- Document how hyperlink handling interacts with passthrough, alternate screens, and paged output.

- Do not reinterpret the environment variables as terminal-side policy unless you explicitly advertise that behavior.

## Compatibility notes

This convention does not replace existing hyperlink flags. It gives them a shared global context. Projects with legacy booleans or config keys can map them into the same decision order without renaming public APIs immediately.
