A lightweight, feature-rich shell implementation built in C# targeting .NET 9.0. Toysh provides a functional command-line interface with built-in commands, external command execution, and advanced shell features like history management, auto-completion, and line editing.
- Command Execution: Execute both built-in and external commands from your system's PATH
- Interactive Shell: Full-featured REPL with prompt and line editing capabilities
- Command Parsing: Sophisticated lexer, expander, and parser for processing shell input
- Error Handling: Graceful error management with proper exit codes
echo- Display text outputpwd- Print working directorycd- Change directoryexit- Exit the shelltype- Show command type (builtin or external)history- Access command history with read/write capabilities
- Auto-completion - Intelligent command and path auto-completion
- Command History - Persistent history storage with load/save functionality
- Line Editor - Rich line editing experience with history navigation
- Argument Parsing - Sophisticated argument parser supporting flags and options
- External Commands - Full PATH resolution and execution of system commands
- Variable Expansion - Support for variable expansion in commands
src/
├── main.cs # Entry point and shell initialization
├── Commands/ # Built-in command implementations
│ ├── Echo.cs
│ ├── Exit.cs
│ ├── Pwd.cs
│ ├── Cd.cs
│ ├── Type.cs
│ ├── History.cs
│ └── ExternalCommand.cs
├── Core/ # Core shell infrastructure
│ ├── CmdRegistry.cs # Command registry and lookup
│ ├── Executer.cs # Command execution engine
│ ├── LineEditor.cs # Interactive line editing
│ ├── AutoCompleter.cs # Auto-completion logic
│ ├── HistoryStore.cs # Command history management
│ ├── Lexer.cs # Tokenization
│ ├── Expander.cs # Variable expansion
│ ├── Parser.cs # AST generation
│ ├── Consts/ # Constants
│ ├── Enums/ # Enumerations
│ ├── Exceptions/ # Custom exceptions
│ ├── Interfaces/ # Core interfaces (ICommand, IOperator)
│ └── Types/ # AST types (Token, AstNode)
├── Parser/ # Parsing components
├── Utils/ # Utility functions
│ ├── ArgsParser.cs # Command-line argument parsing
│ ├── FileUtils.cs # File system utilities
│ ├── StreamUtils.cs # Stream operations
│ ├── Logger.cs # Logging utilities
│ └── AstLogger.cs # AST debugging
- .NET 9.0 SDK
- macOS, Linux, or Windows
dotnet builddotnet runThe shell will start in interactive mode and display a prompt awaiting user input.
Compiled binaries are available in:
- Debug mode:
bin/Debug/net9.0/Toysh - Release mode:
bin/Release/net9.0/Toysh
- Lexer tokenizes the user input
- Expander handles variable expansion
- Parser constructs an Abstract Syntax Tree (AST)
- Executer traverses the AST and executes commands
- Commands are resolved via the CommandRegistry and executed
The LineEditor provides:
- Real-time input feedback
- History navigation (up/down arrows)
- Auto-completion suggestions
- Standard editing keybindings
The CmdRegistry maintains two types of commands:
- Built-in Commands: Implemented as
ICommandinstances (echo, pwd, cd, etc.) - External Commands: System executables discovered via PATH resolution
Environment variables:
HISTFILE- Specifies the history file location (default:h)
- Create a new class in
src/Commands/implementingICommand - Implement required members:
Name,Type,ExecuteAsync() - Register the command in
Program.csviaRegisterBuiltinCommands()
class MyCommand : ICommand
{
public string Name => "mycommand";
public string Type => CommandType.Builtin;
public async Task ExecuteAsync(string[] args, CommandContext context)
{
await context.Output.WriteStringAsync("Hello from mycommand!");
}
}Run unit tests with:
dotnet testThe project includes logging utilities:
Logger.cs- General loggingAstLogger.cs- AST debugging and visualization
This project is part of the CodeCrafters challenge platform. https://app.codecrafters.io/courses/shell/overview