# Show HN: I built a Neovim plugin to answer questions about your config

> Source: <https://github.com/michtesar/how.nvim>
> Published: 2026-08-03 22:19:23+00:00

Ask the Neovim you are actually running.

`how.nvim`

is a small, keyboard-first configuration assistant backed by the
official Codex CLI. It inspects effective mappings, loaded plugins, your config
files, operating system, and detected distribution before answering.

```
:How how do I move between buffers?
```

No API key is required when Codex is signed in with an eligible ChatGPT plan.
The plugin does not read or store credentials; it talks to `codex app-server`

over local stdio.

- Native Neovim buffers, splits, motions, search, yanks, and marks.
- No UI dependencies and no embedded browser.
- Short answers based on active runtime state rather than remembered defaults.
- Read-only by default, enforced by the Codex sandbox.
- A config change requires a detected proposal,
`a`

, and an explicit confirmation. - Writes are scoped to
`stdpath("config")`

. Commands require another approval.

- Neovim 0.10+
[Codex CLI](https://github.com/openai/codex)`codex login`

completed with ChatGPT or an OpenAI API key

Run `:checkhealth how`

after installation.

During local development with lazy.nvim:

```
{
  dir = vim.fn.expand("~/Developer/how.nvim"),
  name = "how.nvim",
  cmd = { "How", "HowAsk", "HowToggle", "HowApply" },
  keys = {
    { "<leader>ah", "<cmd>How<cr>", desc = "Ask How" },
  },
  opts = {},
}
```

After the repository is published, replace `dir`

with its GitHub `owner/repo`

.

```
:How                         " open the prompt
:How why does K open hover?  " ask directly
:HowToggle                   " toggle the panel
:HowApply                    " confirm the last concrete proposal
:HowStop                     " stop streaming
:HowReset                    " new conversation
```

Inside the panel:

| Key | Action |
|---|---|
`i` |
Ask a question |
`a` |
Apply the last proposal |
`R` |
Start a new conversation |
`<C-c>` |
Stop the response |
`g?` |
Toggle help |
`q` |
Close the panel |

The panel is a normal read-only Markdown buffer. `j`

, `k`

, `/`

, `n`

, `N`

, `yy`

,
marks, and window commands work normally.

``` js
require("how").setup({
  window = {
    position = "right", -- "left" also works
    width = 0.38,
    min_width = 46,
  },
  keymaps = {
    ask = "i",
    apply = "a",
    close = "q",
    stop = "<C-c>",
    reset = "R",
    help = "g?",
  },
  codex = {
    command = "codex",
    model = nil, -- use the Codex default
  },
})
```

`require("how").status()`

returns a compact string suitable for a statusline.

Ordinary questions run with `readOnly`

sandbox policy and approvals disabled. An
assistant response becomes applicable only when it includes a valid internal
proposal marker. Pressing `a`

shows the proposal summary, files, and risk. Only
the exact **Apply exact proposal** selection starts a `workspaceWrite`

turn, whose
writable root is the Neovim config directory.

How automatically denies requests to write outside that directory. Shell
commands are displayed verbatim and require a separate **Allow once** decision.
There is deliberately no "allow for session" shortcut.

Runtime inspection works with custom configurations. Detection currently labels LazyVim, NvChad, AstroNvim, LunarVim, Kickstart, and custom setups. Distribution detection is a hint; effective mappings and loaded plugins remain the source of truth.

```
make test
make format
make check
```

MIT
