{"id":30135745,"url":"https://github.com/timewarpengineering/timewarp-amuru","last_synced_at":"2026-04-26T17:01:42.890Z","repository":{"id":304161600,"uuid":"1016904835","full_name":"TimeWarpEngineering/timewarp-amuru","owner":"TimeWarpEngineering","description":null,"archived":false,"fork":false,"pushed_at":"2026-04-25T16:41:35.000Z","size":2789,"stargazers_count":17,"open_issues_count":6,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-04-25T17:12:47.738Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TimeWarpEngineering.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"license","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-07-09T17:53:48.000Z","updated_at":"2026-04-25T16:41:03.000Z","dependencies_parsed_at":"2025-07-11T13:59:22.725Z","dependency_job_id":"087b000d-269d-4bf2-8cf8-4c68a23d9caa","html_url":"https://github.com/TimeWarpEngineering/timewarp-amuru","commit_stats":null,"previous_names":["timewarpengineering/timewarp-cli","timewarpengineering/timewarp-amuru"],"tags_count":52,"template":false,"template_full_name":null,"purl":"pkg:github/TimeWarpEngineering/timewarp-amuru","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimeWarpEngineering%2Ftimewarp-amuru","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimeWarpEngineering%2Ftimewarp-amuru/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimeWarpEngineering%2Ftimewarp-amuru/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimeWarpEngineering%2Ftimewarp-amuru/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TimeWarpEngineering","download_url":"https://codeload.github.com/TimeWarpEngineering/timewarp-amuru/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimeWarpEngineering%2Ftimewarp-amuru/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32305040,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T09:34:17.070Z","status":"ssl_error","status_checked_at":"2026-04-26T09:34:00.993Z","response_time":129,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-08-10T22:52:43.667Z","updated_at":"2026-04-26T17:01:42.881Z","avatar_url":"https://github.com/TimeWarpEngineering.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Stars](https://img.shields.io/github/stars/TimeWarpEngineering/timewarp-amuru?logo=github)](https://github.com/TimeWarpEngineering/timewarp-amuru)\n[![workflow](https://github.com/TimeWarpEngineering/timewarp-amuru/actions/workflows/release-build.yml/badge.svg)](https://github.com/TimeWarpEngineering/timewarp-amuru/actions)\n[![Forks](https://img.shields.io/github/forks/TimeWarpEngineering/timewarp-amuru)](https://github.com/TimeWarpEngineering/timewarp-amuru)\n[![License](https://img.shields.io/github/license/TimeWarpEngineering/timewarp-amuru.svg?style=flat-square\u0026logo=github)](https://github.com/TimeWarpEngineering/timewarp-amuru/issues)\n[![Issues Open](https://img.shields.io/github/issues/TimeWarpEngineering/timewarp-amuru.svg?logo=github)](https://github.com/TimeWarpEngineering/timewarp-amuru/issues)\n[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/TimeWarpEngineering/timewarp-amuru/badge)](https://scorecard.dev/viewer/?uri=github.com/TimeWarpEngineering/timewarp-amuru)\n\n[![nuget](https://img.shields.io/nuget/v/TimeWarp.Amuru?logo=nuget)](https://www.nuget.org/packages/TimeWarp.Amuru/)\n[![nuget](https://img.shields.io/nuget/dt/TimeWarp.Amuru?logo=nuget)](https://www.nuget.org/packages/TimeWarp.Amuru/)\n\n[![Twitter](https://img.shields.io/twitter/url?style=social\u0026url=https%3A%2F%2Fgithub.com%2FTimeWarpEngineering%2Ftimewarp-amuru)](https://twitter.com/intent/tweet?url=https://github.com/TimeWarpEngineering/timewarp-amuru)\n[![Dotnet](https://img.shields.io/badge/dotnet-10.0-blue)](https://dotnet.microsoft.com)\n\n[![Discord](https://img.shields.io/discord/715274085940199487?logo=discord)](https://discord.gg/7F4bS2T)\n[![Twitter](https://img.shields.io/twitter/follow/StevenTCramer.svg)](https://twitter.com/intent/follow?screen_name=StevenTCramer)\n[![Twitter](https://img.shields.io/twitter/follow/TheFreezeTeam1.svg)](https://twitter.com/intent/follow?screen_name=TheFreezeTeam1)\n\n\u003cimg src=\"https://raw.githubusercontent.com/TimeWarpEngineering/timewarpengineering.github.io/refs/heads/master/images/LogoNoMarginNoShadow.svg\" alt=\"logo\" height=\"120\" style=\"float: right\" /\u003e\n\n# TimeWarp.Amuru\n\n*Amuru means \"command\" in Swahili*\n\n**TimeWarp.Amuru** is a powerful fluent API library for elegant command-line execution in C#. It transforms shell scripting into a type-safe, IntelliSense-friendly experience with a simple static `Builder()` method, async operations, and proper error handling.\n\nDesigned for modern C# developers, TimeWarp.Amuru brings the power of shell scripting directly into your C# code. Whether you're building automation tools, DevOps scripts, or integrating command-line tools into your applications, TimeWarp.Amuru provides the elegant, type-safe API you need.\n\n## Why TimeWarp.Amuru?\n\n- **Zero Learning Curve**: If you know C#, you already know how to use TimeWarp.Amuru\n- **IntelliSense Everything**: Full IDE support with autocomplete, parameter hints, and documentation\n- **Type Safety**: Catch errors at compile-time, not runtime\n- **No String Escaping Hell**: Use C# arrays and parameters naturally\n- **Built for .NET 10**: Modern C# features and performance optimizations\n- **Script or Library**: Use it in quick scripts or production applications\n\n## Give a Star! :star:\n\nIf you find this project useful, please give it a star. Thanks!\n\n## Installation\n\n```bash\n# Core library for shell scripting and process execution\ndotnet add package TimeWarp.Amuru\n```\n\nOr reference in your C# runfile:\n```csharp\n#:package TimeWarp.Amuru@\u003clatest-version\u003e\n```\n\n### Optional: CLI Tools\n\n```bash\n# Global CLI tool with additional utilities (private package)\ndotnet tool install --global TimeWarp.Ganda --source https://nuget.pkg.github.com/TimeWarpEngineering/index.json\n```\n\nThe CLI tool includes various utilities like timestamp conversion, color generation, and more. See the [Ganda repository](https://github.com/TimeWarpEngineering/timewarp-ganda) for details.\n\n## Quick Start\n\n```csharp\n#!/usr/bin/dotnet --\n#:package TimeWarp.Amuru\n\nusing TimeWarp.Amuru;\nusing static System.Console;\n\n// Default behavior - stream to console (like bash/PowerShell)\nawait Shell.Builder(\"npm\", \"install\").RunAsync();\n\n// Capture output when needed\nvar result = await Shell.Builder(\"git\", \"status\").CaptureAsync();\nif (result.Success)\n{\n    WriteLine($\"Git says: {result.Stdout}\");\n}\n\n// Stream large files without memory issues\nawait foreach (var line in Shell.Builder(\"tail\", \"-f\", \"/var/log/app.log\").StreamStdoutAsync())\n{\n    WriteLine($\"Log: {line}\");\n}\n\n// Chain commands with pipelines\nvar result = await Shell.Builder(\"find\", \".\", \"-name\", \"*.cs\")\n    .Pipe(\"grep\", \"async\")\n    .CaptureAsync();\nWriteLine($\"Found {result.Lines.Length} async files\");\n\n// Work with CommandOutput\nvar output = await Shell.Builder(\"docker\", \"ps\").CaptureAsync();\nWriteLine($\"Exit code: {output.ExitCode}\");\nWriteLine($\"Success: {output.Success}\");\nWriteLine($\"Stdout: {output.Stdout}\");\nWriteLine($\"Stderr: {output.Stderr}\");\nWriteLine($\"Combined: {output.Combined}\");\n\n// Use the fluent builder API for complex commands\nvar result = await Shell.Builder(\"git\")\n    .WithArguments(\"log\", \"--oneline\", \"-n\", \"10\")\n    .WithWorkingDirectory(\"/my/repo\")\n    .WithCancellationToken(cancellationToken)\n    .CaptureAsync();\n\n// Provide standard input to commands\nvar grepResult = await Shell.Builder(\"grep\")\n    .WithArguments(\"pattern\")\n    .WithStandardInput(\"line1\\nline2 with pattern\\nline3\")\n    .CaptureAsync();\n\n// Interactive selection with Fzf\nvar selectedFile = await Fzf.Builder()\n    .FromInput(\"file1.txt\", \"file2.txt\", \"file3.txt\")\n    .WithPreview(\"cat {}\")\n    .SelectAsync();\n\n// Interactive pipeline - find and select files\nvar chosenFile = await Shell.Builder(\"find\")\n    .WithArguments(\".\", \"-name\", \"*.cs\")\n    .Pipe(\"fzf\", \"--preview\", \"head -20 {}\")\n    .SelectAsync();\n\n// Full interactive mode for stream-based tools (fzf, REPLs)\nawait Shell.Builder(\"fzf\")\n    .PassthroughAsync();\n\n// TUI applications (vim, nano, edit) need true TTY passthrough\nawait Shell.Builder(\"vim\")\n    .WithArguments(\"myfile.txt\")\n    .TtyPassthroughAsync();\n```\n\n### DotNet Commands\n\n```csharp\n// Global dotnet options\nvar sdks = await DotNet.WithListSdks().CaptureAsync();\nvar runtimes = await DotNet.WithListRuntimes().CaptureAsync();\nvar version = await DotNet.WithVersion().CaptureAsync();\n\n// Base builder for custom arguments\nvar result = await DotNet.Builder()\n    .WithArguments(\"--list-sdks\")\n    .CaptureAsync();\n\n// Build and test with streaming output\nawait DotNet.Build()\n    .WithConfiguration(\"Release\")\n    .RunAsync();\n\nawait DotNet.Test()\n    .WithFilter(\"Category=Unit\")\n    .RunAsync();\n```\n\n### Conditional Configuration\n\nThe `When()` extension method allows you to apply configuration conditionally without breaking the fluent chain:\n\n```csharp\n// Without When() - breaks the fluent chain\nDotNetAddPackageBuilder builder = DotNet.AddPackage(packageName);\nif (version != null)\n{\n    builder = builder.WithVersion(version);\n}\nelse\n{\n    builder = builder.WithPrerelease();\n}\nawait builder.CaptureAsync();\n\n// With When() - keeps the fluent chain intact\nawait DotNet.AddPackage(packageName)\n    .WithProject(projectFile)\n    .When(version != null, b =\u003e b.WithVersion(version!))\n    .When(version == null, b =\u003e b.WithPrerelease())\n    .CaptureAsync();\n\n// Works with all builders\nawait Shell.Builder(\"git\")\n    .WithArguments(\"push\")\n    .When(force, b =\u003e b.WithArguments(\"--force\"))\n    .When(dryRun, b =\u003e b.WithArguments(\"--dry-run\"))\n    .When(workDir != null, b =\u003e b.WithWorkingDirectory(workDir!))\n    .RunAsync();\n```\n\n### Available Extension Methods\n\nAll extension methods work on any builder that implements `ICommandBuilder\u003cT\u003e`:\n\n**`When(condition, configure)`** - Apply configuration when condition is true\n```csharp\n.When(version != null, b =\u003e b.WithVersion(version!))\n```\n\n**`WhenNotNull(value, configure)`** - Apply configuration when value is not null, passing the value\n```csharp\n.WhenNotNull(version, (b, v) =\u003e b.WithVersion(v))  // Cleaner than When!\n```\n\n**`Unless(condition, configure)`** - Apply configuration when condition is false\n```csharp\n.Unless(isProduction, b =\u003e b.WithVerbose())\n```\n\n**`Apply(configure)`** - Extract and reuse configuration logic\n```csharp\nstatic DotNetBuildBuilder AddProductionSettings(DotNetBuildBuilder b) =\u003e\n  b.WithConfiguration(\"Release\").WithNoRestore();\n\nawait DotNet.Build()\n  .Apply(AddProductionSettings)\n  .RunAsync();\n```\n\n**`ForEach(items, configure)`** - Apply configuration for each item\n```csharp\n.ForEach(sources, (b, source) =\u003e b.WithSource(source))\n```\n\n**`Tap(action)`** - Side effects without modifying the builder (logging, debugging)\n```csharp\n.Tap(b =\u003e Console.WriteLine($\"Building with config: {b}\"))\n```\n\nThese extensions:\n- Maintain type safety and IntelliSense support\n- Keep method chains fluent and readable\n- Work with all command builders (Shell, DotNet, Fzf, etc.)\n- Enable functional programming patterns\n\n## Key Features\n\n- **Shell-Like Default**: `RunAsync()` streams to console just like bash/PowerShell\n- **Explicit Capture**: `CaptureAsync()` for when you need to process output\n- **Memory-Efficient Streaming**: `IAsyncEnumerable` for large data without buffering\n- **Complete Output Access**: CommandOutput with Stdout, Stderr, Combined, and ExitCode\n- **Fluent Interface**: Chain operations naturally with `.Pipe()` and builder methods\n- **Conditional Configuration**: `When()` extension for fluent conditional logic\n- **Async-First Design**: All operations support modern async/await patterns\n- **Smart Error Handling**: Commands throw on errors by default, with opt-in graceful degradation\n- **Pipeline Support**: Chain commands with Unix-like pipe semantics\n- **Standard Input Support**: Provide stdin to commands with `.WithStandardInput()`\n- **NO CACHING Philosophy**: Like shells, commands run fresh every time\n- **Configuration Options**: Working directory, environment variables, and more\n- **Cancellation Support**: Full CancellationToken support for timeouts and manual cancellation\n- **Cross-Platform**: Works on Windows, Linux, and macOS\n- **Command Builders**: Fluent builders for complex commands (DotNet, Fzf, Ghq, Gwq)\n- **Interactive Commands**: `PassthroughAsync()` for stream-based tools, `TtyPassthroughAsync()` for TUI apps (vim, nano), `SelectAsync()` for selection tools\n- **.NET 10 Script Support**: AppContext extensions and ScriptContext for file-based apps\n\n## Output Handling\n\n### Core API Methods\n\nTimeWarp.Amuru provides clear, purpose-built methods for different scenarios:\n\n```csharp\n// RunAsync() - Default shell behavior, streams to console\nawait Shell.Builder(\"npm\", \"install\").RunAsync();\n// Returns: exit code (int)\n// Console output: real-time streaming\n\n// CaptureAsync() - Silent execution with full output capture\nvar result = await Shell.Builder(\"git\", \"status\").CaptureAsync();\n// Returns: CommandOutput with all streams\n// Console output: none (silent)\n\n// PassthroughAsync() - Stream-based interactive tools (fzf, REPLs)\nawait Shell.Builder(\"fzf\").PassthroughAsync();\n// Returns: ExecutionResult\n// Console output: piped through Console streams\n\n// TtyPassthroughAsync() - True TTY for TUI applications (vim, nano, edit)\nawait Shell.Builder(\"vim\", \"file.txt\").TtyPassthroughAsync();\n// Returns: ExecutionResult\n// Console output: inherits parent TTY (required for TUI apps)\n\n// SelectAsync() - Selection tools (shows UI, captures selection)\nvar selected = await Fzf.Builder()\n    .FromInput(\"option1\", \"option2\")\n    .SelectAsync();\n// Returns: selected string\n// Console output: UI on stderr, selection captured from stdout\n```\n\n### The CommandOutput Type\n\n```csharp\nvar output = await Shell.Builder(\"docker\", \"ps\").CaptureAsync();\n\n// Access individual streams\nConsole.WriteLine($\"Stdout: {output.Stdout}\");\nConsole.WriteLine($\"Stderr: {output.Stderr}\");\nConsole.WriteLine($\"Combined: {output.Combined}\"); // Both in chronological order\n\n// Check status\nConsole.WriteLine($\"Exit code: {output.ExitCode}\");\nConsole.WriteLine($\"Success: {output.Success}\"); // ExitCode == 0\n\n// Convenience properties for line processing\nforeach (var line in output.Lines) // Combined.Split('\\n')\n{\n    ProcessLine(line);\n}\n```\n\n### Streaming Large Data\n\nFor commands that produce large amounts of data:\n\n```csharp\n// Stream lines as they arrive (no buffering)\nawait foreach (var line in Shell.Builder(\"tail\", \"-f\", \"/var/log/app.log\")\n    .StreamStdoutAsync(cancellationToken))\n{\n    Console.WriteLine($\"Log: {line}\");\n}\n\n// Stream with LINQ-style processing\nvar errorLines = Shell.Builder(\"cat\", \"huge.log\")\n    .StreamStdoutAsync()\n    .Where(line =\u003e line.Contains(\"ERROR\"))\n    .Take(100);\n\nawait foreach (var error in errorLines)\n{\n    LogError(error);\n}\n```\n\n### Method Comparison\n\n| Method | Console Output | Captures | Returns | Primary Use Case |\n|--------|---------------|----------|---------|------------------|\n| `RunAsync()` | ✅ Real-time | ❌ | Exit code | Default scripting (80%) |\n| `CaptureAsync()` | ❌ Silent | ✅ All streams | CommandOutput | Process output (15%) |\n| `PassthroughAsync()` | ✅ Piped | ❌ | ExecutionResult | Stream-based interactive (3%) |\n| `TtyPassthroughAsync()` | ✅ TTY | ❌ | ExecutionResult | TUI apps (vim, nano) (1%) |\n| `SelectAsync()` | ✅ UI only | ✅ Selection | string | Selection tools (1%) |\n| `StreamStdoutAsync()` | ❌ | ✅ As stream | IAsyncEnumerable | Large data |\n\n### Design Philosophy: NO CACHING\n\nTimeWarp.Amuru intentionally does NOT cache command results:\n\n```csharp\n// Shells don't cache - neither do we\nawait Shell.Builder(\"date\").RunAsync();  // Shows current time\nawait Shell.Builder(\"date\").RunAsync();  // Shows NEW current time\n\n// If you need caching, it's trivial in C#:\nprivate static CommandOutput? cachedResult;\nvar result = cachedResult ??= await Shell.Builder(\"expensive-command\").CaptureAsync();\n```\n\n**Why no caching?**\n- Commands can have side effects\n- Results change over time\n- Shells don't cache\n- Users can trivially cache in C# if needed\n\n## Error Handling\n\nTimeWarp.Amuru provides intelligent error handling that distinguishes between different failure types:\n\n### Default Behavior (Throws Exceptions)\n```csharp\n// Throws CommandExecutionException on non-zero exit code\nawait Shell.Builder(\"ls\", \"/nonexistent\").RunAsync();\n\n// CaptureAsync also throws on failure by default\nvar result = await Shell.Builder(\"git\", \"invalid-command\").CaptureAsync();\n```\n\n### Graceful Degradation (Opt-in)\n```csharp\n// Disable validation for graceful degradation\nvar result = await Shell.Builder(\"ls\", \"/nonexistent\")\n    .WithValidation(CommandResultValidation.None)\n    .CaptureAsync();\n\nif (!result.Success)\n{\n    Console.WriteLine($\"Command failed with exit code: {result.ExitCode}\");\n    Console.WriteLine($\"Error: {result.Stderr}\");\n}\n```\n\n### Cancellation and Timeouts\n```csharp\n// With explicit cancellation token\nvar cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));\nawait Shell.Builder(\"long-running-command\")\n    .RunAsync(cts.Token);\n\n// With timeout via builder\nawait Shell.Builder(\"slow-command\")\n    .WithTimeout(TimeSpan.FromSeconds(10))\n    .RunAsync();\n\n// Timeout and external token are combined\nawait Shell.Builder(\"another-command\")\n    .WithTimeout(TimeSpan.FromSeconds(5))\n    .RunAsync(userCancellationToken);\n```\n\n## Testing and Mocking\n\nTimeWarp.Amuru provides built-in support for mocking commands during testing through the `CliConfiguration` class:\n\n### Basic Mocking\n```csharp\n// Set up mock commands for testing\nCliConfiguration.SetCommandPath(\"fzf\", \"/path/to/mock/fzf\");\nCliConfiguration.SetCommandPath(\"git\", \"/path/to/mock/git\");\n\n// Your code using these commands will now use the mocks\nvar selected = await Fzf.Builder()\n    .FromInput(\"option1\", \"option2\", \"option3\")\n    .SelectAsync(); // Uses mock fzf\n\nvar status = await Shell.Builder(\"git\", \"status\")\n    .CaptureAsync(); // Uses mock git\n\n// Clean up after tests\nCliConfiguration.Reset();\n```\n\n### Creating Mock Executables\n```csharp\n// Create a simple mock script\nFile.WriteAllText(\"/tmp/mock-fzf\", \"#!/bin/bash\\necho 'mock-selection'\");\nawait Shell.Builder(\"chmod\", \"+x\", \"/tmp/mock-fzf\").RunAsync();\n\n// Configure TimeWarp.Amuru to use it\nCliConfiguration.SetCommandPath(\"fzf\", \"/tmp/mock-fzf\");\n\n// Now SelectAsync will use the mock\nvar selected = await Fzf.Builder()\n    .FromInput(\"a\", \"b\", \"c\")\n    .SelectAsync(); // Returns \"mock-selection\"\n```\n\n### Testing Interactive Commands\nFor commands like `fzf` that are normally interactive, you can either:\n1. Use mock executables as shown above\n2. Use non-interactive modes (e.g., `fzf --filter`)\n\n### API Reference\n- `CliConfiguration.SetCommandPath(command, path)` - Set custom executable path\n- `CliConfiguration.ClearCommandPath(command)` - Remove custom path for a command\n- `CliConfiguration.Reset()` - Clear all custom paths\n- `CliConfiguration.HasCustomPath(command)` - Check if command has custom path\n- `CliConfiguration.AllCommandPaths` - Get all configured paths\n\n## .NET 10 File-Based App Support\n\nTimeWarp.Amuru provides specialized support for .NET 10's new file-based apps (single-file C# scripts) with AppContext extensions and ScriptContext for directory management.\n\n- **AppContext Extensions** - Clean access to script metadata without magic strings\n- **ScriptContext** - Automatic working directory management with cleanup guarantees\n- **ProcessExit Handling** - Cleanup runs even with `Environment.Exit()`\n\n📖 **[See the documentation](Documentation/Developer/HowToGuides/)** for detailed usage guides and examples.\n\n## Architecture\n\nTimeWarp.Amuru is built on several key architectural principles:\n\n- **Static Entry Point**: Minimal ceremony with global `Builder()` method\n- **Immutable Design**: Thread-safe, readonly objects throughout\n- **Integration Testing**: Real command validation over mocking\n- **Predictable Error Handling**: Clear distinction between failure types\n- **Opt-in Complexity**: Advanced features available when needed\n\nSee our [Architectural Decision Records](Documentation/Conceptual/ArchitecturalDecisionRecords/Overview.md) for detailed design rationale.\n\n## Documentation\n\n- **[Migration Guide](Analysis/MigrationGuide.md)** - Guide for migrating from older versions\n- **[command-extensions.cs](source/timewarp-amuru/core/command-extensions.cs)** - Collocated command construction design documentation\n- **[command-result.cs](source/timewarp-amuru/core/command-result.cs)** - Collocated command execution design documentation\n- **[Architectural Decisions](Documentation/Conceptual/ArchitecturalDecisionRecords/Overview.md)** - Design rationale and decisions\n\n## Example Scripts\n\nSee [Spikes/CsScripts/](Spikes/CsScripts/) for example scripts demonstrating TimeWarp.Amuru usage patterns.\n\n## Unlicense\n\n[![License](https://img.shields.io/github/license/TimeWarpEngineering/timewarp-amuru.svg?style=flat-square\u0026logo=github)](https://unlicense.org)  \nThis project is licensed under the [Unlicense](https://unlicense.org).\n\n## Related Packages\n\n- **[TimeWarp.Multiavatar](https://www.nuget.org/packages/TimeWarp.Multiavatar/)** - Avatar generation library (see [documentation](Source/TimeWarp.Multiavatar/README.md))\n- **[TimeWarp.Ganda](https://github.com/TimeWarpEngineering/timewarp-ganda)** - Shell toolkit CLI (private, moved to separate repository)\n- **[TimeWarp.Zana](https://github.com/TimeWarpEngineering/timewarp-ganda)** - Private utilities library (in timewarp-ganda repo)\n\n## Contributing\n\nYour contributions are welcome! Before starting any work, please open a [discussion](https://github.com/TimeWarpEngineering/timewarp-amuru/discussions).\n\nSee our [Kanban board](Kanban/Overview.md) for current development tasks and priorities.\n\n## Contact\n\nIf you have an issue and don't receive a timely response, feel free to reach out on our [Discord server](https://discord.gg/A55JARGKKP).\n\n[![Discord](https://img.shields.io/discord/715274085940199487?logo=discord)](https://discord.gg/7F4bS2T)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimewarpengineering%2Ftimewarp-amuru","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftimewarpengineering%2Ftimewarp-amuru","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimewarpengineering%2Ftimewarp-amuru/lists"}