Terminal Brain is a small CLI assistant that uses your local ollama LLM with a decorator-based tool framework to run system commands and helper tools from your terminal in a simple interactive tmux session.
✅ Highlights
- Decorator-based tool registry (
@tool) intools.py— define tool metadata and handler in one place. tm_driver.pydrives an interactive session (tmux). Tests should exercise real handlers and tool flows by invoking tool handlers directly and supplying real secrets where relevant.- Robust incremental stream parsing withprocess_ollama_chunkandparse_ollama_streamto handle malformed LLM responses.- Tests under
tests/demonstrate parsing, injected-stream integration, and tool behavior. Tools include duckduck go search to search the web and "above_my_paygrayde" to ask a smarter llm for help (currently Gemini, aquire your gemini api key and place in secrets if you want to enable this), and run commands that puts input directly in your bash shell.(Whith confirmation of course.)
Requirements:
- OS: Linux (tested on Debian-based systems)
- Python 3.10 or newer
- tmux (required for interactive driver features)
- Python packages (install via pip):
- requests
- ollama
- duckduckgo-search (or install the newer
ddgspackage) - pytest (development/test dependency)
Install example:
python -m pip install -U pip
python -m pip install requests ollama duckduckgo-search pytest
# or, to use the renamed package:
# python -m pip install requests ollama ddgs pytestRun interactive driver:
python tm_driver.pyRun the test suite:
pytest -qImportant testing notes:
- Prefer invoking real tool handlers directly (use
get_tool_handler(name)and callhandler(args, context, execute=True)) for end-to-end verification. - Where external APIs are required, tests may use repository
secrets.json(loaded viatools.load_secrets()) or environment variables to authenticate real requests. - Logs: some tests write
tests/_last_tool_run.logwith detailed tool outputs.
This project intentionally bypasses common sandboxing and safety protections to be maximally powerful. It can execute arbitrary shell commands and may modify or destroy your system. Use it at your own risk — do not run this on machines you cannot afford to lose or on production systems. Always review any proposed commands before confirming execution. No live-guard or enforced interlocks are implemented; tests run the real methods and may perform real actions when executed.
For the interactive driver to work correctly, point your home tmux config at the repo's tmux config (symlink is preferred) and add the repository's bash additions to your shell rc.
Example (run from the repo root):
-
Backup existing tmux config: mv ~/.tmux.conf ~/.tmux.conf.backup
-
Create a symlink to the repo tmux config (preferred): ln -s "$(pwd)/tmux.conf" ~/.tmux.conf
-
Or copy instead: cp "$(pwd)/tmux.conf" ~/.tmux.conf
-
Reload tmux config: tmux source-file ~/.tmux.conf
-
Add the repo's bash additions to your shell rc so they're loaded for new shells (preferred): echo 'source /full/path/to/terminal_brain/bash_additions.sh' >> ~/.bashrc
echo 'source /full/path/to/terminal_brain/bash_additions.sh' >> ~/.zshrc
-
Apply immediately by sourcing your rc or opening a new shell: source ~/.bashrc
Adjust paths and filenames if your repository uses different names or if you use a shell other than bash.
tm_driver.py— main interactive driver and stream handlingtools.py— decorator-based tool registry and example toolstests/— unit and integration-style tests (parsing, injected streams, tool tests)
Tool handlers are functions with the signature:
def my_tool(args: Dict[str, Any], context: Dict[str, Any], execute: bool = False):
...Return values:
{'action': 'propose', 'proposal': '<text>'}— ask the user to confirm running something (interactive).{'action': 'result', 'output': '<text>'}— tool result (can be returned immediately in test mode or for read-only tools).{'action': 'add_tools', 'selected': [...], 'message': '...'}— used byrequest_toolshelper.{'action': 'error', 'message': '...'}— error state.
- Use
query_ollama_test_wrapperto inject a stream of chunks ({'message': {'content': '...'}}and{'message': {'tool_calls': ...}}) and assert on returned parsed state (full_response, tool_calls, errors). - Tests must ensure the new tool is added to
current_toolsandselected_tool_namesif the test expects to call it.
- Add tools via
@tool(...)intools.py(seeAgent Developer Guidefor details).
For more detailed developer guidance about how to author and test tools, see AGENT_GUIDE.md.