Skip to content
Open
155 changes: 155 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
<!-- GitHub Copilot / AI agent instructions for wireguard-tools -->

# Purpose

Concise, action-first guidance for AI coding agents to be productive in
`wireguard-tools`. Focus: where to change code, how to build/test, and
project conventions that differ from typical C projects.

# Big picture

- Repo provides userspace tooling for WireGuard: the `wg(8)` CLI and
`wg-quick(8)` helper scripts. Primary code: `src/`. Platform specifics live
under `uapi/` (kernel headers) and `wincompat/` (Windows portability).
- Major areas: `src/` (C CLI tools), `wg-quick/` (shell helpers), `uapi/`,
`completion/`, `systemd/`, `man/`, and `contrib/` + `external-tests/`.

# Quick start (commands you'll use most)

- Build: `cd src && make`
- Verbose build/debug: `cd src && make V=1 DEBUG=yes`
- Install for packaging tests: `make install PREFIX=/usr DESTDIR=<dest> WITH_WGQUICK=yes WITH_BASHCOMPLETION=yes`
- Static analysis: `cd src && make check` (runs `scan-build` if available)
- Cross-build for Windows: set `PLATFORM=windows` (Makefile will use `wincompat/`).

# Code change conventions (important)

- Adding a C source: place under `src/` — the `src/Makefile` builds `*.c`
by default. Keep flags consistent with `CFLAGS` in `src/Makefile`.
- Platform-specific headers go in `uapi/<platform>/` and are added with
`-isystem uapi/$(PLATFORM)`; do not diverge from kernel WireGuard headers
without coordinating upstream kernel changes.
- When adding runtime files (scripts, manpages, completion, systemd units),
update the `install` target in `src/Makefile` so packaging includes them.
- Prefer existing helpers (`ipc-*.h`, `netlink.h`) for IPC and netlink logic.

# Files to read first (high value)

- `src/Makefile` — build, platform detection, install flags (`WITH_WGQUICK`,
`WITH_BASHCOMPLETION`, `WITH_SYSTEMDUNITS`).
- `src/wg.c`, `src/setconf.c`, `src/show.c` — core CLI behavior and parsing.
- `wg-quick/` scripts — show how configs are consumed and expected runtime
behavior for `wg-quick`.
- `uapi/` — kernel/user API headers (keeps user tooling in sync with kernel).

# Testing / validation checklist before PR

- Run `cd src && make V=1` to reproduce compile issues.
- Run `cd src && make check` if changing parsing, memory-handling, or IPC.
- If adding files that affect packaging, run `make install DESTDIR=<tmp>` and
verify installed layout.

# Notes on portability & packaging

- Minimal dependencies: project targets portability and a plain libc.
- Keep changes small and portable. Avoid introducing new heavy deps.

# PR tips for reviewers

- Include the minimal build and install commands you used to verify the
change. Show `make V=1` output if build flags or toolchain changes were
required.
- If you changed `uapi/`, state why it must differ from upstream kernel
headers and include references.

# If you're stuck

- Read `README.md` and `src/Makefile` first. If build errors persist, paste
`make V=1` output and relevant `gcc/clang` errors into the PR description.

---
If you'd like, I can (a) shorten or expand any section, (b) add a short
walkthrough for adding a CLI flag in `wg.c`, or (c) include a sample PR
checklist. Which would you prefer?

## Walkthrough — Add a small CLI flag to an existing subcommand

Example: add a simple `--example-flag` to the `show` subcommand.

- Files to edit: `src/show.c` (subcommand implementation) and, if needed,
tests or `man/` pages.
- Typical steps:
1. Locate the subcommand entry in `src/wg.c` (the `subcommands[]` table lists
available subcommands and their `*_main` functions; `show` maps to `show_main`).
2. Open `src/show.c` and find `show_main` — it handles argc/argv for `show`.
3. Add minimal flag parsing near the top of `show_main`. This project uses
simple `argv` checks rather than a heavy option parser; follow existing
patterns (see checks for `argc` and `argv[1]` already in `show_main`).
4. Implement the behavior (set a local `bool` or configuration struct and
branch later in the printing functions such as `pretty_print` or
`ugly_print`).
5. Build and run the subcommand locally: `cd src && make V=1 && ./wg show --help`.
6. Run `make check` if you changed parsing or memory handling.

