{"id":50336932,"url":"https://github.com/benoitpetit/agent-spinner","last_synced_at":"2026-05-29T14:01:27.122Z","repository":{"id":350255172,"uuid":"1205838647","full_name":"benoitpetit/agent-spinner","owner":"benoitpetit","description":"Unicode spinner animations for Go CLI applications. Beautiful, smooth, and highly customizable terminal spinners.","archived":false,"fork":false,"pushed_at":"2026-04-09T14:08:43.000Z","size":508,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-09T16:10:23.417Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://devbyben.fr","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/benoitpetit.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":null,"dco":null,"cla":null}},"created_at":"2026-04-09T10:26:42.000Z","updated_at":"2026-04-09T14:08:47.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/benoitpetit/agent-spinner","commit_stats":null,"previous_names":["benoitpetit/agent-spinner"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/benoitpetit/agent-spinner","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benoitpetit%2Fagent-spinner","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benoitpetit%2Fagent-spinner/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benoitpetit%2Fagent-spinner/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benoitpetit%2Fagent-spinner/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/benoitpetit","download_url":"https://codeload.github.com/benoitpetit/agent-spinner/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benoitpetit%2Fagent-spinner/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33655441,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-29T02:00:06.066Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":"2026-05-29T14:01:26.292Z","updated_at":"2026-05-29T14:01:27.116Z","avatar_url":"https://github.com/benoitpetit.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Agent Spinner\n\nUnicode spinner animations for Go CLI applications. Beautiful, smooth, and highly customizable terminal spinners with 42 built-in styles.\n\n![Agent Spinner Logo](./logo.png)\n\n## Features\n\n- 🎨 **42 Built-in Spinners** - From classic braille to modern animations\n- ⚡ **Lightweight** - Zero external dependencies\n- 🎯 **Thread-Safe** - Concurrent access safe by design\n- 🔧 **Customizable** - Create your own spinners easily\n- 📦 **Simple API** - Start spinning in 3 lines of code\n- 🖥️ **Terminal Aware** - Proper cursor handling and cleanup\n\n## Installation\n\n```bash\ngo get github.com/benoitpetit/agent-spinner\n```\n\nRequires Go 1.21 or later.\n\n## Quick Start\n\n```go\npackage main\n\nimport (\n    \"time\"\n    agentspinner \"github.com/benoitpetit/agent-spinner\"\n)\n\nfunc main() {\n    spinner := agentspinner.Start(\"Loading...\")\n    time.Sleep(2 * time.Second)\n    spinner.Stop(\"Done!\")\n}\n```\n\n## Usage Examples\n\n### Basic Usage\n\n```go\n// Default braille spinner\nspinner := agentspinner.Start(\"Processing...\")\nspinner.Stop(\"Complete!\")\n```\n\n### With Different Styles\n\n```go\n// Sci-fi style\nspinner := agentspinner.Start(\"Training AI...\", agentspinner.Helix)\n\n// Matrix/cyberpunk style\nspinner = agentspinner.Start(\"Decrypting...\", agentspinner.Matrix)\n\n// Progress bar style\nspinner = agentspinner.Start(\"Uploading...\", agentspinner.Progress)\n```\n\n### Update Message During Operation\n\n```go\nspinner := agentspinner.Start(\"Step 1/3...\")\nspinner.Update(\"Step 2/3...\")\nspinner.Update(\"Step 3/3...\")\nspinner.Stop(\"Finished!\")\n```\n\n### Error Handling\n\n```go\nspinner := agentspinner.Start(\"Validating...\")\n// On error:\nspinner.Fail(\"Validation failed!\")\n```\n\n### Run Helper (Simplified)\n\n```go\n// Execute function with automatic spinner\nerr := agentspinner.Run(\"Uploading...\", func() error {\n    // Your work here\n    return nil\n}, agentspinner.Radar)\n```\n\n### Run with Result\n\n```go\nresult, err := agentspinner.RunWithResult(\"Computing...\", func() (string, error) {\n    return \"42\", nil\n}, agentspinner.Star)\n```\n\n### Custom Spinner\n\n```go\ncustom := agentspinner.Spinner{\n    Frames:   []string{\"◐\", \"◓\", \"◑\", \"◒\"},\n    Interval: 100, // milliseconds\n}\nspinner := agentspinner.StartCustom(\"Loading...\", custom)\n```\n\n### Signal Handling\n\n```go\n// Graceful shutdown on Ctrl+C\nspinner := agentspinner.Start(\"Working...\").HandleSignals()\nspinner.Stop()\n```\n\n### Custom Output with RawRenderer\n\n```go\n// Fully control the output format\nrenderer := agentspinner.NewRawRenderer()\nrenderer.Output = os.Stdout\nrenderer.FormatFrame = \"\\r→ %s %s\"     // Custom prefix\nrenderer.FormatFinal = \"\\r→ %s %s\\n\"   // Custom final format\n\nspinner := agentspinner.StartCustom(\"Processing...\",\n    agentspinner.NewDefaultRegistry().Get(agentspinner.Dots),\n    agentspinner.WithRenderer(renderer),\n)\nspinner.Stop(\"Done!\")\n```\n\n## Available Spinners\n\n### Classic Braille Spinners\n\n| Name | Preview | Description | Interval |\n|------|---------|-------------|----------|\n| `Braille` | `⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏` | Classic rotating braille (default) | 80ms |\n| `BrailleWave` | `⠁⠂⠄⡀ → ⠂⠄⡀⢀ → ...` | Wave pattern across braille cells | 100ms |\n| `DNA` | `⠋⠉⠙⠚ → ⠉⠙⠚⠒ → ...` | Double helix DNA animation | 80ms |\n\n### Movement \u0026 Scan\n\n| Name | Description | Interval |\n|------|-------------|----------|\n| `Scan` | Vertical scanner bar moving left to right | 70ms |\n| `ScanDual` | Dual vertical scanners converging from edges | 70ms |\n| `ScanLine` | Horizontal scanning line moving up and down | 120ms |\n| `Cascade` | Diagonal cascading effect | 60ms |\n| `FillSweep` | Bottom-to-top fill animation | 100ms |\n| `DiagSwipe` | Diagonal wipe transition | 60ms |\n\n### Wave Animations\n\n| Name | Description | Interval |\n|------|-------------|----------|\n| `Wave` | Horizontal sine wave | 100ms |\n| `WaveVertical` | Vertical sine wave | 100ms |\n| `WaveRows` | Row-based wave motion | 90ms |\n| `Ripple` | Expanding circular ripple | 100ms |\n\n### Geometric Patterns\n\n| Name | Description | Interval |\n|------|-------------|----------|\n| `Helix` | Double helix spiral | 80ms |\n| `Orbit` | Orbiting dot pattern | 100ms |\n| `Circle` | Drawing circle animation | 100ms |\n| `Diamond` | Expanding diamond shape | 120ms |\n| `Cross` | Rotating cross/plus | 80ms |\n| `Star` | Four-pointed star rotation | 90ms |\n| `Zigzag` | Zigzag pattern | 120ms |\n\n### Progress \u0026 Loading\n\n| Name | Description | Interval |\n|------|-------------|----------|\n| `Progress` | Left-to-right progress bar | 80ms |\n| `Loading` | Progressive cell fill animation | 50ms |\n| `Bars` | Animated bar chart | 90ms |\n| `Columns` | Filling columns sequentially | 60ms |\n| `Expand` | Expanding rectangle from center | 80ms |\n| `Shrink` | Shrinking rectangle to center | 80ms |\n| `RandomFill` | Random cell filling pattern | 60ms |\n| `Border` | Border tracing animation | 100ms |\n\n### Modern \u0026 Fun\n\n| Name | Description | Interval |\n|------|-------------|----------|\n| `Matrix` | Matrix-style falling code | 80ms |\n| `Pulse` | Pulsing heartbeat effect | 180ms |\n| `Radar` | Radar/sonar sweep | 100ms |\n| `Typing` | Typing cursor animation | 80ms |\n| `Bounce` | Bouncing ball effect | 100ms |\n| `PingPong` | Ping pong game simulation | 80ms |\n| `Snake` | Snake game-like path | 80ms |\n\n### Decorative\n\n| Name | Description | Interval |\n|------|-------------|----------|\n| `Sparkle` | Random sparkle pattern | 150ms |\n| `Rain` | Matrix-style rain drops | 100ms |\n| `Tiles` | Tiling pattern animation | 200ms |\n| `Checkerboard` | Alternating checker pattern | 250ms |\n| `Breathe` | Breathing effect with expanding dots | 100ms |\n\n### Arrows \u0026 Indicators\n\n| Name | Description | Interval |\n|------|-------------|----------|\n| `Arrow` | Moving arrow pointer | 120ms |\n| `Dots` | Animated dot matrix | 120ms |\n\n### Complete List\n\n**Classic:** `Braille`, `BrailleWave`, `DNA`\n\n**Movement:** `Scan`, `ScanDual`, `ScanLine`, `Cascade`, `FillSweep`, `DiagSwipe`\n\n**Wave:** `Wave`, `WaveVertical`, `WaveRows`, `Ripple`\n\n**Geometric:** `Helix`, `Orbit`, `Circle`, `Diamond`, `Cross`, `Star`, `Zigzag`\n\n**Progress:** `Progress`, `Loading`, `Bars`, `Columns`, `Expand`, `Shrink`, `RandomFill`, `Border`\n\n**Modern:** `Matrix`, `Pulse`, `Radar`, `Typing`, `Bounce`, `PingPong`, `Snake`, `Rain`, `Sparkle`\n\n**Decorative:** `Tiles`, `Checkerboard`, `Breathe`\n\n**Indicators:** `Arrow`, `Dots`\n\n## API Reference\n\n### Functions\n\n| Function | Description |\n|----------|-------------|\n| `Start(message, name?)` | Create and start a spinner with optional style name |\n| `StartCustom(message, spinner, opts...)` | Start with custom spinner definition |\n| `Run(message, fn, name?)` | Execute function with automatic spinner handling |\n| `RunWithResult[T](message, fn, name?)` | Execute function returning a value with spinner |\n| `NewDefaultRegistry()` | Get the default spinner registry |\n| `NewMutableRegistry()` | Get a mutable registry for custom spinners |\n\n### Renderers\n\n| Function | Description |\n|----------|-------------|\n| `NewTerminalRenderer()` | Default renderer (stderr, with padding) |\n| `NewTerminalRendererWithOutput(w)` | Terminal renderer with custom output |\n| `NewRawRenderer()` | Fully configurable renderer (stdout by default) |\n| `NewRawRendererWithOutput(w)` | Raw renderer with custom output |\n| `NewSilentRenderer()` | No-op renderer (quiet/testing mode) |\n\n### Instance Methods\n\n| Method | Description |\n|--------|-------------|\n| `Update(message)` | Change the spinner message dynamically |\n| `Stop(message?)` | Stop with success symbol (✓) |\n| `Fail(message?)` | Stop with error symbol (✗) |\n| `HandleSignals()` | Enable graceful shutdown on interrupt signals |\n\n### Types\n\n```go\n// Spinner defines an animation sequence\ntype Spinner struct {\n    Frames   []string // Animation frames\n    Interval int      // Milliseconds between frames\n}\n\n// Name identifies a spinner animation style\ntype Name string\n\n// State represents the spinner's current state\ntype State int\n\nconst (\n    StateRunning State = iota // Spinner is active\n    StateStopped              // Completed successfully\n    StateFailed               // Stopped with error\n)\n```\n\n## Advanced Usage\n\n### Custom Registry\n\n```go\nreg := agentspinner.NewMutableRegistry()\nreg.Register(\"custom\", agentspinner.Spinner{\n    Frames:   []string{\"▁\", \"▃\", \"▄\", \"▅\", \"▆\", \"▇\", \"█\"},\n    Interval: 100,\n})\n```\n\n### With Options\n\n```go\nspinner := agentspinner.StartCustom(\"Loading...\", customSpinner,\n    agentspinner.WithRenderer(myRenderer),\n    agentspinner.WithClock(testClock),\n    agentspinner.WithRegistry(customRegistry),\n)\n```\n\n### RawRenderer Configuration\n\nUse `RawRenderer` for full control over output formatting:\n\n```go\nrenderer := agentspinner.NewRawRenderer()\nrenderer.Output = os.Stdout\nrenderer.FormatFrame = \"\\r\\033[K[%s] %s\"   // [frame] message\nrenderer.FormatFinal = \"\\r\\033[K[%s] %s\\n\" // [symbol] message + newline\nrenderer.EnableCursor = true               // Enable cursor hide/show\n\nspinner := agentspinner.StartCustom(\"Loading...\", customSpinner,\n    agentspinner.WithRenderer(renderer),\n)\n```\n\n**RawRenderer Options:**\n\n| Option | Default | Description |\n|--------|---------|-------------|\n| `Output` | `os.Stdout` | Destination writer |\n| `FormatFrame` | `\"\\r\\033[K%s %s\"` | Format for frames (%s = frame, message) |\n| `FormatFinal` | `\"\\r\\033[K%s\\n\"` | Format for final output (%s = symbol, message) |\n| `EnableCursor` | `true` | Hide/show cursor with ANSI codes |\n\n### Renderer Comparison\n\n| Feature | TerminalRenderer | RawRenderer |\n|---------|-----------------|-------------|\n| Default output | stderr | stdout |\n| Auto padding | 2 spaces | none |\n| Custom format | no | yes |\n| Cursor control | yes | optional |\n\n## Testing\n\nThe package is designed for testability. Use `WithRenderer()` and `WithClock()` to inject mocks:\n\n```go\nmockRenderer := \u0026mockRenderer{}\nmockClock := \u0026mockClock{}\nspinner := agentspinner.StartCustom(\"Test\", s,\n    agentspinner.WithRenderer(mockRenderer),\n    agentspinner.WithClock(mockClock),\n)\n```\n\n## Examples\n\nRun the example:\n\n```bash\ncd examples/basic\ngo run main.go\n```\n\n## Architecture\n\nThe package follows a layered architecture:\n\n- `types.go` - Core types and interfaces (Renderer, Clock, Registry, State)\n- `spinner.go` - Runtime with dependency injection support\n- `registry.go` - Thread-safe spinner registry with built-in definitions\n- `renderer.go` - Terminal, raw, and silent renderer implementations\n- `names.go` - Predefined spinner name constants\n- `internal/braille` - Grid operations for Braille patterns\n- `internal/animations` - Animation generators for complex patterns\n\n## Requirements\n\n- Go 1.21 or later\n- Unicode-supporting terminal for best results\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file\n\n## Contributing\n\nContributions welcome! Feel free to add new spinner animations or improve existing ones.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbenoitpetit%2Fagent-spinner","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbenoitpetit%2Fagent-spinner","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbenoitpetit%2Fagent-spinner/lists"}