A portable terminal AI interface
195
stars
178
commits
Go
primary language
Jul 16, 2026
updated
A powerful and intuitive terminal utility for interacting with both local and cloud LLMs.
A tool for those who appreciate keyboard driven apps and terminal workflows (mouse works too btw)

Ensure API keys are configured before running NeKot
A good terminal with GPU acceleration is recommended (the app is mostly tested on Ghostty)
brew tap BalanceBalls/BalanceBalls
brew install nekot --cask
choco install nekot
Requires curl and tar.
For updating the app, just run the script again
Basic install:
sudo, and installs to /usr/local/bin/curl -fsSL https://raw.githubusercontent.com/BalanceBalls/nekot/main/install.sh | sudo sh
Install to path:
-p flag to specify install path.$PATH.sudo depending on the path specified.bash -c "$(curl -fsSL https://raw.githubusercontent.com/BalanceBalls/nekot/main/install.sh)" -- -p ~/.local/bin
$PATHNeKot can load the active provider's API key from a command or from its existing
environment variable. To use a secure store, add an apiKeyResolveCommand command to
~/.nekot/config.json:
{
"apiKeyResolveCommand": "cmd:security find-generic-password -s openrouter_nekot_key -w"
}
Everything after cmd: is executed once at startup using /bin/sh -c on macOS
and Linux, or cmd /C on Windows. The command's trimmed standard output is used
as the API key. This also supports password-manager CLIs, for example:
{
"apiKeyResolveCommand": "cmd:bw get password openrouter_nekot_key"
}
The command inherits NeKot's environment, including variables such as
BW_SESSION. Do not put secrets directly in the command. If apiKeyResolveCommand is absent
or empty, NeKot falls back to OPENAI_API_KEY, GEMINI_API_KEY, or
OPENROUTER_API_KEY, depending on the active provider. A configured command
takes precedence and a command failure does not fall back to the environment.
Plaintext values in apiKeyResolveCommand are rejected. Treat config files that
contain apiKeyResolveCommand like scripts: do not copy or run configs from
people you do not trust.
Set up your openai api key:
export OPENAI_API_KEY="some-key" # you would want to export this in your .zshrc or .bashrc
Set up your api key - how to get an api key
export GEMINI_API_KEY="some-key" # you would want to export this in your .zshrc or .bashrc
Set up your api key - how to get an api key
export OPENROUTER_API_KEY="some-key" # you would want to export this in your .zshrc or .bashrc
You can pipe input into the app and do things like this:
cat PROMPT.md | nekot -p openai -u http://localhost:11434 -m gpt-oss:latest -n
Web search feature uses tool calling for web search reqests exectution.
This feature can be toggled using Ctrl+w.
current_datetime tool alongside web_search so models can check the local date, time, and timezone before current-day searchesWe provide a config.json file within your directory for easy access to essential settings.
~/.nekot/config.json.C:\Users\%UserName%\.nekot\config.json or %HOMEPATH%\.nekot\config.json{
"providerBaseUrl": "https://api.openai.com", // Or http://localhost:11434, or any other OpenAi compatible API
"apiKeyResolveCommand": "", // Optional cmd: command; falls back to the provider's environment variable
"systemMessage": "",
"defaultModel": "",
"colorScheme": "groove", // pink, blue, groove
"provider": "openai", // openai, gemini, openrouter
"maxAttachmentSizeMb": 3,
"includeReasoningTokensInContext": true,
"sessionExportDir": "/must/be/absolute/path/to/exports",
"titleGeneration": {
"enabled": true,
"timeoutSeconds": 5
}
}
providerBaseUrl: The url can be anything that follows OpenAI API standard ( ollama, lmstudio, etc)apiKeyResolveCommand: optional cmd: command whose output provides the active provider's API keychatGPTApiUrl [obsolete]: same as providerBaseUrlsystemMessage field is available for customizing system prompt messages. Better to set it from the appdefaultModel field sets the default model. Better to set it from the appmaxAttachmentSizeMb field sets maximum allowed image sizeincludeReasoningTokensInContext field sets whether to include reasoning tokens in the next request or not.sessionExportDir allows to specify directory for session exports. If not set, exports are saved to current directory. The path must be an absolute pathtitleGeneration config for automatic session name generationYou can change API provider using the provider field.
Available providers:
openai defaultgeminiopenrouterTo use GeminiAPI, set "provider": "gemini" and configure apiKeyResolveCommand or GEMINI_API_KEY.
When using the gemini or openrouter providers, providerBaseUrl param is not used.
You can change colorscheme using the colorScheme field.
Available themes:
groove defaultpinkblueIf you need your settings and chats on other machine - simply copy chat.db and config.json from the .nekot/ directory
and paste to the same directory on other machine.
Models list is cached for 14 days upon loading. If you need to invalidate cache use --purge-cache flag:
nekot --purge-cache
To switch between openai and gemini APIs you can use -p flag:
nekot -p openai
nekot -p gemini
nekot -p openrouter
To specify provier url use -u flag(works with the openai provider only):
nekot -u http://localhost:11434
To specify color scheme use -t flag:
nekot -t blue
To specify a model use -m flag:
nekot -m "qwen3:4b"
To create a new session on start use -n flag:
nekot -n
Tab: Change focus between panes. The currently focused pane will be highlighted1-4 pane jumps: 1 prompt pane, 2, chat pane, 3 settings pane, 4 sessions paneCtrl+b or Ctrl+s: Interrupt inferenceCtrl+o: Toggles zen modeCtrl+c: Exit the programCtrl+n: Create new sessionCtrl+w: Toggles web search (preset level setting)Ctrl+h: Hide/show reasoning tokens (preset level setting)Ctrl+q: Start quick chatCtrl+x: Save quick chat to sessioni: Enters insert mode (you can now safely paste messages into the tui)
Ctrl+e: Open/Close prompt editor
Ctrl+r: Clear prompt
Ctrl+v: Paste text from the clipboard, or attach an image copied to the clipboard
Ctrl+s: Paste text from buffer as a code block (only in editor mode)
go the result of Ctrl+s will be:```go
{bufferContent}
```
esc: Exit insert mode for the prompt
esc second time will close editorCtrl+a: open file picker for attaching images. You can also attach images by typing: [img=/path/to/image]
y: Copies the last message into your clipboard.Shift+y: Copies all messages from current session into your clipboard.v, Shift+v or space: Enters navigation mode when chat pane is focused (allows to move accross the chat content lines)Left mouse button to enter line selection mode. Click left mouse button to enter selection mode, then hold left mouse button to select lines
Right mouse button to enter character selection mode (within a line). Click right mouse button to enter selection mode, then hold right mouse button to select text
Selection mode allows to navigate the chat pane and select lines to copy. Supports basic vim-motions.
Navigation
j, k - go down and up a lined, u, Ctrl+d, Ctrl+u - go up or down half pageg - go to topShift+g - go to bottomSelection
d, u, Ctrl+d, Ctrl+u - go up or down half pagej, k - go down and up a line
3j (3 lines down), 99k (99 lines up) are also supportedv, Shift+v or space to enter or quit line selection modey to copy selected text (with formatting from the app)r, c to copy selected text as raw LLM outputEsc to quit selection or navigation modes[ and ]: switch between presets and settings tabsm: Opens a model picker to change the model. (use / to set filter)f: Change the frequency valuet: Change the maximum number of tokens per messagee: Change the temperature valuep: Change the top_p value (nucleus sampling)s: Opens a text editor to edit system promptCtrl+r: resets current settings preset to default valuesCtrl+p: creates new preset with a specified name from the current presetd: remove preset (default and current selected presets cannot be removed)enter: select preset as the current one/: filter presetsCtrl+n: Creates a new session.Shift+X: Exports session to a markdown file.d: Deletes the currently selected session from the list.e: Edit session nameEnter: Switches to the session that is currently selected./: filter sessionsInformation pane displays processing state of inference (IDLE, PROCESSING) as well as token stats for the current session:
IN: shows the total amount of input tokens LLM consumed per sessionOUT: shows the total amount of output tokens LLM produced per sessionPlease refer to this guide as you navigate the TUI. Happy exploring!
The SQL db is stored in you your/home/directory/.nekot, as well as the debug log. To enable debug mode, export DEBUG=1 before running the program.
To get access to the release candidates, install command:
brew install rc-nekot
rc-nekot
Go
99.3%
A portable terminal AI interface
195
stars
178
commits
Go
primary language
Jul 16, 2026
updated
A powerful and intuitive terminal utility for interacting with both local and cloud LLMs.
A tool for those who appreciate keyboard driven apps and terminal workflows (mouse works too btw)

