{"id":25695163,"url":"https://github.com/yertto/asciinema-rec_script","last_synced_at":"2025-08-30T09:36:01.338Z","repository":{"id":40276290,"uuid":"418056826","full_name":"yertto/asciinema-rec_script","owner":"yertto","description":"Record 💭 comments and ❯ commands from from shell scripts in addition to their output.","archived":false,"fork":false,"pushed_at":"2023-04-19T08:49:31.000Z","size":2649,"stargazers_count":29,"open_issues_count":4,"forks_count":4,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-15T10:06:52.194Z","etag":null,"topics":["asciicast","asciinema","recorder","recording","shell-script","terminal","terminal-recording"],"latest_commit_sha":null,"homepage":"https://github.com/asciinema/asciinema#rec-filename","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yertto.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2021-10-17T07:43:24.000Z","updated_at":"2025-02-20T22:04:09.000Z","dependencies_parsed_at":"2024-01-16T20:29:57.295Z","dependency_job_id":"3a5a890a-d90f-4569-a7d2-2b2198ba17f6","html_url":"https://github.com/yertto/asciinema-rec_script","commit_stats":null,"previous_names":["yertto/asciinema-rec_script","zechris/asciinema-rec_script"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/yertto/asciinema-rec_script","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yertto%2Fasciinema-rec_script","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yertto%2Fasciinema-rec_script/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yertto%2Fasciinema-rec_script/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yertto%2Fasciinema-rec_script/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yertto","download_url":"https://codeload.github.com/yertto/asciinema-rec_script/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yertto%2Fasciinema-rec_script/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272833295,"owners_count":25000870,"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","status":"online","status_checked_at":"2025-08-30T02:00:09.474Z","response_time":77,"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":["asciicast","asciinema","recorder","recording","shell-script","terminal","terminal-recording"],"created_at":"2025-02-25T00:02:27.173Z","updated_at":"2025-08-30T09:36:01.310Z","avatar_url":"https://github.com/yertto.png","language":"Shell","funding_links":[],"categories":["Shell"],"sub_categories":[],"readme":"# asciinema-rec_script\n[![Conventional Commits][conventional-commits-image]][conventional-commits-url]\n\nRecord 💭 comments and ❯ commands from from shell scripts in addition to their output.\n\nThis is done by building a version of the original script that surfaces all the comments and commands by *also* echoing them to the screen.\n\nThen passing that augmented script to asciinema's [rec --command](https://github.com/asciinema/asciinema#rec-filename) command.\n\n\n## Motivation\n\nThe [asciinema](https://asciinema.org) tool is an awesome terminal session recorder.\n\nAnd it has a [rec [filename]](https://github.com/asciinema/asciinema#rec-filename) command with a `-c --command=\u003ccommand\u003e` option.\n\nThis specifies a `command` to record (other than the default of `$SHELL`)\n\nSo given an (executable) script [screencasts/demo-date_maths](https://github.com/zechris/asciinema-rec_script/blob/main/screencasts/demo-date_maths):\n```bash\n#!/usr/bin/env bash\n## Date maths\n\n# The `date` command can be used to retrieve the:\n#  * *day of the week* using the `%l` option\nday_of_the_week=$(date +%l)\n\n#  * *hour of the day* using the `%u` option\nhour=$(date +%u)\n\n\n# Now, can you guess what we're going to do with those two numbers?\n# 🤔...\nsleep 3\n\n# We're going to add them together!\necho $((day_of_the_week + hour))\n```\n\nWe can use asciinema's `rec` to make a recording:\n```\nasciinema rec --command screencasts/demo-date_maths\n```\n\n\nHowever that recording is going to lose a bunch of context from the script and end up looking something like this:\n\u003cimg width=\"808\" alt=\"Screen Shot 2021-10-17 at 19 49 14\" src=\"https://user-images.githubusercontent.com/49626717/137619503-05ec8492-f2df-4bc3-a410-ad3300223b8f.png\"\u003e\n\nIf, however we instead used this command:\n```\nasciinema-rec_script screencasts/demo-date_maths\n```\n\nWithout *any* effort we can end up with a recording like this:\n[![demo-date_maths.cast](screencasts/demo-date_maths.gif)](https://asciinema.org/a/gOhB2rxL8LTl3PL6kpC4YPCID)\n\n\n## Getting Started\n### Installation:\nPlace `asciinema-rec_script` somewhere in your $PATH.\n\n\n#### Requirements:\n * [asciinema](https://asciinema.org) ([installation](https://github.com/asciinema/asciinema#installation))\n * bash\n * (optional) [bat](https://github.com/sharkdp/bat) ([installation](https://github.com/sharkdp/bat#installation))\n   * _A `cat` clone to provide syntax highlighting_\n\n\n### Example Usages:\n * `asciinema-rec_script ./screencasts/demo-date_maths`\n   * _When called with no extra arguments, the tool will pass `asciinema rec` a filename of `./screencasts/demo-date_maths.cast` to place the recording in_\n   * _(Nb. the filename is derived from the source script by attaching a `.cast` extension.)_\n * `./screencasts/demo-date_maths.asc`\n   * _Will take advantage of the shebang line [#!/usr/bin/env asciinema-rec_script](https://github.com/zechris/asciinema-rec_script/blob/main/screencasts/demo-bash_functions.asc#L1) in the `.asc` script_\n   * _(ie. allowing the input script to be run as its own command, without having to pass it as an argument to `asciinema-rec_script`)_\n * `./screencasts/demo-date_maths.asc --`\n   * _When called with `--` the tool will allow `asciinema rec` to receive no additional arguments_\n   * _(ie. allowing it to maintain its default behaviour of uploading screencasts to https://asciinema.org)_\n * `./screencasts/demo-date_maths.asc --help`\n   * _Will also pass any additional arguments it gets to `asciinema rec`_\n   * _(so eg. `--help` will show all the [asciinema rec [options]](https://github.com/asciinema/asciinema#rec-filename))_\n * `SLEEP=0 ./screencasts/demo-bash_functions.asc`\n   * _(env vars can be passed into the script in the regular way)_\n   * _(to eg set `PROMPT=\"$ \"`, `PROMPT_PAUSE=5`)_\n * `bash ./screencasts/demo-date_maths.asc`\n   * _Nb. It should also be possibe to execute the `.asc` script in your $SHELL as a regular bash script_\n   * _(Maintaining this compatability means that the `.asc` file won't require any special commands that a regular shell script wouldn't already have in it.  Which hopefully results in regular shell scripts resulting in half-decent looking recordings.)_\n\n(Nb. the `.asc` extension (_\"ASCiinema\"_) is not strictly necessary, but gives some uniformity.)\n\n\n### How it works\n`asciinema-rec_script` (written in bash) reads from the file passed to it one line at a time and will detect:\n * ❯ _lines of code_ (syntax highlighting them as bash code)\n * 💭 _comments_ (syntax highlighting them as markdown)\n * _blank lines_ (preserving whitespace)\n * 💬 and some other _special lines_\n\nIt uses meta-programming to build an augmented version of itself from each of these lines storing them in a temporary `augmented_script` file.\n\nAnd finally it passes that file (and any other arguments specified on the command line) to `asciinema run --command \u003caugmented_script\u003e` for it to make a recording.\n\nNb. although the `.asc` scripts are used to produced asciinema recordings its expected that these files can also be run in bash/zsh\n\neg.\n```\n❯ source screencasts/demo-bash_functions.asc\na='a 0', b='b 0', c=''\n-\u003e f1(a='a 0', b='b 0', c='')\n-\u003e f1(a='a 0', b='b 0', c='')\nBEFORE: a='a 0', b='b 0', c=''\n-\u003e f1(a='a 1', b='b 1', c='c 1')\nAFTER : a='a 1', b='b 1', c='c 1'\nBEFORE: a='a 0', b='b 0', c=''\n-\u003e f1(a='a 1', b='b 1', c='c 1')\nAFTER : a='a 0', b='b 0', c=''\n-\u003e f1(a='a 1', b='b 2', c='c 2')\n-\u003e f1(a='a 1', b='b 0', c='c 2')\nSun Oct 17 20:56:56 AEDT 2021\n-\u003e f1(a='a 1', b='b 0', c='Sun Oct 17 20:56:56 AEDT 2021')\nBEFORE: a='a 0', b='b 0', c=''\n-\u003e f1(a='a 1', b='b 3', c='c 3')\nAFTER : a='a 0', b='b 0', c=''\n-\u003e f2(a='a 4', b='b 4', c='Sun Oct 17 20:56:56 AEDT 2021')\n-\u003e f2(a='a 4', b='b 4', c='Sun Oct 17 20:56:56 AEDT 2021')\n-\u003e f2(a='a 4', b='b 4', c='c 4')\n```\n\n#### Limitations\nAs the `.asc` is read in one line at a time, making it difficult (if not impossible) to execute multi-line commands in these shell scripts.\n\nThe two workarounds I could think of were:\n1. making every multi-line command fit on one line\n  * So this:\n    ```bash\n    f1() {\n      echo \"-\u003e f1(a='$a', b='$b', c='$c')\"\n    }\n    ```\n  * would have to be manually edited in the `.asc` file to this:\n    ```bash\n    f1() { echo \"-\u003e f1(a='$a', b='$b', c='$c')\"; }\n    ```\n2. inline the multi-line code from a `source` command:\n  * So something like this:\n    ```bash\n    source \"${script%.asc}/f1.1\"\n    ```\n  * could be used (eg. [here](https://github.com/zechris/asciinema-rec_script/blob/4d7b6e6768a1a9d7af97af72afeaf415be0fc647/screencasts/demo-bash_functions.asc#L7)) to source [this file](https://github.com/zechris/asciinema-rec_script/blob/4d7b6e6768a1a9d7af97af72afeaf415be0fc647/screencasts/demo-bash_functions/f1.1#L1-L3) but be seemlessly displayed in the [recording](https://asciinema.org/a/2Vvvu1UoiUI1GU6kBYDCRx9Vp?t=2) as:\n    ```bash\n    f1() {\n      echo \"-\u003e f1(a='$a', b='$b', c='$c')\"\n    }\n    ```\n\n## Similar \u0026 Related Projects\n\n* https://github.com/garbas/asciinema-scenario\n\n## Also included\n### [asciinema-gh](https://github.com/zechris/asciinema-rec_script/blob/main/bin/asciinema-gh)\nThis tool provides a command line playack menu of screencasts which it pulls from github repos.\n\nIt works with both public \u0026 private github repos.\n\n(Nb. The recordings that appear in the menu don't necessarily have to be made using `asciinema-rec_script`,\nbut the menu will filter out all the `.asc` files from that directory.)\n\n#### Requirements:\n * [asciinema](https://asciinema.org)\n * [gh](https://github.com/cli/cli)\n * [jq](https://stedolan.github.io/jq)\n\n\n#### Example Usages:\n * `asciinema-gh zechris/asciinema-rec_script`\n   * _search for .cast files in https://github.com/zechris/asciinema-rec_script/tree/master/screencasts_\n * `REF=v0.9.0 asciinema-gh zechris/asciinema-rec_script` \n   * _(which can be used with a github `REF`s like release tags eg. [v0.9.0](https://github.com/zechris/asciinema-rec_script/releases/tag/v0.9.0))_\n * `REF=first_pr asciinema-gh zechris/asciinema-rec_script` \n   * _(or branch names eg. [first_pr](https://github.com/zechris/asciinema-rec_script/tree/first_pr))_\n * `asciinema-gh spectreconsole/spectre.console docs/input/assets/casts`\n   * _(NB. a path can also be specified if the screencasts aren't found in the default `./screencasts`)_\n * `echo 26 | screencast_dir=docs/input/assets/casts asciinema-gh spectreconsole/spectre.console`\n   * _(to pre-select number `26` from the menu)_\n\n[![asciicast](https://asciinema.org/a/uiqC0yZrCP9UPGqWaX5Wnf7wF.svg)](https://asciinema.org/a/uiqC0yZrCP9UPGqWaX5Wnf7wF)\n\n\n\n[conventional-commits-image]: https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg\n[conventional-commits-url]: https://conventionalcommits.org\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyertto%2Fasciinema-rec_script","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyertto%2Fasciinema-rec_script","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyertto%2Fasciinema-rec_script/lists"}