Get Started

How to build it, use it, test it and ship a change. Where code goes: Architecture.

Build and use it

cargo build
./target/debug/lnk --help          # every command
./target/debug/lnk plugin list     # all installed: lnk runs the plugins built next to it
./target/debug/lnk agent start

To have lnk on your PATH instead, from source or a release, and to switch between the two: install.md. To see a tunnel work, with the demo or by hand: run.md.

Test

# everything: about 4 minutes from clean on 4 cores, 2 minutes once built
cargo test
# one crate
cargo test -p link-plugin-harness
# one end-to-end file: the end-to-end tests are one program, each file a module
cargo test -p link-e2e --test e2e tunnel::
# the docs' links, anchors and lnk commands
cargo test -p link-e2e --test e2e docs::
# the spec cases, src/tests/specs/<group>/: a new case is a new file
cargo test -p link-e2e --test e2e specs::

A test that runs lnk gives it a temporary HOME, LNK_SERVICES=off and LNK_KEYCHAIN=off (or a fake security, LNK_SECURITY): a service's or a Keychain item's name doesn't depend on HOME, so without them a test on a Mac stops or replaces your agent and writes your Keychain.

Against your real AWS and Google Cloud accounts, which costs a few cents: live-tests.md.

On Linux with bubblewrap, cargo test also runs the mini harness in the sandbox, its endpoint served out by its proxy (bridge.rs). Link Harness on the wire, against a stand-in model, is tested in its own repository (Link Harness); a harness from outside Link runs the same test against its real harness in its own.

To measure Link's harnesses side by side (install, running, what each sends its model, what it asks for), never in CI: Harness Bench.

Agents as systemctl --user services under a real systemd, in a Docker container, free (Linux, and a Docker that runs privileged containers):

# once, for the rclone its backup check uses
cargo test -p link-plugin-bucket --test rclone
# start, a restart, two agents, a backup, stop, the upgrade from before names
src/tests/services/run.sh

The sandbox with real traffic, free, a few MB of downloads: its probes, its proxy to a real host (pypi.org, or LNK_SANDBOX_TEST_HOST), the kill switch, and git, pip and an MCP server from npm through the proxy:

src/tests/sandbox/run.sh

The sandbox's tests need bubblewrap: Gotchas.

Before you push

Pull requests into dev get no CI, so run these. All must be clean.

cargo fmt --check
cargo clippy --all-targets --locked -- -D warnings
# unit tests, src/tests/e2e (end to end, architecture, help, docs), about 2 minutes once built
cargo test --locked
# on Linux, after a change to the sandbox: its unit tests on the release's libc (musl-tools)
cargo test --locked --target x86_64-unknown-linux-musl -p link-plugin-sandbox --lib
shellcheck src/demos/demo.sh bench/harnesses/run.sh ../.github/publish-release.sh ../.github/sign-release.sh \
  src/local/cli/install.sh src/tests/live/run.sh src/tests/sandbox/run.sh src/tests/services/run.sh \
  src/server/deploy/bootstrap.sh src/server/deploy/create-droplet.sh src/server/deploy/rebuild.sh src/server/deploy/fetch-backup.sh \
  src/server/deploy/files/link-relay-update src/server/deploy/files/link-state

The shellcheck list is the one in the repository's .github/workflows/checks.yml; keep the two in step. A change to the docs is checked by cargo test; the website's own checks, and translating the docs, are on the website's page.

Ship it

git checkout -b my-change origin/dev
# commit, push, open a PR into dev (fill in the template's Release notes)

Releases, cut from dev into main: releases.md.

More

  • architecture.md: the core and its plugins, the layout, the dependency rules, where new code goes
  • conventions.md: the rules every change follows
  • writing-docs.md: how a doc is written, and where it goes
  • run.md: running locally in detail, writing tests, gotchas
  • live-tests.md: lnk against real clouds, and what it costs
  • QA: the checks a person repeats on real machines and accounts
  • plugins.md: adding a plugin, harness, channel or cloud
  • contracts.md: what each lnk ... --json prints
  • specs.md: adding a command's flags, or a spec, and its tests
  • protocol.md: the relay's wire protocol, login
  • decisions.md: why it works this way