# @zoytown/dsh-avatar

English | [中文](README.zh.md)

Wallpaper theming for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (dsh):
upload images from the Settings page, pick one, and the whole dsh web UI renders over it —
with an adjustable readability veil, background blur, and fill mode.

- **Upload in the UI** — click or drag & drop (png / jpg / webp / gif, 20 MB per image by default);
  files land in `~/.dsh/avatar/v1/` under content-addressed names
- **Gallery** — thumbnails of everything you uploaded; click to apply, hover to delete,
  pick **None** to go back to the plain theme
- **Readability controls** — a veil slider (the UI surfaces stay translucent over the image),
  a blur slider, and fill / fit / tile modes; changes preview live and persist automatically
- **Scheme-aware** — the veil re-tints itself from the active light/dark palette; one image serves both

## Install

```bash
dsh plugin --profile web add @zoytown/dsh-avatar
```

Then open **Settings → Background** in the dsh web UI. Remove with
`dsh plugin --profile web remove @zoytown/dsh-avatar` — the UI reverts fully; uploaded images stay
in `~/.dsh/avatar/` until you delete that directory.

## Configuration

Row config (override by id `dsh-avatar` in your `cordis.patch.yml`; restate every field):

| Field | Default | Meaning |
|---|---|---|
| `maxImageBytes` | `20971520` | Per-image upload cap in bytes |
| `trustedHosts` | `[]` | Non-loopback authorities allowed to **fetch image bytes** (`host` or `host:port`). Uploads and preferences stay loopback-only regardless, because the harness pins its settings API to loopback. |
| `dshHome` | *(unset)* | Override the dsh home the wallpaper directory lives under |

User preferences (active wallpaper, veil opacity, blur, fill) live in the `avatar` section of
`~/.dsh/settings.yaml`.

## Scope and limitations

- **dsh web only.** The Electron form has no HTTP server, so the image route this plugin relies on
  does not exist there.
- **Remote (non-loopback) browsers are read-only.** The harness rejects settings reads/writes from
  non-loopback origins, so the Background page disables itself with a note, and the wallpaper is
  not applied there.
- **No data leaves your machine.** This plugin makes no external requests and reports nothing.
- Sticky headers and small chips become slightly translucent while a wallpaper is active — that is
  the veil working; raise the veil slider if anything is hard to read.

## Development

```bash
pnpm install   # use pnpm — npm currently crashes on this dependency graph
pnpm run typecheck && pnpm run test && pnpm run build && pnpm run test
```

Architecture decisions and their upstream evidence: [DESIGN.md](./DESIGN.md).

## License

MIT
