Improve docs structure and navigation

Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
Harivansh Rathi 2026-03-26 09:46:01 -04:00
parent 844f2f2bc6
commit 84dae7ce87
8 changed files with 210 additions and 41 deletions

View file

@ -9,6 +9,23 @@ const headings: MarkdownHeading[] = Astro.props.headings ?? [];
const isIndex = const isIndex =
Astro.url.pathname === "/" || Astro.url.pathname === "/index.html"; Astro.url.pathname === "/" || Astro.url.pathname === "/index.html";
const h2s = headings.filter((h) => h.depth === 2); const h2s = headings.filter((h) => h.depth === 2);
const docsSections = [
{
title: "Start",
items: [
{ href: "/installation", label: "Installation" },
{ href: "/quick-start", label: "Quick start" },
],
},
{
title: "Reference",
items: [
{ href: "/commands", label: "Commands" },
{ href: "/architecture", label: "Architecture" },
{ href: "/runtime-contract", label: "Runtime contract" },
],
},
];
function formatTocText(text: string): string { function formatTocText(text: string): string {
if (!text.includes(" ") && /[-.]/.test(text)) { if (!text.includes(" ") && /[-.]/.test(text)) {
@ -30,7 +47,7 @@ function formatTocText(text: string): string {
<body> <body>
{ {
!isIndex && ( !isIndex && (
<nav> <nav class="breadcrumbs">
<a class="title" href="/"> <a class="title" href="/">
deskctl deskctl
</a> </a>
@ -40,6 +57,31 @@ function formatTocText(text: string): string {
) )
} }
{
!isIndex && (
<div class="docs-nav">
{docsSections.map((section) => (
<div class="docs-nav-section">
<span class="docs-nav-title">{section.title}</span>
<div class="docs-nav-links">
{section.items.map((item) => (
<a
href={item.href}
class:list={[
"docs-nav-link",
{ active: Astro.url.pathname === item.href },
]}
>
{item.label}
</a>
))}
</div>
</div>
))}
</div>
)
}
{ {
toc && ( toc && (
<aside class="toc-nav"> <aside class="toc-nav">

View file

@ -6,9 +6,12 @@ toc: true
# Architecture # Architecture
`deskctl` is not trying to be a desktop environment abstraction layer. The
design goal is a small, unsurprising Linux X11 control primitive that agents
can discover and compose progressively.
## Public model ## Public model
`deskctl` is a thin, non-interactive X11 control primitive for agent loops.
The public flow is: The public flow is:
- diagnose with `deskctl doctor` - diagnose with `deskctl doctor`
@ -20,7 +23,7 @@ The public flow is:
The tool stays intentionally narrow. It does not try to be a full desktop shell The tool stays intentionally narrow. It does not try to be a full desktop shell
or a speculative Wayland abstraction. or a speculative Wayland abstraction.
## Client-daemon architecture ## Client and daemon
The CLI talks to an auto-managed daemon over a Unix socket. The daemon keeps The CLI talks to an auto-managed daemon over a Unix socket. The daemon keeps
the X11 connection alive so repeated commands stay fast and share the same the X11 connection alive so repeated commands stay fast and share the same
@ -76,7 +79,7 @@ main public knob when you need isolated daemon instances.
Selector and wait failures are structured in `--json` mode so clients can Selector and wait failures are structured in `--json` mode so clients can
recover without scraping text. recover without scraping text.
## Backend notes ## Backend boundary
The backend is built around a `DesktopBackend` trait and currently ships with The backend is built around a `DesktopBackend` trait and currently ships with
an X11 implementation backed by `x11rb`. an X11 implementation backed by `x11rb`.

View file

@ -6,7 +6,10 @@ toc: true
# Commands # Commands
## Observe The public CLI is intentionally small. Most workflows boil down to grouped
reads, grouped waits, selector-driven actions, and a few input primitives.
## Observe and inspect
```sh ```sh
deskctl doctor deskctl doctor
@ -25,9 +28,10 @@ deskctl get-mouse-position
`doctor` checks the runtime before daemon startup. `snapshot` produces a `doctor` checks the runtime before daemon startup. `snapshot` produces a
screenshot plus window refs. `list-windows` is the same window tree without the screenshot plus window refs. `list-windows` is the same window tree without the
side effect of writing a screenshot. side effect of writing a screenshot. The grouped `get` commands are the
preferred read surface for focused state queries.
## Wait ## Wait for state transitions
```sh ```sh
deskctl wait window --selector 'title=Firefox' --timeout 10 deskctl wait window --selector 'title=Firefox' --timeout 10
@ -38,7 +42,7 @@ deskctl --json wait window --selector 'class=firefox' --poll-ms 100
Wait commands return the matched window payload on success. In `--json` mode, Wait commands return the matched window payload on success. In `--json` mode,
timeouts and selector failures expose structured `kind` values. timeouts and selector failures expose structured `kind` values.
## Act on a window ## Act on windows
```sh ```sh
deskctl launch firefox deskctl launch firefox
@ -55,7 +59,7 @@ deskctl resize-window @w1 1280 720
Selector-driven actions accept refs, explicit selector modes, or absolute Selector-driven actions accept refs, explicit selector modes, or absolute
coordinates where appropriate. coordinates where appropriate.
## Input and mouse ## Keyboard and mouse input
```sh ```sh
deskctl type "hello world" deskctl type "hello world"
@ -71,16 +75,10 @@ Supported key names include `enter`, `tab`, `escape`, `backspace`, `delete`,
`space`, arrow keys, paging keys, `f1` through `f12`, and any single `space`, arrow keys, paging keys, `f1` through `f12`, and any single
character. character.
## Launch
```sh
deskctl launch firefox
deskctl launch code -- --new-window
```
## Selectors ## Selectors
Prefer explicit selectors when the target matters: Prefer explicit selectors when the target matters. They are clearer in logs,
more deterministic for automation, and easier to retry safely.
```sh ```sh
ref=w1 ref=w1

View file

@ -16,23 +16,57 @@ import DocLayout from "../layouts/DocLayout.astro";
then verify. then verify.
</p> </p>
<h2>Start here</h2> <pre><code>{`npm install -g deskctl
deskctl doctor
deskctl snapshot --annotate`}</code></pre>
<h2>Start</h2>
<p>
Install the CLI, verify the runtime, then run the core observe -&gt; wait
-&gt; act -&gt; verify loop.
</p>
<ul> <ul>
<li><a href="/installation">Installation</a></li> <li>
<li><a href="/quick-start">Quick start</a></li> <a href="/installation">Installation</a> - install paths, runtime requirements,
and first-run checks
</li>
<li>
<a href="/quick-start">Quick start</a> - the minimal workflow for real desktop
control
</li>
</ul> </ul>
<h2>Reference</h2> <h2>Reference</h2>
<p>
Read the command surface, the daemon/runtime model, and the stable JSON
contract.
</p>
<ul> <ul>
<li><a href="/commands">Commands</a></li> <li>
<li><a href="/architecture">Architecture</a></li> <a href="/commands">Commands</a> - grouped reads, waits, actions, selectors,
<li><a href="/runtime-contract">Runtime contract</a></li> and global flags
</li>
<li>
<a href="/architecture">Architecture</a> - client/daemon model, sessions, sockets,
and support boundary
</li>
<li>
<a href="/runtime-contract">Runtime contract</a> - stable JSON fields, errors,
and best-effort text behavior
</li>
</ul> </ul>
<h2>Links</h2> <h2>Links</h2>
<p>
The repo is the source of truth for the CLI, the skill, and the release
assets.
</p>
<ul> <ul>
<li> <li>
<a href="https://github.com/harivansh-afk/deskctl">GitHub</a> <a href="https://github.com/harivansh-afk/deskctl">GitHub</a>

View file

@ -6,19 +6,38 @@ toc: true
# Installation # Installation
## Default install Install the public `deskctl` command first, then validate the desktop runtime
with `deskctl doctor` before trying to automate anything.
## Recommended path
```sh ```sh
npm install -g deskctl npm install -g deskctl
deskctl doctor
``` ```
`deskctl` is the default install path. It installs the command by `deskctl` is the default install path. It installs the command by
downloading the matching GitHub Release asset for the supported runtime target. downloading the matching GitHub Release asset for the supported runtime target.
The repo skill lives under `skills/deskctl`, so `skills` can install it This path does not require a Rust toolchain. The installed command is always
directly from this GitHub repo. It is designed around the same observe -> wait `deskctl`, even though the release asset itself is target-specific.
-> act -> verify loop as the CLI. `-g` installs it globally; omit that flag if
you want a project-local install. ## Quick try without a global install
```sh
npx deskctl --help
```
This is useful when you only need a temporary run or want to smoke-test a
machine before deciding how to install it permanently.
## What the npm install does
- downloads the matching GitHub Release asset for the current supported target
- exposes the public command as `deskctl`
- keeps the install path operator-friendly: no source build, no manual rename
Today the npm distribution is aimed at Linux x64 X11 environments.
## Other install paths ## Other install paths
@ -43,6 +62,17 @@ Source builds on Linux require:
- `pkg-config` - `pkg-config`
- X11 development libraries such as `libx11-dev` and `libxtst-dev` - X11 development libraries such as `libx11-dev` and `libxtst-dev`
## Skill install
The repo skill lives under `skills/deskctl`, so `skills` can install it
directly from this GitHub repo. It is designed around the same observe -> wait
-> act -> verify loop as the CLI. `-g` installs it globally; omit that flag if
you want a project-local install.
```sh
npx skills add harivansh-afk/deskctl -s deskctl
```
## Runtime requirements ## Runtime requirements
- Linux with an active X11 session - Linux with an active X11 session
@ -53,8 +83,13 @@ Source builds on Linux require:
The binary itself only depends on the standard Linux glibc runtime. The binary itself only depends on the standard Linux glibc runtime.
If setup fails, run: ## First troubleshooting step
If setup fails, start here:
```sh ```sh
deskctl doctor deskctl doctor
``` ```
`doctor` checks X11 connectivity, window enumeration, screenshot viability, and
daemon/socket health before normal command execution.

View file

@ -6,7 +6,10 @@ toc: true
# Quick start # Quick start
## Install and diagnose The fastest way to use `deskctl` is to follow the same four-step loop every
time: observe, wait, act, verify.
## 1. Install and diagnose
```sh ```sh
npm install -g deskctl npm install -g deskctl
@ -16,7 +19,7 @@ deskctl doctor
Use `deskctl doctor` first. It checks X11 connectivity, basic enumeration, Use `deskctl doctor` first. It checks X11 connectivity, basic enumeration,
screenshot viability, and socket health before you start driving the desktop. screenshot viability, and socket health before you start driving the desktop.
## Observe ## 2. Observe the desktop
```sh ```sh
deskctl snapshot --annotate deskctl snapshot --annotate
@ -29,7 +32,7 @@ Use `snapshot` when you want a screenshot artifact plus window refs. Use
`list-windows` when you only need the current window tree without writing a `list-windows` when you only need the current window tree without writing a
screenshot. screenshot.
## Target windows cleanly ## 3. Pick selectors that stay readable
Prefer explicit selectors when you need deterministic targeting: Prefer explicit selectors when you need deterministic targeting:
@ -44,7 +47,7 @@ focused
Legacy refs such as `@w1` still work after `snapshot` or `list-windows`. Bare Legacy refs such as `@w1` still work after `snapshot` or `list-windows`. Bare
strings like `firefox` are fuzzy matches and now fail on ambiguity. strings like `firefox` are fuzzy matches and now fail on ambiguity.
## Wait, act, verify ## 4. Wait, act, verify
The core loop is: The core loop is:
@ -69,7 +72,7 @@ deskctl snapshot
The wait commands return the matched window payload on success, so they compose The wait commands return the matched window payload on success, so they compose
cleanly into the next action. cleanly into the next action.
## Use `--json` when parsing matters ## 5. Use `--json` when parsing matters
Every command supports `--json` and uses the same top-level envelope: Every command supports `--json` and uses the same top-level envelope:

View file

@ -11,7 +11,7 @@ This page defines the current public output contract for `deskctl`.
It is intentionally scoped to the current Linux X11 runtime surface. It does It is intentionally scoped to the current Linux X11 runtime surface. It does
not promise stability for future Wayland or window-manager-specific features. not promise stability for future Wayland or window-manager-specific features.
## JSON envelope ## Stable top-level envelope
Every command supports `--json` and uses the same top-level envelope: Every command supports `--json` and uses the same top-level envelope:
@ -32,7 +32,7 @@ Stable top-level fields:
If `success` is `false`, the command exits non-zero in both text mode and JSON If `success` is `false`, the command exits non-zero in both text mode and JSON
mode. mode.
## Stable window fields ## Stable window payload
Whenever a response includes a window payload, these fields are stable: Whenever a response includes a window payload, these fields are stable:

View file

@ -224,34 +224,88 @@ hr {
} }
} }
nav { .breadcrumbs {
max-width: 50rem; max-width: 50rem;
margin: 0 auto; margin: 0 auto;
padding: 1.5rem clamp(1.25rem, 5vw, 3rem) 0; padding: 1.5rem clamp(1.25rem, 5vw, 3rem) 0;
font-size: 0.9rem; font-size: 0.9rem;
} }
nav a { .breadcrumbs a {
color: inherit; color: inherit;
text-decoration: none; text-decoration: none;
opacity: 0.6; opacity: 0.6;
transition: opacity 0.15s; transition: opacity 0.15s;
} }
nav a:hover { .breadcrumbs a:hover {
opacity: 1; opacity: 1;
} }
nav .title { .breadcrumbs .title {
font-weight: 500; font-weight: 500;
opacity: 1; opacity: 1;
} }
nav .sep { .breadcrumbs .sep {
opacity: 0.3; opacity: 0.3;
margin: 0 0.5em; margin: 0 0.5em;
} }
.docs-nav {
max-width: 50rem;
margin: 0 auto;
padding: 1rem clamp(1.25rem, 5vw, 3rem) 0;
display: flex;
flex-wrap: wrap;
gap: 1rem 1.5rem;
font-size: 0.92rem;
}
.docs-nav-section {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.5rem 0.75rem;
}
.docs-nav-title {
opacity: 0.45;
font-size: 0.82rem;
text-transform: uppercase;
letter-spacing: 0.06em;
}
.docs-nav-links {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.docs-nav-link {
color: inherit;
text-decoration: none;
padding: 0.2rem 0.5rem;
border-radius: 999px;
opacity: 0.68;
transition:
opacity 0.15s,
background 0.15s;
}
.docs-nav-link:hover,
.docs-nav-link.active {
opacity: 1;
background: #ebebeb;
}
@media (prefers-color-scheme: dark) {
.docs-nav-link:hover,
.docs-nav-link.active {
background: #222222;
}
}
.toc-nav { .toc-nav {
position: fixed; position: fixed;
top: 6.5rem; top: 6.5rem;