# dsh-emoji

English | [简体中文](README.md)

Add switchable, customizable inline emoji to DeepSeek Harness responses.

![dsh-emoji whale emoji pack](assets/readme/banner.en.png)

## Preview

![Inline whale emoji in a DSH conversation](assets/readme/chat-preview.en.png)

## Installation

Add the plugin to the Web Profile with the DSH CLI, then restart the Web Host:

```sh
dsh plugin --profile web add dsh-emoji
```

To try a prerelease, replace the package name in the installation command with `dsh-emoji@beta`. A plain `npm install dsh-emoji` only adds the package to the current Node.js project; it does not enable the DSH plugin.

## How it works

- When the AI wants an emotional or decorative reaction, it chooses directly from 42 allowed Unicode emoji, such as `😊`. They resolve to 40 stable semantic keys, and the Host converts the chosen character into an inline image from the active emoji pack without another model call.
- Built-in and uploaded packs share 40 stable semantic keys, can be switched at any time, and support four display sizes.
- Rewriting applies only to the 40 canonical Unicode emoji, the common aliases `😄` and `🙂`, and this plugin's images. Other Unicode emoji, code, links, double-colon text, and ordinary Markdown images are left unchanged. The program never guesses the reply's emotion or inserts a fallback image. Reply text must separate multiple plugin emoji, while the same emoji may repeat later.

## Adjusting emoji frequency

After installation and a Web Host restart, open **Plugins → dsh-emoji** in the sidebar:

- **Off**: do not use emoji.
- **Smart**: use emoji only when it meaningfully helps express emotion, up to 3 per turn. This is the default.
- **Frequent**: include one fitting custom emoji in every conversational reply and place it after the sentence or short paragraph whose emotion it best matches, up to 4 per turn.

You can also choose an emoji pack, adjust its display size, or use **Additional prompt** to control emoji selection, tone, and usage. Changes apply to the next reply without a restart. The model is responsible for following the selected frequency policy.

## Uploading your own emoji pack

Click **Upload ZIP** in the same settings card. After upload, select the pack and save; the next model call uses it without a Host restart. A custom pack implements the same 40 stable semantic keys as the built-in pack. The AI keeps using the same allowed Unicode emoji while the Host changes only the image.

The ZIP may contain these files directly or inside one top-level directory:

```text
my-whale.zip
├── pack.json
└── images/
    ├── happy.png
    ├── sad.png
    ├── thinking.png
    ├── celebrate.png
    └── ...the remaining canonical keys
```

`pack.json`:

```json
{
  "schemaVersion": 1,
  "keySet": "dsh-emoji-core@1",
  "id": "my-whale",
  "name": "My Whale Emoji",
  "version": "1.0.0"
}
```

`schemaVersion` identifies the technical ZIP format, while `keySet` identifies the semantic set implemented by the images. Uploaded packs must currently declare `dsh-emoji-core@1`. See the [core semantic contract](EMOJI_KEYS.md) for the normative meaning, visual guidance, and boundaries of every key.

The 40 filename keys are:

```text
happy, sad, confused, watching, angry, speechless, doge, overloaded,
neutral, laughing, crying, sweating, thinking, okay, nodding, sleeping,
hurt, peeking, approve, heart, shy, star-eyes, laugh-cry, touched,
scared, facepalm, eye-roll, sigh, frustrated, playful, snickering,
sarcastic, cool, celebrate, cheer, thanks, sorry, hug, please, applause
```

Each key must have exactly one matching `.png`. IDs use lowercase letters, digits, and hyphens; versions use SemVer. Content at one `id@version` is immutable, so changed assets require a new version. Limits are 20 MiB per ZIP, 80 MiB expanded, 2 MiB per file, and 512 pixels per image dimension. Path traversal, extra files, missing keys, unknown `keySet` values, spoofed formats, and conflicting content are rejected.

User packs live under `$DSH_HOME/emoji-packs/` (default `~/.dsh/emoji-packs/`), while Settings stores only the active `id@version`. **Remove** hides a pack from the selector but intentionally retains its immutable bytes for historical messages. Uploading the exact same ZIP restores that version.

## Compatibility

Supports DSH versions admitted by `^0.1.7-rc.2 || ^0.2.0-rc.2`, with Node.js `^22.19.0 || >=24`. Development pins the exact DSH `0.2.0-rc.2` type graph; the Web Profile supplies the shared runtime. Full runtime acceptance status is recorded in `package.json` under `dsh.compatibility.dshReleases`. Settings persist in the active Profile's `cordis.patch.yml`; image packs live in DSH Home.

## Local development

Requires Node.js `^22.19.0 || >=24` and pnpm 11.

```sh
corepack pnpm install
corepack pnpm typecheck
corepack pnpm test
corepack pnpm build
npm pack --dry-run
```

## Links

Available on the [dshfind.com](https://dshfind.com) DSH plugin marketplace.