Ensure API keys are configured before running NeKot
A good terminal with GPU acceleration is recommended (the app is mostly tested on Ghostty)
brew tap BalanceBalls/BalanceBalls
brew install nekot --cask
choco install nekot
Requires curl and tar.
For updating the app, just run the script again
Basic install:
sudo, and installs to /usr/local/bin/curl -fsSL https://raw.githubusercontent.com/BalanceBalls/nekot/main/install.sh | sudo sh
Install to path:
-p flag to specify install path.$PATH.sudo depending on the path specified.bash -c "$(curl -fsSL https://raw.githubusercontent.com/BalanceBalls/nekot/main/install.sh)" -- -p ~/.local/bin
$PATHNeKot can load the active provider's API key from a command or from its existing
environment variable. To use a secure store, add an apiKeyResolveCommand command to
~/.nekot/config.json:
{
"apiKeyResolveCommand": "cmd:security find-generic-password -s openrouter_nekot_key -w"
}
Everything after cmd: is executed once at startup using /bin/sh -c on macOS
and Linux, or cmd /C on Windows. The command's trimmed standard output is used
as the API key. This also supports password-manager CLIs, for example:
{
"apiKeyResolveCommand": "cmd:bw get password openrouter_nekot_key"
}
The command inherits NeKot's environment, including variables such as
BW_SESSION. Do not put secrets directly in the command. If apiKeyResolveCommand is absent
or empty, NeKot falls back to OPENAI_API_KEY, GEMINI_API_KEY, or
OPENROUTER_API_KEY, depending on the active provider. A configured command
takes precedence and a command failure does not fall back to the environment.
Plaintext values in apiKeyResolveCommand are rejected. Treat config files that
contain apiKeyResolveCommand like scripts: do not copy or run configs from
people you do not trust.
Set up your openai api key:
export OPENAI_API_KEY="some-key" # you would want to export this in your .zshrc or .bashrc
Set up your api key - how to get an api key
export GEMINI_API_KEY="some-key" # you would want to export this in your .zshrc or .bashrc
Set up your api key - how to get an api key
export OPENROUTER_API_KEY="some-key" # you would want to export this in your .zshrc or .bashrc
You can pipe input into the app and do things like this:
cat PROMPT.md | nekot -p openai -u http://localhost:11434 -m gpt-oss:latest -n
Web search feature uses tool calling for web search reqests exectution.
This feature can be toggled using Ctrl+w.
current_datetime tool alongside web_search so models can check the local date, time, and timezone before current-day searchesWe provide a config.json file within your directory for easy access to essential settings.
~/.nekot/config.json.C:\Users\%UserName%\.nekot\config.json or %HOMEPATH%\.nekot\config.json{
"providerBaseUrl": "https://api.openai.com", // Or http://localhost:11434, or any other OpenAi compatible API
"apiKeyResolveCommand": "", // Optional cmd: command; falls back to the provider's environment variable
"systemMessage": "",
"defaultModel": "",
"colorScheme": "groove", // pink, blue, groove
"provider": "openai", // openai, gemini, openrouter
"maxAttachmentSizeMb": 3,
"includeReasoningTokensInContext": true,
"sessionExportDir": "/must/be/absolute/path/to/exports",
"titleGeneration": {
"enabled": true,
"timeoutSeconds": 5
}
}
providerBaseUrl: The url can be anything that follows OpenAI API standard ( ollama, lmstudio, etc)apiKeyResolveCommand: optional cmd: command whose output provides the active provider's API keychatGPTApiUrl [obsolete]: same as providerBaseUrlsystemMessage field is available for customizing system prompt messages. Better to set it from the appdefaultModel field sets the default model. Better to set it from the appmaxAttachmentSizeMb field sets maximum allowed image sizeincludeReasoningTokensInContext field sets whether to include reasoning tokens in the next request or not.sessionExportDir allows to specify directory for session exports. If not set, exports are saved to current directory. The path must be an absolute pathtitleGeneration config for automatic session name generationYou can change API provider using the provider field.
Available providers:
openai defaultgeminiopenrouterTo use GeminiAPI, set "provider": "gemini" and configure apiKeyResolveCommand or GEMINI_API_KEY.
When using the gemini or openrouter providers, providerBaseUrl param is not used.
You can change colorscheme using the colorScheme field.
Available themes:
groove defaultpinkblueIf you need your settings and chats on other machine - simply copy chat.db and config.json from the .nekot/ directory
and paste to the same directory on other machine.
Models list is cached for 14 days upon loading. If you need to invalidate cache use --purge-cache flag:
nekot --purge-cache
To switch between openai and gemini APIs you can use -p flag:
nekot -p openai
nekot -p gemini
nekot -p openrouter
To specify provier url use -u flag(works with the openai provider only):
nekot -u http://localhost:11434
To specify color scheme use -t flag:
nekot -t blue
To specify a model use -m flag:
nekot -m "qwen3:4b"
To create a new session on start use -n flag:
nekot -n
Tab: Change focus between panes. The currently focused pane will be highlighted1-4 pane jumps: 1 prompt pane, 2, chat pane, 3 settings pane, 4 sessions paneCtrl+b or Ctrl+s: Interrupt inferenceCtrl+o: Toggles zen modeCtrl+c: Exit the programCtrl+n: Create new sessionCtrl+w: Toggles web search (preset level setting)Ctrl+h: Hide/show reasoning tokens (preset level setting)Ctrl+q: Start quick chatCtrl+x: Save quick chat to sessioni: Enters insert mode (you can now safely paste messages into the tui)
Ctrl+e: Open/Close prompt editor
Ctrl+r: Clear prompt
Ctrl+v: Paste text from the clipboard, or attach an image copied to the clipboard
Ctrl+s: Paste text from buffer as a code block (only in editor mode)
go the result of Ctrl+s will be:```go
{bufferContent}
```
esc: Exit insert mode for the prompt
esc second time will close editorCtrl+a: open file picker for attaching images. You can also attach images by typing: [img=/path/to/image]
y: Copies the last message into your clipboard.Shift+y: Copies all messages from current session into your clipboard.v, Shift+v or space: Enters navigation mode when chat pane is focused (allows to move accross the chat content lines)Left mouse button to enter line selection mode. Click left mouse button to enter selection mode, then hold left mouse button to select lines
Right mouse button to enter character selection mode (within a line). Click right mouse button to enter selection mode, then hold right mouse button to select text
Selection mode allows to navigate the chat pane and select lines to copy. Supports basic vim-motions.
Navigation
j, k - go down and up a lined, u, Ctrl+d, Ctrl+u - go up or down half pageg - go to topShift+g - go to bottomSelection
d, u, Ctrl+d, Ctrl+u - go up or down half pagej, k - go down and up a line
3j (3 lines down), 99k (99 lines up) are also supportedv, Shift+v or space to enter or quit line selection modey to copy selected text (with formatting from the app)r, c to copy selected text as raw LLM outputEsc to quit selection or navigation modes[ and ]: switch between presets and settings tabsm: Opens a model picker to change the model. (use / to set filter)f: Change the frequency valuet: Change the maximum number of tokens per messagee: Change the temperature valuep: Change the top_p value (nucleus sampling)s: Opens a text editor to edit system promptCtrl+r: resets current settings preset to default valuesCtrl+p: creates new preset with a specified name from the current presetd: remove preset (default and current selected presets cannot be removed)enter: select preset as the current one/: filter presetsCtrl+n: Creates a new session.Shift+X: Exports session to a markdown file.d: Deletes the currently selected session from the list.e: Edit session nameEnter: Switches to the session that is currently selected./: filter sessionsInformation pane displays processing state of inference (IDLE, PROCESSING) as well as token stats for the current session:
IN: shows the total amount of input tokens LLM consumed per sessionOUT: shows the total amount of output tokens LLM produced per sessionPlease refer to this guide as you navigate the TUI. Happy exploring!
The SQL db is stored in you your/home/directory/.nekot, as well as the debug log. To enable debug mode, export DEBUG=1 before running the program.
To get access to the release candidates, install command:
brew install rc-nekot
rc-nekot
Go
99.3%