A modern, feature-rich shell written in Rust with an integrated Lisp interpreter and AI-powered command completion.
doge-shell (dsh) is a simple yet powerful shell that combines traditional shell capabilities with modern features like AI-assisted command completion, frecency-based history, and an embedded Lisp scripting environment.
- Interactive Command Line: Full-featured interactive shell with readline-like functionality
- Command Execution: Execute external commands, built-in commands, and shell scripts
- Background Processing: Run commands in background with
&and manage jobs - Pipes and Redirections: Support for pipes (
|), input/output redirection (>,>>,<), and error redirection - Signal Handling: Proper handling of signals like SIGINT, SIGQUIT, SIGTSTP
- Subshells: Support for command substitution and process substitution
- Frecency-based History: Intelligent command history using frecency scoring (frequency + recency)
- Directory Navigation: Smart directory history and jump with
zcommand - Path Management: Dynamic PATH management with
add_pathcommand - Job Control: Background job management with
jobs,bg,fgcommands - Aliases: Command aliasing with
aliascommand - Variables: Environment variable management with
var,setcommands - Abbreviations: Define and use abbreviations with
abbrcommand
- Context-Aware Completion: Intelligent tab completion for commands, files, and options
- Skim Integration: Fuzzy finding interface for completion using skim
- History Search: Interactive history search with Ctrl+R
- Command Abbreviations: Define and use abbreviations with
abbrcommand - AI-Powered Completion: OpenAI integration for intelligent command completion suggestions
- Embedded Lisp: Built-in Lisp interpreter for shell scripting
- Configuration: Shell configuration in Lisp with
~/.config/dsh/config.lisp - Custom Commands: Define custom shell commands using Lisp
- Extensibility: Extend shell functionality with Lisp functions
- MCP Client: Connect to external Model Context Protocol servers
- Multiple Transport: Support for stdio, HTTP, and SSE transports
- Dynamic Tools: Automatic discovery of MCP server tools
- Configuration: MCP servers can be configured in both config.lisp and config.toml
- Git Integration: Commands for Git operations (
gco,glog, etc.) - UUID Generation: Built-in UUID generation with
uuidcommand - URL Shortening: URL shortening with
dmvcommand - Web Server: Built-in static file server with
servecommand - Configuration Reload: Runtime configuration reloading with
reloadcommand
The shell includes many built-in commands:
| Command | Description |
|---|---|
exit |
Exit the shell |
cd |
Change directory |
history |
Show command history |
z |
Jump to frequently used directories |
jobs |
Show background jobs |
fg |
Bring job to foreground |
bg |
Send job to background |
lisp |
Execute Lisp expressions |
set |
Set shell variables |
var |
Manage shell variables |
read |
Read input into a variable |
abbr |
Configure abbreviations |
alias |
Configure command aliases |
chat |
Chat with AI assistant |
chat_prompt |
Set AI assistant system prompt |
chat_model |
Set AI model |
glog |
Git log with interactive selection |
gco |
Git checkout with interactive branch selection |
add_path |
Add path to PATH environment variable |
serve |
Start a static file server |
uuid |
Generate UUIDs |
dmv |
URL shortener |
reload |
Reload shell configuration |
help |
Show help information |
The embedded Lisp interpreter includes many built-in functions:
print- Print a valueis_null,is_number,is_symbol,is_boolean,is_procedure,is_pair- Type checkingcar,cdr,cons,list,nth,sort,reverse- List operationsmap,filter- Higher-order functionslength,range- List utilitieshash,hash_get,hash_set- Hash map functions+,-,*,/,truncate- Arithmetic operationsnot,==,!=,<,<=,>,>=- Comparison operationseval,apply- Meta functions
alias- Set command aliases from Lispabbr- Set abbreviations from Lispcommand- Execute external commands and capture outputsh- Execute shell commands in the current shell contextsh!- Execute shell commands with output capturesetenv- Set environment variablesvset- Set shell variablesadd_path- Add paths to PATHallow-direnv- Configure direnv roots
add-hook- Add a function to a hook listbound?- Check if a symbol is bound*pre-prompt-hooks*- Hook list for functions to run before prompt is displayed*pre-exec-hooks*- Hook list for functions to run before command execution*post-exec-hooks*- Hook list for functions to run after command execution*on-chdir-hooks*- Hook list for functions to run after changing directory
mcp-clear- Clear all MCP serversmcp-add-stdio- Add an MCP server with stdio transportmcp-add-http- Add an MCP server with HTTP transportmcp-add-sse- Add an MCP server with SSE transportchat-execute-clear- Clear execute tool allowlistchat-execute-add- Add command(s) to execute tool allowlist (accepts multiple commands)
Create a ~/.config/dsh/config.lisp file to configure your shell:
;; Example configuration
(setq prompt "πΆ > ")
(alias "ls" "ls --color=auto")
(alias "ll" "ls -alF")
(alias "la" "ls -A")
(alias "l" "ls -CF")
;; Set environment variables
(setenv "EDITOR" "vim")
(setenv "PAGER" "less")
;; Set shell variables
(vset "MY_VAR" "my_value")
;; Set abbreviations
(abbr "g" "git")
(abbr "ga" "git add")
(abbr "gc" "git commit")
(abbr "gs" "git status")
;; Add paths to PATH
(add_path "~/bin")
(add_path "~/.cargo/bin")
;; MCP server configuration using Lisp functions
(mcp-clear) ; Clear any existing servers before adding new ones
;; Add MCP server with stdio transport (for local executable servers)
;; Parameters: label, command path, arguments list, environment variables list, working directory (optional), description (optional)
(mcp-add-stdio
"local-dev-tools" ; label
"/path/to/your/mcp-server" ; command
'("arg1" "arg2") ; arguments list
'(("ENV_VAR1" "value1") ("ENV_VAR2" "value2")) ; environment variables list
'() ; working directory (NIL = current directory)
"Local development tools via stdio" ; description
)
;; Add MCP server with HTTP transport
;; Parameters: label, URL, authentication header (optional), allow stateless (optional), description (optional)
(mcp-add-http
"remote-http-service" ; label
"https://example.com/mcp" ; URL
'() ; authentication header (NIL = no auth)
'() ; allow stateless (NIL = false)
"Remote HTTP MCP service" ; description
)
;; Add MCP server with SSE transport
;; Parameters: label, URL, description (optional)
(mcp-add-sse
"streaming-service" ; label
"https://example.com/sse" ; URL
"SSE-based MCP service" ; description
)
;; Chat execute allowlist - commands that can be executed by AI assistant
(chat-execute-clear)
;; You can add multiple commands in a single call:
(chat-execute-add "ls" "cat" "echo" "grep" "find")
;; Or add them one by one as before:
;(chat-execute-add "ls")
;(chat-execute-add "cat")
;(chat-execute-add "echo")
;(chat-execute-add "grep")
;(chat-execute-add "find")
;; Hook System - Functions that run at specific shell events
;; Define a function to use as a hook
(defun my-pre-prompt-func ()
(print "Pre-prompt hook executed")
;; You can update variables, check status, etc.
)
(defun my-pre-exec-func (command)
(print (string-append "About to execute: " command))
)
(defun my-post-exec-func (command exit-code)
(print (string-append "Executed " command " with exit code: " (number->string exit-code)))
)
(defun my-chdir-func ()
(print (string-append "Changed directory to: " (getenv "PWD")))
)
;; Add functions to the appropriate hook lists
;; Note: add-hook expects the base name without asterisks - it adds them internally
(add-hook 'pre-prompt-hooks 'my-pre-prompt-func)
(add-hook 'pre-exec-hooks 'my-pre-exec-func)
(add-hook 'post-exec-hooks 'my-post-exec-func)
(add-hook 'on-chdir-hooks 'my-chdir-func)MCP (Model Context Protocol) allows the shell to connect to external services that provide tools for AI assistants. You can configure MCP servers in your config.lisp file using these functions:
Removes all currently configured MCP servers.
Adds an MCP server that communicates via standard input/output streams.
label: A unique identifier for the servercommand: Path to the server executableargs: List of command-line arguments to pass to the serverenv-vars: List of (key value) pairs for environment variablescwd: Working directory for the server (or NIL for current directory)description: Optional description of the server
Example:
(mcp-add-stdio
"git-tools"
"/usr/local/bin/git-mcp-server"
'("--verbose")
'(("GIT_AUTHOR_NAME" "Your Name"))
'()
"Git utility tools"
)Adds an MCP server that communicates via HTTP requests.
label: A unique identifier for the serverurl: The HTTP endpoint for the serverauth-header: Authentication header value (or NIL)allow-stateless: Whether to allow stateless operations (or NIL)description: Optional description of the server
Example:
(mcp-add-http
"remote-api"
"https://api.example.com/mcp"
'("Bearer your-token-here")
'()
"Remote API server"
)Adds an MCP server that communicates via Server-Sent Events.
label: A unique identifier for the serverurl: The SSE endpoint URLdescription: Optional description of the server
Example:
(mcp-add-sse
"events-service"
"https://events.example.com/stream"
"Real-time events service"
)For MCP server configuration, you can also create a ~/.config/dsh/config.toml file:
[mcp]
# Define MCP servers that connect via stdio
servers = [
{ label = "local-tools", description = "Local MCP tools", transport = { type = "stdio", command = "/path/to/server", args = [] } },
{ label = "remote-service", description = "Remote HTTP MCP service", transport = { type = "http", url = "https://example.com/mcp" } },
{ label = "streaming-service", description = "SSE MCP service", transport = { type = "sse", url = "https://example.com/sse" } }
]# Start the shell interactively
dsh
# Execute a single command
dsh -c "echo 'Hello, World!'"
# Execute a Lisp script
dsh -l "(print \"Hello from Lisp!\")"Import command history from other shells:
# Import from fish shell
dsh import fish
# Import from bash with custom path
dsh import bash --path /path/to/bash_historyTab- Context-aware completionCtrl+R- Interactive history searchCtrl+C- Cancel current command (press twice to exit shell)Ctrl+L- Clear screenCtrl+D- Show exit hint (useexitto leave)
The shell includes AI-powered command completion using OpenAI. To use this feature:
-
Set your OpenAI API key in the environment:
export AI_CHAT_API_KEY="your-api-key-here"
-
The shell will automatically provide command suggestions when available.
-
Use
!prefix to chat with the AI directly:!explain how to use the grep command
-
Use the
chatcommand for extended conversations:chat "How do I compress a directory with tar?"
dsh/- Main shell executable and core implementationdsh-builtin/- Built-in commandsdsh-frecency/- Frecency-based history managementdsh-types/- Shared data structuresdsh-openai/- OpenAI integrationcompletions/- Command completion definitions
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Add tests if applicable
- Run tests (
cargo test) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT/Apache-2.0 license - see the LICENSE file for details.