- Minimal illustrative code sketch (adapt to project's helpers):

```c
// in src/show.c, inside show_main before printing
bool example_flag = false;
for (int i = 1; i < argc; ++i) {
if (!strcmp(argv[i], "--example-flag")) {
example_flag = true;
// optionally remove the consumed arg or shift argv
}
}
// Later, in pretty_print or dump_print, use `example_flag` to alter output
```

Keep changes small and follow existing formatting and error handling patterns.

## Walkthrough — Add a `uapi/<platform>/` header

Use this when you need to add platform-specific kernel/user API headers
that the `src/` build will include via `-isystem uapi/$(PLATFORM)`.

- Files to edit: create `uapi/<platform>/linux/wireguard.h` (or matching
platform path) and keep contents aligned with kernel headers.
- Typical steps:
1. Duplicate the closest existing platform header under `uapi/` and
adapt only the necessary differences. The project expects these
headers to match the kernel WireGuard API.
2. Update `src/Makefile` only if you need to add a new install step
for the header; usually `-isystem uapi/$(PLATFORM)` is sufficient.
3. Build locally: `cd src && make V=1` and ensure the compiler uses
the `uapi/` header (compiler include paths appear with `V=1`).
4. Add tests or mention kernel version differences in the PR description
when the header intentionally diverges from upstream kernel headers.

## Commit & DCO checklist

Before pushing, ensure commits are signed off to satisfy the DCO bot:

- Set git identity (one-time):

```bash
git config user.name "Your Name"
git config user.email "[email protected]"
```

- Make a commit and sign-off:

```bash
git add <files>
git commit -s -m "docs: update copilot instructions (concise)"
```

- If DCO fails on the PR, amend the offending commit with a sign-off and force-push:

```bash
git commit --amend --no-edit --signoff
git push --force-with-lease
```

- Use `gh` to open the PR or post follow-up comments if you fix DCO or CI.

This checklist is intentionally minimal — use it to avoid common DCO issues.
104 changes: 104 additions & 0 deletions .github/copilot-instructions.original.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<!-- GitHub Copilot / AI agent instructions for wireguard-tools -->

# Purpose

Short, actionable guidance for AI coding agents to be immediately productive in
this repository. Focus on how the project is structured, build/test/debug
workflows, and concrete file examples you should read before changing code.

# Big picture

- **What this repo is**: userspace tooling for WireGuard: the `wg(8)` CLI and
`wg-quick(8)` helper scripts. Primary code lives in `src/` and platform
specifics under `uapi/` and `wincompat/`.
- **Major components**:
- `src/` — main C sources (`wg.c`, `setconf.c`, `show.c`, etc.) and `src/Makefile`.
- `wg-quick/` — platform-specific shell scripts (bash) used by install.
- `uapi/` — platform-specific kernel/user API headers included at build time.
- `contrib/` and `external-tests/` — sample integrations and language bindings.
- `wincompat/` — compatibility layer and resources for Windows builds.

# What to read first (examples)

- `README.md` — project overview and canonical build/install commands.
- `src/Makefile` — most important: how compilation, platform detection, and
installation variables work (`PREFIX`, `WITH_WGQUICK`, `WITH_BASHCOMPLETION`).
- `src/wg.c`, `src/setconf.c`, `src/show.c` — core CLI behavior and parsing.
- `wg-quick/` — how the quick helper expects configuration files.
- `uapi/linux/` — shows kernel-compatible headers used when compiling.

# Build, test and debug (concrete commands)

- Build the tools (recommended):

`cd src && make`

- Install (honors packaging env vars):

`make install PREFIX=/usr DESTDIR=... WITH_WGQUICK=yes WITH_BASHCOMPLETION=yes`

- Useful Makefile knobs:
- `V=1` — disable pretty short messages and print full compiler/linker commands.
- `DEBUG=yes` — compile with `-g` for debugging symbols.
- `PLATFORM=$(uname -s | tr '[:upper:]' '[:lower:]')` is auto-detected.

- Static analysis:

`cd src && make check` # runs `scan-build` if available

- Windows cross-build: `wincompat/` files are used when `PLATFORM=windows`.
The Makefile sets `CC` for mingw (`x86_64-w64-mingw32-clang`) when building
for Windows; inspect `wincompat/` for resource and manifest handling.

# Project-specific conventions & patterns

- Minimal dependencies: the top-level `README.md` states "no dependencies other
than a good C compiler and a sane libc." Expect simple, portable C patterns.
- Platform headers: `src/Makefile` adds `-isystem uapi/$(PLATFORM)` when that
directory exists. Prefer adding platform-specific headers under `uapi/`.
- Packaging variables and conditional installs are controlled in `src/Makefile`.
When adding files that should be packaged, update `install` target there.
- Shell helpers: `wg-quick` is intentionally a small, opinionated bash script;
changes to interface/flags must remain compatible with it.

# Integration points & external interfaces

- Kernel/user API: code relies on headers in `uapi/` to match kernel wireguard
definitions — don't diverge without coordinating kernel changes.
- System integration: systemd unit templates are in `systemd/`; `install`
target will optionally install them if `WITH_SYSTEMDUNITS` is enabled.
- Completion scripts are under `completion/` and are installed when
`WITH_BASHCOMPLETION=yes`.
- `contrib/embeddable-wg-library/` contains an example of embedding wireguard
logic into other languages; use it as a reference for integrations.

# Testing & external test harnesses

- Look at `external-tests/` for example consumers in Go, Rust, Python and
Haskell. These show how others interact with the CLI or wireguard APIs.
- Fuzzing harness is in `fuzz/` with its own `Makefile` — follow that
directory's README before changing the fuzz targets.

# Helpful patterns and examples for edits

- When adding a new source file to `src/`, add it to the wildcard `*.c` pattern
in `src/Makefile` (it already builds all `*.c`). Keep compilation flags
consistent with the existing `CFLAGS` defined there.
- To preserve portable behavior, prefer using existing helpers in `ipc-*.h`
and `netlink.h` rather than adding custom platform IPC code.

# What an AI agent should do when making a change

1. Read `src/Makefile` and the relevant `uapi/<platform>/` headers.
2. Run `cd src && make V=1` locally to verify build commands and locate
compile-time failures.
3. Update `install` target only if adding runtime files (scripts, manpages,
completions, systemd units) and test installation locally using `DESTDIR`.
4. Run `make check` if the change touches memory/undefined behavior sensitive
code and static analysis is available.

# Questions / feedback

If any of these sections are unclear or you'd like more examples (e.g. a
short walkthrough of adding a new CLI flag in `wg.c`), tell me which area to
expand and I'll update this file.
28 changes: 28 additions & 0 deletions contrib/external-tests/show_flag_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: MIT
# Small integration test: build `wg` and check that `wg show --help` mentions --show-keys
set -euo pipefail

REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
cd "$REPO_ROOT/src"

echo "Building src/ (this may take a moment)..."
make V=1 || { echo "Build failed"; exit 2; }

WG_BIN="$REPO_ROOT/src/wg"
if [ ! -x "$WG_BIN" ]; then
echo "wg binary not found at $WG_BIN" >&2
exit 3
fi

echo "Checking 'wg show --help' for --show-keys flag"
HELP_OUT="$($WG_BIN show --help 2>&1 || true)"

if echo "$HELP_OUT" | grep -q -- "--show-keys"; then
echo "OK: --show-keys documented in show help"
exit 0
else
echo "FAIL: --show-keys not found in show help output:" >&2
echo "$HELP_OUT" >&2
exit 4
fi
25 changes: 25 additions & 0 deletions external-tests/show_flag_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env bash
set -euo pipefail

# Simple smoke test: build the `wg` binary and verify `--show-keys` appears
# in the `wg show --help` output. This runs from the repository root so it
# works when invoked from CI or the workspace root.

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
SRC_DIR="${REPO_ROOT}/src"

echo "Repository root: ${REPO_ROOT}"
echo "Building src/... (this may take a moment)"
cd "${SRC_DIR}"
make V=1

echo "Checking help for --show-keys"
if ./wg show --help 2>&1 | grep -q -- '--show-keys'; then
echo "OK: --show-keys present in help"
exit 0
else
echo "FAIL: --show-keys not found in help output"
./wg show --help 2>&1 | sed -n '1,200p'
exit 2
fi
8 changes: 8 additions & 0 deletions preview/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Preview placeholder

This directory contains a simple placeholder page (`index.html`) used to
prevent 404 responses when using preview/forwarding services (codespaces,
app.github.dev, etc.) that expect a file at a particular path.

If you want a custom preview page or a different path, tell me what to add
and I'll update it.
24 changes: 24 additions & 0 deletions preview/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Preview — wireguard-tools</title>
<style>
body{font-family:system-ui,-apple-system,Segoe UI,Roboto,'Helvetica Neue',Arial;background:#f7fafc;color:#0f172a;margin:0;display:flex;align-items:center;justify-content:center;height:100vh}
.card{max-width:760px;padding:28px;border-radius:12px;background:white;box-shadow:0 6px 24px rgba(2,6,23,0.08)}
h1{margin:0 0 8px 0;font-size:20px}
p{margin:0 0 8px 0;color:#334155}
a{color:#0366d6}
</style>
</head>
<body>
<div class="card">
<h1>Preview placeholder — wireguard-tools</h1>
<p>This is a lightweight placeholder page created so repository previews do not return 404.</p>
<p>Repo: <a href="https://github.com/SupananWC/wireguard-tools" target="_blank" rel="noreferrer">SupananWC/wireguard-tools</a></p>
<p>Branch: <code>update/copilot-instructions</code></p>
<p>If you want a different preview path or content, tell me the desired filepath or HTML and I'll update it.</p>
</div>
</body>
</html>
2 changes: 1 addition & 1 deletion src/completion/wg.bash-completion
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ _wg_completion() {
fi

if [[ $COMP_CWORD -eq 3 && ${COMP_WORDS[1]} == show && ${COMP_WORDS[2]} != interfaces ]]; then
COMPREPLY+=( $(compgen -W "public-key private-key listen-port peers preshared-keys endpoints allowed-ips fwmark latest-handshakes persistent-keepalive transfer dump" -- "${COMP_WORDS[3]}") )
COMPREPLY+=( $(compgen -W "--show-keys public-key private-key listen-port peers preshared-keys endpoints allowed-ips fwmark latest-handshakes persistent-keepalive transfer dump" -- "${COMP_WORDS[3]}") )
return
fi

Expand Down
7 changes: 7 additions & 0 deletions src/man/wg.8
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ fwmark. Subsequent lines are printed for each peer and contain in order separate
by tab: public-key, preshared-key, endpoint, allowed-ips, latest-handshake,
transfer-rx, transfer-tx, persistent-keepalive.
.TP
\fBshow\fP [\fI--show-keys\fP] { \fI<interface>\fP | \fIall\fP | \fIinterfaces\fP } [\fIpublic-key\fP | \fIprivate-key\fP | \fIlisten-port\fP | \fIfwmark\fP | \fIpeers\fP | \fIpreshared-keys\fP | \fIendpoints\fP | \fIallowed-ips\fP | \fIlatest-handshakes\fP | \fIpersistent-keepalive\fP | \fItransfer\fP | \fIdump\fP]
.PP
If the special option \fI--show-keys\fP is provided before the interface
argument, the pretty-printing output will reveal private and preshared keys
for debugging (this respects the `WG_HIDE_KEYS=never` override). Use with care
as keys are sensitive.
.TP
\fBshowconf\fP \fI<interface>\fP
Shows the current configuration of \fI<interface>\fP in the format described
by \fICONFIGURATION FILE FORMAT\fP below.
Expand Down
Loading