BareGit
# Doctor Boring

Doctor Boring is a playful, LLM-backed relative of Emacs's classic
`M-x doctor`. It gives you the same simple conversation-buffer experience,
but sends each turn to an OpenAI-compatible Chat Completions API.

It is meant as a fun side activity, not as a medical tool or serious
assistant.

## Requirements

- GNU Emacs 30.2 or newer
- An OpenAI-compatible Chat Completions endpoint
- Optionally, `markdown-mode` for response fontification

Doctor Boring does not require third-party packages or external executables.
When `markdown-mode` is unavailable, it uses `text-mode` automatically.

## Installation

Install the package file directly with:

```text
M-x package-install-file RET /path/to/doctor-boring.el RET
```

For development or a manual installation, add the repository to your load
path:

```elisp
(add-to-list 'load-path "/path/to/emacs-doctor")
(require 'doctor-boring)
```

## Configuration

Run:

```text
M-x customize-group RET doctor-boring RET
```

At minimum, set `doctor-boring-endpoint`. It is the base URL ending at the
API version, not the complete Chat Completions URL. Doctor Boring appends
`/chat/completions` itself.

For example:

```elisp
(setq doctor-boring-endpoint "https://api.example.com/v1"
      doctor-boring-api-key "your-api-key"
      doctor-boring-model "your-model")
```

The available options are:

| Option | Default | Purpose |
| --- | --- | --- |
| `doctor-boring-endpoint` | `""` | Base URL for the API |
| `doctor-boring-api-key` | `""` | Optional bearer token |
| `doctor-boring-model` | `""` | Model sent in each request |
| `doctor-boring-temperature` | `1.0` | Sampling temperature |
| `doctor-boring-system-prompt` | Built in | Conversation personality |
| `doctor-boring-greeting` | Built in | Initial visible greeting |
| `doctor-boring-request-timeout` | `300` | Request timeout in seconds |

An empty API key omits the `Authorization` header. An empty model is allowed
for compatible local servers that ignore it. The endpoint cannot be empty
when submitting a message.

Be aware that saving the API key through Customize writes it to your Emacs
customization file.

## Usage

Start or return to the conversation with:

```text
M-x doctor-boring
```

Type at the bottom of the `*doctor-boring*` buffer, then either:

- Press `RET` twice to submit.
- Or press `C-j` once to submit.

Whitespace-only messages are ignored. While a request is running, the
conversation buffer is read-only and another message cannot be queued.

The default personality uses subtle, classic ELIZA-style reflection. It
briefly mirrors the user's wording and is instructed to end every response
with a natural question.

### Editing the conversation

Previous user and assistant messages remain editable. Doctor Boring rebuilds
the complete history from the visible message text before every request, so
an edit affects the next response.

The initial greeting is only part of the presentation. It is not sent to the
API, even if you edit it.

To begin a new conversation, kill the `*doctor-boring*` buffer and run
`M-x doctor-boring` again. Invoking the command while the buffer exists
returns to the same conversation without resetting it.

## Errors and retries

Network, timeout, HTTP, and malformed-response failures display a short local
error above the message that failed. The original input is restored at the
bottom of the buffer so you can edit it or submit it again.

Local errors are never included in the API conversation history. More
detailed diagnostics are written to the `*Messages*` buffer, and the API key
is redacted.

## Privacy

Every submitted conversation turn sends the current recorded conversation
and system prompt to the configured endpoint. Doctor Boring does not persist
the conversation separately from its Emacs buffer and disables URL-library
cookies for API requests.

## Development

Run the test suite without contacting a real API:

```sh
emacs -Q --batch -L . -l doctor-boring-test.el \
    -f ert-run-tests-batch-and-exit
```

Run the static checks with:

```sh
emacs -Q --batch -L . \
    --eval '(byte-compile-file "doctor-boring.el")'

emacs -Q --batch -L . -l doctor-boring.el \
    --eval '(checkdoc-file "doctor-boring.el")'
```

## License

Doctor Boring is released under the WTFPL.