mirror of
https://github.com/harivansh-afk/deskctl.git
synced 2026-04-18 23:02:15 +00:00
Improve docs structure and navigation
Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
parent
844f2f2bc6
commit
84dae7ce87
8 changed files with 210 additions and 41 deletions
|
|
@ -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">
|
||||||
|
|
|
||||||
|
|
@ -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`.
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 -> wait
|
||||||
|
-> act -> 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>
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue