diff --git a/README.md b/README.md
index 4b42b5f..f2e746f 100644
--- a/README.md
+++ b/README.md
@@ -27,10 +27,13 @@ npx deskctl --help
## Installable skill
```bash
-npx skills add harivansh-afk/deskctl -s deskctl
+npx skills add harivansh-afk/deskctl --skill deskctl -g
```
-The installable skill lives in [`skills/deskctl`](skills/deskctl) and is built around the same observe -> wait -> act -> verify loop as the CLI.
+The installable skill lives in [`skills/deskctl`](skills/deskctl), follows the
+standard `skills/` repo layout, and installs directly from this GitHub repo via
+`npx skills add ...`. It is built around the same observe -> wait -> act ->
+verify loop as the CLI.
## Quick example
diff --git a/site/src/pages/index.astro b/site/src/pages/index.astro
index 8b8d4b4..e97b599 100644
--- a/site/src/pages/index.astro
+++ b/site/src/pages/index.astro
@@ -38,7 +38,7 @@ import DocLayout from "../layouts/DocLayout.astro";
There is also an installable skill for `skills.sh`-style agent runtimes:
- npx skills add harivansh-afk/deskctl -s deskctl
+ npx skills add harivansh-afk/deskctl --skill deskctl -g
Links
diff --git a/site/src/pages/installation.mdx b/site/src/pages/installation.mdx
index df53fcc..7754e6b 100644
--- a/site/src/pages/installation.mdx
+++ b/site/src/pages/installation.mdx
@@ -27,11 +27,13 @@ npx deskctl --help
For `skills.sh`-style runtimes:
```sh
-npx skills add harivansh-afk/deskctl -s deskctl
+npx skills add harivansh-afk/deskctl --skill deskctl -g
```
-The repo skill lives under `skills/deskctl` and is designed around the same
-observe -> wait -> act -> verify loop as the CLI.
+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.
## Other install paths
diff --git a/skills/deskctl/agents/openai.yaml b/skills/deskctl/agents/openai.yaml
new file mode 100644
index 0000000..8a5ca13
--- /dev/null
+++ b/skills/deskctl/agents/openai.yaml
@@ -0,0 +1,7 @@
+interface:
+ display_name: "deskctl"
+ short_description: "Control Linux X11 desktops from agent loops"
+ default_prompt: "Use $deskctl to diagnose the desktop, observe state, wait for UI changes, act deterministically, and verify the result."
+
+policy:
+ allow_implicit_invocation: true
diff --git a/skills/deskctl/references/runtime-contract.md b/skills/deskctl/references/runtime-contract.md
deleted file mode 120000
index 8de0781..0000000
--- a/skills/deskctl/references/runtime-contract.md
+++ /dev/null
@@ -1 +0,0 @@
-../../../docs/runtime-contract.md
\ No newline at end of file
diff --git a/skills/deskctl/references/runtime-contract.md b/skills/deskctl/references/runtime-contract.md
new file mode 100644
index 0000000..6efd2bc
--- /dev/null
+++ b/skills/deskctl/references/runtime-contract.md
@@ -0,0 +1,73 @@
+# deskctl runtime contract
+
+This copy ships inside the installable skill so `npx skills add ...` installs a
+self-contained reference bundle.
+
+All commands support `--json` and use the same top-level envelope:
+
+```json
+{
+ "success": true,
+ "data": {},
+ "error": null
+}
+```
+
+Use `--json` whenever you need to parse output programmatically.
+
+## Stable window fields
+
+Whenever a response includes a window payload, these fields are stable:
+
+- `ref_id`
+- `window_id`
+- `title`
+- `app_name`
+- `x`
+- `y`
+- `width`
+- `height`
+- `focused`
+- `minimized`
+
+Use `window_id` for stable targeting inside a live daemon session. Use
+`ref_id` or `@wN` for short-lived follow-up actions after `snapshot` or
+`list-windows`.
+
+## Stable grouped reads
+
+- `deskctl get active-window` -> `data.window`
+- `deskctl get monitors` -> `data.count`, `data.monitors`
+- `deskctl get version` -> `data.version`, `data.backend`
+- `deskctl get systeminfo` -> runtime-scoped diagnostic fields such as
+ `backend`, `display`, `session_type`, `session`, `socket_path`, `screen`,
+ `monitor_count`, and `monitors`
+
+## Stable waits
+
+- `deskctl wait window` -> `data.wait`, `data.selector`, `data.elapsed_ms`,
+ `data.window`
+- `deskctl wait focus` -> `data.wait`, `data.selector`, `data.elapsed_ms`,
+ `data.window`
+
+## Stable structured error kinds
+
+When a command fails with structured JSON data, these `kind` values are stable:
+
+- `selector_not_found`
+- `selector_ambiguous`
+- `selector_invalid`
+- `timeout`
+- `not_found`
+
+Wait failures may also include `window_not_focused` in the last observation
+payload.
+
+## Best-effort fields
+
+Treat these as useful but non-contractual:
+
+- exact monitor names
+- incidental text formatting in non-JSON mode
+- default screenshot file names when no explicit path was provided
+- environment-dependent ordering details from the window manager