From fbaab1d37775232b2d66ae8ed2812a9c35dc3d8a Mon Sep 17 00:00:00 2001 From: Dominic Rubas <1042243+rubas@users.noreply.github.com> Date: Sat, 26 Sep 2026 23:22:09 +0200 Subject: [PATCH 1/2] docs: plain English README and AGENTS.md, fix stale skill facts --- AGENTS.md | 88 ++++++++++++++++------------------------ README.md | 117 +++++++++++++++++------------------------------------- 2 files changed, 71 insertions(+), 134 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 03bb953..dd557cf 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,66 +1,48 @@ # kagi -## Goal - -Unofficial Unix-style CLIs for Kagi: `kagi-search`, `kagi-maps`, `kagi-summarize`. -Each binary ships a companion agent skill from `skills/`. +Three Unix-style CLIs for Kagi, `kagi-search`, `kagi-maps`, and `kagi-summarize`, and one agent +skill, `skills/kagi`, for all three. `README.md` covers install, the token, and usage. ## Gates -- `task ci` runs `task check`, the release-profile check, `nix build`, - cargo-machete, and cargo-deny. GitHub Actions runs all but `task test:nix`, so - run `task ci` yourself after you touch `flake.nix`, `flake.lock`, or - `Cargo.toml`. A lock-only input refresh still ships a Nix build nothing else - checks. -- `task lint` calls `zizmor`. The `nix develop` shell does not ship it, so put - `zizmor` on `PATH` before you run lint or check. -- `task test:live` hits the real Kagi service. Run it when you change the - request path or a parser: `src/cli.rs`, `src/client.rs`, or `src/parse.rs`. It - needs `KAGI_SESSION_TOKEN` or `~/.config/kagi/session-token` and fails without - one. +- `task ci` runs `task check`, the release-profile check, `nix build`, cargo-machete, and + cargo-deny. GitHub Actions runs all of it except `task test:nix`. Run `task ci` yourself after + you touch `flake.nix`, `flake.lock`, or `Cargo.toml`, because nothing else builds the Nix + package. This includes a lock-only input refresh. +- `task test:live` calls the real Kagi service. Run it when you change the request path or a + parser: `src/cli.rs`, `src/client.rs`, or `src/parse.rs`. It needs a session token (see + `README.md`) and fails without one. -## Layout +## Rules -- `skills/kagi` is the one skill; it installs as `kagi`. A rename changes all - of these together: +- Keep three separate binaries. Do not add a combined command again. +- Never hardcode a session token. +- A rename of the skill changes all of these together: - `install.sh` and the `install` task in `Taskfile.yml` - `postInstall` and `skillNames` in `flake.nix` - `.github/workflows/release.yml` - - the `name:` front matter in each `skills/*/SKILL.md` - - the documented install paths in `README.md` - -## Decisions - -- Three separate binaries. Do not reintroduce a combined command. -- Never hardcode a session token. The client reads `KAGI_SESSION_TOKEN` (empty - counts as unset), then `$XDG_CONFIG_HOME/kagi/session-token`, falling back to - `~/.config/kagi/session-token`. It refuses a token file that is group- or - world-readable. -- `--sort` means two different things. `kagi-search` sends it to Kagi as the - `order` parameter. `kagi-maps` fetches the whole page, sorts locally, then - truncates to `--limit`. -- `install.sh` is the one installer. `task install` and the release smoke test - run it on local archives. It installs the skill once to - `~/.agents/skills/kagi` and links it into each agent's skill dir. The link - targets are the ones `realpath -m --relative-to` gives between the physical - paths, the same links a dotfiles fan-out from `~/.agents/skills` creates. - Keep them byte-identical, or the installer and the fan-out replace each - other's links on every run. `task install` packs the local build like a - release archive, so it runs only on the two release platforms. -- A version bump is the release trigger: on each push to `main`, `release.yml` - reads `version` from `Cargo.toml`. When the tag `v` does not exist, - it tags and publishes. The tag decides, not the parent commit, so a - multi-commit push or a cancelled run does not lose a release. A tag deleted by - hand comes back on the next push. Recover a failed build or release through - `workflow_dispatch` on `release.yml`. + - the `name:` front matter in `skills/kagi/SKILL.md` + - the install paths in `README.md` +- `--sort` means two things. `kagi-search` sends it to Kagi as the `order` parameter. `kagi-maps` + gets the whole result page, sorts it locally, then cuts it to `--limit`. +- `install.sh` is the one installer. `task install` and the release smoke test run it on local + archives. It installs the skill once to `~/.agents/skills/kagi` and links it into the skill + directory of each agent. Each link target is the path `realpath -m --relative-to` gives between + the physical paths, the same link a dotfiles fan-out from `~/.agents/skills` makes. Keep the two + identical, or the installer and the fan-out replace each other's links on every run. + `task install` packs the local build like a release archive, so it runs only on the two release + platforms. +- A version bump is the release trigger. On each push to `main`, `release.yml` reads `version` + from `Cargo.toml`. When the tag `v` does not exist, it tags and publishes. The tag + decides, not the parent commit, so a push of many commits or a cancelled run does not lose a + release. A tag that someone deletes comes back on the next push. To recover a failed build or + release, run `release.yml` through `workflow_dispatch`. ## Pitfalls -- `flake.nix` repeats the package version as a literal. Bump it in the same - commit as `Cargo.toml`, or `nix build` produces a package with the old - version. -- `install.sh` runs under `sh` on Linux with GNU tools and on macOS with BSD - tools. Use POSIX sh and flags both sets have: no `realpath --relative-to`, no - `ln -T`. -- `ci.yml` skips a pull request whose author is not the repository owner. A - contributor PR shows no checks; that is the gate, not a broken run. +- `flake.nix` repeats the package version as a literal. Bump it in the same commit as + `Cargo.toml`, or `nix build` makes a package with the old version. +- `install.sh` runs under `sh` on Linux with GNU tools and on macOS with BSD tools. Use POSIX sh + and only flags that both sets have: no `realpath --relative-to`, no `ln -T`. +- `ci.yml` skips a pull request whose author is not the repository owner. A contributor PR shows + no checks. That is the gate, not a broken run. diff --git a/README.md b/README.md index 5e24eac..1728685 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # kagi -Unofficial Unix-style CLI tools for [Kagi Search](https://kagi.com). Not affiliated with or endorsed by Kagi Inc. +Unofficial Unix-style command-line tools for [Kagi Search](https://kagi.com). Kagi Inc. does not +make or endorse them. Each binary does one job: @@ -8,9 +9,8 @@ Each binary does one job: - `kagi-maps` finds places and addresses - `kagi-summarize` summarizes one explicit URL -Output is plain text by default and compact JSON with `--json`, so it works well for terminal use and agentic pipelines. - -Requires a Kagi account with an active session token. +Output is plain text by default and compact JSON with `--json`, for scripts and agents. You need a +Kagi account and its session token. ## Install @@ -32,9 +32,8 @@ whose configuration directory exists: | `~/.pi/agent` | `~/.pi/agent/skills/kagi` -> `../../../.agents/skills/kagi` | A link replaces a skill directory that an older installer copied there. When a configuration -directory or its `skills` directory is a symlink, the link target is the relative path between the -resolved directories, the same path `realpath --relative-to` gives. A `skills` directory that links -to `~/.agents/skills` already holds the skill and gets no link. +directory is a symlink, the link is relative between the resolved directories. A `skills` directory +that links to `~/.agents/skills` already holds the skill and gets no link. Run the same command again to update. When `~/.local/bin/kagi-search --version` already shows the target version, the installer says so and changes nothing. @@ -55,8 +54,8 @@ curl -fsSL https://github.com/rubas/kagi/releases/latest/download/install.sh | s Supported platforms: Linux x86_64 and macOS aarch64. When the GitHub CLI (`gh`) is available, the installer verifies the build provenance attestation of -the release archive before it changes a file; without `gh` it warns and continues. For a fully -verifiable install path, prefer the Nix flake below: `flake.lock` pins every input by hash. +the release archive before it changes a file. Without `gh`, it warns and continues. The Nix flake +below is the fully verifiable path: `flake.lock` pins every input by hash. The release also attests `install.sh`. To verify the installer before you run it: @@ -79,17 +78,6 @@ curl -fsSLO https://github.com/rubas/kagi/releases/latest/download/install.sh && cargo install --git https://github.com/rubas/kagi.git ``` -For local development with the required native build tools: - -```bash -nix develop -task check -``` - -`task lint` also runs [zizmor](https://github.com/zizmorcore/zizmor) over the -workflows, and the dev shell does not include it. Install `zizmor` separately or -that step fails. - ### With Nix flakes Install the CLIs directly: @@ -98,7 +86,8 @@ Install the CLIs directly: nix profile install github:rubas/kagi ``` -Or enable the Home Manager module to install the CLIs and companion skills: +Or enable the Home Manager module. It installs the CLIs and puts the `kagi` skill in +`~/.agents/skills`, `~/.claude/skills`, and `~/.gemini/antigravity-cli/skills`: ```nix { @@ -121,11 +110,11 @@ Or enable the Home Manager module to install the CLIs and companion skills: You need a Kagi session token. The binaries check these sources in order: -1. `KAGI_SESSION_TOKEN` environment variable (ignored when empty) -2. `$XDG_CONFIG_HOME/kagi/session-token`, falling back to - `~/.config/kagi/session-token` when `XDG_CONFIG_HOME` is unset, empty, or - relative -3. Fail with an error if neither is set +1. The `KAGI_SESSION_TOKEN` environment variable, when it is not empty. +2. `$XDG_CONFIG_HOME/kagi/session-token`, or `~/.config/kagi/session-token` when `XDG_CONFIG_HOME` + is unset, empty, or relative. + +Without either, they stop with an error. Create the token file with owner-only permissions (paste the token, then Ctrl-D): @@ -135,26 +124,18 @@ install -d -m 700 ~/.config/kagi (umask 077; cat > ~/.config/kagi/session-token) ``` -The token is a full kagi.com session cookie, so the binaries refuse a token -file that is group- or world-readable (`chmod 600` fixes it). The permission -check does not apply to `KAGI_SESSION_TOKEN`. The binaries never embed or -store secrets. +The token is a full kagi.com session cookie, so the binaries refuse a token file that is group- or +world-readable (`chmod 600` fixes it). This check does not apply to `KAGI_SESSION_TOKEN`. The +binaries never embed or store secrets. ## Binaries -### `kagi-search` +Each binary lists all its flags with `--help`. -Search the web with Kagi. - -Usage: - -```bash -kagi-search [OPTIONS] ... -``` - -Run the binary with `--help` for all flags. +### `kagi-search` -Examples: +Searches the web. The text output is numbered results and, when Kagi has them, `Related:` terms. +The JSON is `{ "results": [...], "related": [...] }`. ```bash kagi-search 'rust async runtime' --lens programming --limit 5 @@ -164,17 +145,8 @@ kagi-search 'memory leak' --site github.com --filetype rs --json ### `kagi-maps` -Search Kagi Maps for places, businesses, points of interest, and addresses. - -Usage: - -```bash -kagi-maps [OPTIONS] ... -``` - -Run the binary with `--help` for all flags. - -Examples: +Searches Kagi Maps for places, businesses, and addresses. The text output is numbered places with +the address, coordinates, rating, phone, and URL that Kagi has. The JSON is `{ "results": [...] }`. ```bash kagi-maps 'coffee zurich' --ll 47.3769,8.5417 --zoom 13 @@ -183,17 +155,8 @@ kagi-maps 'bookstore near bern' --sort rating --json ### `kagi-summarize` -Summarize one explicit URL with Kagi. - -Usage: - -```bash -kagi-summarize [OPTIONS] -``` - -Run the binary with `--help` for all flags. - -Examples: +Summarizes one explicit URL. The text output is the raw Markdown summary. The JSON is +`{ "summary": "..." }`. ```bash kagi-summarize 'https://www.rust-lang.org/learn' @@ -201,28 +164,20 @@ kagi-summarize 'https://www.rust-lang.org/learn' --type takeaway kagi-summarize 'https://www.rust-lang.org/learn' --lang DE --json ``` -## Output +## Agent skill -`kagi-search` returns: +[`skills/kagi/SKILL.md`](skills/kagi/SKILL.md) teaches Claude Code and other agents when and how to +use the three binaries. The installer and the Home Manager module install it. -- text: numbered results plus optional `Related:` terms -- json: `{ "results": [...], "related": [...] }` +## Development -`kagi-maps` returns: - -- text: numbered places with address, coordinates, rating, phone, and URL when present -- json: `{ "results": [...] }` - -`kagi-summarize` returns: - -- text: raw markdown summary -- json: `{ "summary": "..." }` - -## Skills - -This repo ships one companion skill for Claude Code and other agents: +```bash +nix develop +task check +``` -- [`skills/kagi/SKILL.md`](skills/kagi/SKILL.md): one skill covering search, maps, and summarize +`task lint` also runs [zizmor](https://github.com/zizmorcore/zizmor) over the workflows. The dev +shell does not include it, so install `zizmor` yourself or that step fails. ## License From 1f935582e857ce7316f44806b484a933154bafd8 Mon Sep 17 00:00:00 2001 From: Dominic Rubas <1042243+rubas@users.noreply.github.com> Date: Sat, 26 Sep 2026 23:27:34 +0200 Subject: [PATCH 2/2] AGENTS.md: keep the zizmor gate note --- AGENTS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index d150ced..152b71a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -9,6 +9,8 @@ covers install, the token, and usage. cargo-deny. GitHub Actions runs all of it except `task test:nix`. Run `task ci` yourself after you touch `flake.nix`, `flake.lock`, or `Cargo.toml`, because nothing else builds the Nix package. This includes a lock-only input refresh. +- `task lint`, and with it `task check` and `task ci`, runs `zizmor`. The `nix develop` shell does + not include it, so put `zizmor` on `PATH` first. - `task test:live` calls the real Kagi service. Run it when you change the request path or a parser: `src/cli.rs`, `src/client.rs`, or `src/parse.rs`. It needs a session token (see `README.md`) and fails without one.