{"id":20895084,"url":"https://github.com/topheman/snake-pipe-rust","last_synced_at":"2025-07-10T19:05:00.300Z","repository":{"id":220565708,"uuid":"690755775","full_name":"topheman/snake-pipe-rust","owner":"topheman","description":"🦀 A snake game based on stdin/stdout (+tcp and unix sockets) in rust","archived":false,"fork":false,"pushed_at":"2024-05-29T20:39:32.000Z","size":247,"stargazers_count":13,"open_issues_count":8,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-31T07:12:10.273Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","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/topheman.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","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}},"created_at":"2023-09-12T20:09:32.000Z","updated_at":"2025-05-21T22:56:59.000Z","dependencies_parsed_at":"2024-03-12T21:31:16.728Z","dependency_job_id":"028742bb-9325-4390-a243-376424ba8c88","html_url":"https://github.com/topheman/snake-pipe-rust","commit_stats":null,"previous_names":["topheman/snake-pipe-rust"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/topheman/snake-pipe-rust","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/topheman%2Fsnake-pipe-rust","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/topheman%2Fsnake-pipe-rust/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/topheman%2Fsnake-pipe-rust/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/topheman%2Fsnake-pipe-rust/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/topheman","download_url":"https://codeload.github.com/topheman/snake-pipe-rust/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/topheman%2Fsnake-pipe-rust/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264638287,"owners_count":23642139,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":"2024-11-18T10:24:53.899Z","updated_at":"2025-07-10T19:05:00.281Z","avatar_url":"https://github.com/topheman.png","language":"Rust","readme":"# snake-pipe-rust\n\n[![crates.io](https://img.shields.io/crates/v/snakepipe.svg)](https://crates.io/crates/snakepipe) [![Docs](https://docs.rs/snakepipe/badge.svg)](https://docs.rs/snakepipe/latest/snakepipe/) [![Build](https://github.com/topheman/snake-pipe-rust/actions/workflows/rust.yml/badge.svg?label=build)](https://github.com/topheman/snake-pipe-rust/actions/workflows/rust.yml)\n\nNot just yet another snake game in the terminal 😉.\n\nhttps://github.com/topheman/snake-pipe-rust/assets/985982/76161595-1c3a-4252-9cbd-25e144bf185c\n\nThis one follows the [unix philosophy](https://en.wikipedia.org/wiki/Unix_philosophy) as:\n\n- `snakepipe gamestate` accepts user inputs, calculates the state of the game and writes it to `stdout`\n- `snakepipe render` reads the state of the game from `stdin` and renders it on the terminal\n- `snakepipe throttle` reads a pre-recorded game from `stdin` and writes to `stdout` each tick so that `snakepipe render` can pick it up\n- `snakepipe render-browser` spawns a server and sends `stdin` via server-sent events to a JavaScript renderer in your browser\n- `snakepipe stream-sse` connects to the server spawned by `render-browser` and streams server-sent events back to the terminal\n- `snakepipe socket-play` accepts gamestate from stdin and pushes it to a unix socket\n- `snakepipe socket-watch` reads gamestate from a unix socket\n- `snakepipe tcp-play` accepts gamestate from stdin and pushes it to a tcp socket\n- `snakepipe tcp-watch` reads gamestate from a tcp socket\n- `snakepipe pipeline \u003ccommand\u003e` prints out the most common pipelines (combinations of commands), so that you could directly `pbcopy`/paste them\n\nThat way:\n\n- you could write your own version of the `gamestate` or `render` command in any programming language and make it work with mine\n- it's a great exercise to handle stream serialization/deserialization in rust\n\n## Motivation\n\nI've already done [a few rust projects](http://labs.topheman.com) (with WebAssembly or [bevy](https://github.com/topheman/bevy-rust-wasm-experiments)), however, I wanted something that needs to deal directly with:\n\n- I/O\n- parsing\n- parallelism\n- async programming\n- handling piping/stdin/stdout/signaling ...\n- inter-process communication\n\n## Install\n\nAny OS - if you have Rust \u003e= 1.75.0  - [How to install Rust (if you don't have it yet)](https://www.rust-lang.org/tools/install)\n\n```sh\ncargo install snakepipe\n```\n\nOn MacOS, with Homebrew (ships with its own [shell completions](#shell-completions) for zsh, bash and fish)\n\n```sh\nbrew install topheman/tap/snakepipe\n```\n\nOther OS: see [releases](https://github.com/topheman/snake-pipe-rust/releases).\n\n## Usage\n\n### Piping\n\n#### 🎮 Play in terminal\n\n```sh\n# basic usage\nsnakepipe gamestate|snakepipe render\n\n# change the defaults\nsnakepipe gamestate --frame-duration 80 --width 70 --height 20 --snakepipe-length 15|snakepipe render\n\n# call help on any of the commands\nsnakepipe --help\n```\n\n#### 📼 You can even record and replay using basic piping\n\n```sh\n# record a game into a file using the builtin `tee` command utility\nsnakepipe gamestate|tee /tmp/snakepipe-output|snakepipe render\n\n# replay the game you recorded\ncat /tmp/snakepipe-output|snakepipe throttle|snakepipe render\n```\n\n#### 🖥 You can mirror your playing terminal into a server you can open in a browser\n\n```sh\nsnakepipe gamestate|snakepipe render-browser|snakepipe render\n```\n\nThen open [http://localhost:8080](http://localhost:8080). You'll be able to switch between renderers in your browser as you are playing in your terminal (thanks to server-sent events).\n\n#### 🖼 You can mirror your playing terminal into another one, through http\n\nOpen two terminals:\n\n```sh\n# main terminal:\n# - accepts user inputs\n# - spawns an http server that streams stdin to server-sent events\n# - renders the game to the terminal so you can play\nsnakepipe gamestate|snakepipe render-browser|snakepipe render\n```\n\n```sh\n# mirroring terminal (not necessary the same device, only need to be on the same network):\n# - connects to the http server and streams server-sent events to sdout\n# - render the gamestate retrieved from the server\nsnakepipe stream-sse|snakepipe render\n```\n\nYou could share your game accross your LAN!\n\n### IPC (Inter-process communication)\n\n#### TCP\n\nOpen two terminals. `snakepipe tcp-play` will expose a process that accepts tcp connections (on port 8050 by default). You can connect to it via [netcat](https://en.wikipedia.org/wiki/Netcat) (the `nc` command), that will pipe the tcp stream output to stdout.\n\n```sh\n# main terminal\nsnakepipe gamestate|snakepipe tcp-play|snakepipe render\n```\n\n```sh\n# mirroring terminal\nnc localhost 8050|snakepipe render # with netcat\nsnakepipe tcp-watch|snakepipe render # or with snakepipe itself\n```\n\n#### Unix domain sockets\n\nOpen two terminals. `snakepipe socket-play` will expose a [unix domain socket](https://en.wikipedia.org/wiki/Unix_domain_socket) (by default on `/tmp/snakepipe.sock`). You can connect to it via [netcat](https://en.wikipedia.org/wiki/Netcat) (the `nc` command), that will pipe the socket stream to stdout.\n\n```sh\n# main terminal\nsnakepipe gamestate|snakepipe socket-play|snakepipe render\n```\n\n```sh\n# mirroring terminal\nnc -U /tmp/snakepipe.sock|snakepipe render # with netcat\nsnakepipe socket-watch|snakepipe render # or with snakepipe itself\n```\n\n### Others\n\n#### 📺 You can also mirror your playing terminal into another one\n\nYou should prefer using IPC.\n\nOpen two terminals that will communicate via a file that will be `tail`ed and piped to `snakepipe render`\n\n```sh\n# mirroring terminal\ncat /dev/null \u003e /tmp/snakepipe-output \u0026\u0026 tail -f /tmp/snakepipe-output|snakepipe render\n```\n\n```sh\n# main terminal\nsnakepipe gamestate|tee /tmp/snakepipe-output|snakepipe render\n```\n\n### 😉 And maybe you'll find other ways?...\n\n## Shell completions\n\nIf you install `snakepipe` with Homebrew, it ships with its own completions for zsh, bash and fish and they will be installed without you having to do anything.\n\nIf you installed `snakepipe` manually, you can generate the completions files with the `snakepipe generate-completions` command.\n\n## Manual of commands\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ccode\u003esnakepipe --help\u003c/code\u003e\u003c/summary\u003e\n  \u003cpre\u003eA snake game based on stdin/stdout following unix philosophy\n\nUsage: snakepipe \\\u003cCOMMAND\u003e\n\nCommands:\n\n  gamestate       Accepts user inputs (arrow keys to control the snake) and outputs the state of the game to stdout\n  render          Reads gamestate from stdin and renders the game on your terminal\n  throttle        Reads stdin line by line and outputs each line on stdout each `frame_duration` ms (usefull for replaying a file)\n  render-browser  Let's you render the game in your browser at http://localhost:8080 by spawning a server and sending stdin via server-sent events to a JavaScript renderer\n  stream-sse      Connects to the server spawned by `render-browser` and streams server-sent events back to the terminal\n  help            Print this message or the help of the given subcommand(s)\n\nOptions:\n  -h, --help     Print help\n  -V, --version  Print version\n  \u003c/pre\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ccode\u003esnakepipe gamestate --help\u003c/code\u003e\u003c/summary\u003e\n  \u003cpre\u003eAccepts user inputs (arrow keys to control the snake) and outputs the state of the game to stdout\n\nUsage: snakepipe gamestate [OPTIONS]\n\nOptions:\n      --frame-duration \\\u003cFRAME_DURATION\u003e  in ms [default: 120]\n      --width \\\u003cWIDTH\u003e                    default 25\n      --height \\\u003cHEIGHT\u003e                  default 25\n      --snake-length \\\u003cSNAKE_LENGTH\u003e      [default: 2]\n      --fit-terminal\n  \u003c/pre\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ccode\u003esnakepipe render --help\u003c/code\u003e\u003c/summary\u003e\n  \u003cpre\u003e\nReads gamestate from stdin and renders the game on your terminal\n\nUsage: snakepipe render\n  \u003c/pre\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ccode\u003esnakepipe throttle --help\u003c/code\u003e\u003c/summary\u003e\n  \u003cpre\u003e\nReads stdin line by line and outputs each line on stdout each `frame_duration` ms (usefull for replaying a file)\n\nUsage: snakepipe throttle [OPTIONS]\n\nOptions:\n      --frame-duration \\\u003cFRAME_DURATION\u003e  in ms [default: 120]\n      --loop-infinite\n  \u003c/pre\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ccode\u003esnakepipe render-browser --help\u003c/code\u003e\u003c/summary\u003e\n  \u003cpre\u003e\nLet's you render the game in your browser at http://localhost:8080 by spawning a server and sending stdin via server-sent events to a JavaScript renderer\n\nUsage: snakepipe render-browser [OPTIONS]\n\nOptions:\n      --port \u003cPORT\u003e  [default: 8080]\n  \u003c/pre\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ccode\u003esnakepipe stream-sse --help\u003c/code\u003e\u003c/summary\u003e\n  \u003cpre\u003e\nConnects to the server spawned by `render-browser` and streams server-sent events back to the terminal\n\nUsage: snakepipe stream-sse [OPTIONS]\n\nOptions:\n      --address \\\u003cADDRESS\u003e  [default: http://localhost:8080]\n  \u003c/pre\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ccode\u003esnakepipe socket-play --help\u003c/code\u003e\u003c/summary\u003e\n  \u003cpre\u003e\nAccepts gamestate from stdin and pushes it to a unix socket\n\nUsage: snakepipe socket-play [OPTIONS]\n\nOptions:\n      --path \\\u003cPATH\u003e  Unix socket file path [default: /tmp/snakepipe.sock]\n  \u003c/pre\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ccode\u003esnakepipe socket-watch --help\u003c/code\u003e\u003c/summary\u003e\n  \u003cpre\u003e\nReads gamestate from a unix socket\n\nUsage: snakepipe socket-watch [OPTIONS]\n\nOptions:\n      --path \\\u003cPATH\u003e  Unix socket file path [default: /tmp/snakepipe.sock]\n  \u003c/pre\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ccode\u003esnakepipe tcp-play --help\u003c/code\u003e\u003c/summary\u003e\n  \u003cpre\u003e\nAccepts gamestate from stdin and pushes it to a tcp socket\n\nUsage: snakepipe tcp-play [OPTIONS]\n\nOptions:\n      --port \\\u003cPORT\u003e  Port number [default: 8050]\n      --host \\\u003cHOST\u003e  Tcp host [default: 127.0.0.1]\n  \u003c/pre\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ccode\u003esnakepipe tcp-watch --help\u003c/code\u003e\u003c/summary\u003e\n  \u003cpre\u003e\nReads gamestate from a tcp socket\n\nUsage: snakepipe tcp-watch [OPTIONS]\n\nOptions:\n      --port \\\u003cPORT\u003e  Port number [default: 8050]\n      --host \\\u003cHOST\u003e  Tcp host [default: 127.0.0.1]\n  \u003c/pre\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ccode\u003esnakepipe pipeline --help\u003c/code\u003e\u003c/summary\u003e\n  \u003cpre\u003e\nPrints out some common pipelines, so that you can copy/paste them to execute (you can pipe to `pbcopy`)\n\nUsage: snakepipe pipeline [OPTIONS] [COMMAND]\n\nCommands:\n  play        Play in the terminal\n  record      Record a party in the terminal\n  replay      Replay a party you recorded in the terminal\n  file-play   Play and share a party via a shared file in realtime\n  file-watch  Render the party you are sharing through a file in realtime\n  http-play   Play and share a party through an http server\n  http-watch  Render the party you shared through the http server, in the terminal\n  \u003c/pre\u003e\n\u003c/details\u003e\n\n## Using as a library\n\n```sh\ncargo add snakepipe # add it to your project\n```\n\nThis crate is a cli, but it also exports a lib from where you can import a few utilities, such as `snakepipe::stream::parse_gamestate` - [direct link to docs.rs](https://docs.rs/snakepipe/latest/snakepipe/stream/fn.parse_gamestate.html):\n\n```rust\nuse snakepipe::stream::{parse_gamestate, Game};\n\nfn main() -\u003e () {\n    match parse_gamestate() {\n        Ok(stream) =\u003e {\n            println!(\n                \"Frame duration {}, Snake length {}, Level {}x{}\",\n                stream.options.frame_duration,\n                stream.options.snake_length,\n                stream.options.size.width,\n                stream.options.size.height\n            );\n            for parsed_line in stream.lines {\n                do_something(parsed_line);\n            }\n        }\n        Err(e) =\u003e {\n            eprintln!(\"Error occurred while parsing stdin: \\\"{}\\\"\", e);\n        }\n    }\n}\n\nfn do_something(parsed_line: Game) {\n    println!(\"Snake head position {:?}\", parsed_line.snake.head)\n}\n```\n\n## Contributing\n\nYou can:\n\n- Make an implementation of the actual `snakepipe render` command for the terminal in an other language than rust\n- Make your own JavaScript renderer for the `snakepipe render-browser` command and ask for a PR to integrate it to the project\n\nAn Experimental/Partial nodejs implementation of this crate available at [topheman/snake-pipe-node](https://github.com/topheman/snake-pipe-node).\n\nMore infos in [CONTRIBUTING.md](./CONTRIBUTING.md).\n","funding_links":[],"categories":["Applications"],"sub_categories":["Games"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftopheman%2Fsnake-pipe-rust","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftopheman%2Fsnake-pipe-rust","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftopheman%2Fsnake-pipe-rust/lists"}