henning 844d2e716f Add outline-cli: minimal CLI for search and document retrieval
Adds a command-line client in cli/ as its own Cargo workspace, depending
on the outline library via a path dependency. Covers exactly the requested
scope: login (stores the API key in the system keyring via the Secret
Service D-Bus protocol, verified against auth.info() before storing),
search (full-text), and get (fetch a document, render its markdown to a
self-contained HTML page, open it in the default browser).

Verified end-to-end against a real Outline instance and the local
gnome-keyring: login stores and search/get retrieve the token purely from
the keyring and saved config, with no environment variables set.
2026-07-30 15:15:56 +02:00

outline

An async Rust client library for the Outline knowledge base API.

This crate is the foundation for building Outline clients (CLI, GUI, ...) on top of a shared, well-tested API layer. It only talks to the API — no CLI or GUI code lives here.

Quickstart

use outline::Client;

# async fn run() -> outline::Result<()> {
let client = Client::new("ol_api_...")?;

let me = client.auth().info().await?;
println!("Signed in as {} ({})", me.user.name, me.team.name);

let mut documents = client.documents().list().collection_id("col_123").paginate();
while let Some(page) = documents.next_page().await? {
    for document in page.items {
        println!("{}", document.title);
    }
}
# Ok(())
# }

For a self-hosted instance or an OAuth access token, use [Client::builder]:

use std::time::Duration;
use outline::Client;

# fn run() -> outline::Result<()> {
let client = Client::builder()
    .base_url("https://wiki.example.com")
    .access_token("...")
    .timeout(Duration::from_secs(10))
    .build()?;
# let _ = client;
# Ok(())
# }

Design notes

The Outline API is RPC-style: every endpoint is POST /api/<resource>.<action> with a JSON body and a {ok, data, pagination, policies} envelope. This crate mirrors that with a single internal request primitive; resources are exposed as scoped accessors (client.documents(), client.collections(), ...).

Because the API is unversioned and self-hosted instances vary in age, models are deliberately forward-compatible: unknown fields are ignored and unknown string-enum values are preserved rather than causing deserialization to fail.

Status

This crate currently covers a first vertical slice of the API — auth, documents, collections, users — chosen to validate the request/response patterns (single object, paginated list, tree, create/update, delete, search) used across the rest of the API. Broader endpoint coverage, automatic retry on rate limiting, and streaming exports are planned but not yet implemented.

License

MIT OR Apache-2.0

S
Description
Outline client library and CLI
Readme
146 KiB
Languages
Rust 98.9%
CSS 1.1%