<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Asciinema on weblog.masukomi.org</title>
    <link>https://weblog.masukomi.org/tags/asciinema/</link>
    <description>Recent content in Asciinema on weblog.masukomi.org</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <copyright>&amp;copy Kay Rhodes (masukomi.org) 2022</copyright>
    <lastBuildDate>Tue, 11 Oct 2022 16:57:00 -0400</lastBuildDate><atom:link href="https://weblog.masukomi.org/tags/asciinema/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Recording &amp; Sharing Terminal Sessions</title>
      <link>https://weblog.masukomi.org/posts/recording_and_sharing_terminal_sessions/</link>
      <pubDate>Tue, 11 Oct 2022 16:57:00 -0400</pubDate>
      
      <guid>https://weblog.masukomi.org/posts/recording_and_sharing_terminal_sessions/</guid>
      <description>&lt;p&gt;This post describes how to make high quality recordings of terminal sessions that can be replayed in the terminal, or shared on the web. I&amp;rsquo;m defining high quality as recordings with zero typos, and relatively controlled timing between commands.&lt;/p&gt;
&lt;p&gt;to see an example of the type of output I&amp;rsquo;m talking about.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why?&lt;/strong&gt;
Videos and gifs take up a lot of disk space, don&amp;rsquo;t age well as display technology improves, and are problematic for folks low vision requirements.&lt;/p&gt;
&lt;p&gt;With the techniques below you can not only share examples of usage on your web pages, but within your tools themselves.&lt;/p&gt;
&lt;h2 id=&#34;goal--s&#34;&gt;Goal(s)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;record terminal session for demonstrating functionality&lt;/li&gt;
&lt;li&gt;replay said recordings locally on a terminal&lt;/li&gt;
&lt;li&gt;share said recordings online&lt;/li&gt;
&lt;li&gt;have that recording look good&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Bonus points:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;editability&lt;/li&gt;
&lt;li&gt;same file for terminal and web sharing&lt;/li&gt;
&lt;li&gt;not having to do get everything perfect &lt;em&gt;again&lt;/em&gt; when you need to record and updated version.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;tools&#34;&gt;Tools&lt;/h2&gt;
&lt;h3 id=&#34;its-a-live--itsalive&#34;&gt;Its a live (itsalive)&lt;/h3&gt;
&lt;p&gt;same core idea as &amp;ldquo;doitlive&amp;rdquo; BUT with some additional functionality like being able to spit out a whole line, and drive interactive things like vim.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://gitlab.com/stavros/itsalive&#34;&gt;source code (GitLab)&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&#34;what-it-does&#34;&gt;What It Does&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;create a file of commands to be executed&lt;/li&gt;
&lt;li&gt;have doitlive execute each of those commands as you type keys&lt;/li&gt;
&lt;li&gt;always perfectly, and quickly typed&lt;/li&gt;
&lt;li&gt;easy to control timing&lt;/li&gt;
&lt;li&gt;allows you to pause and take control
&lt;ul&gt;
&lt;li&gt;thus &lt;em&gt;actually&lt;/em&gt; doing it live in the middle of your script&lt;/li&gt;
&lt;li&gt;can pause with the &lt;code&gt;##@pause&lt;/code&gt; comment which is useful immediately after a script that needs you to interact with it.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;skip forward / back&lt;/li&gt;
&lt;li&gt;allows you to spew out the rest of a line with &lt;code&gt;CTRL+e&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;supports comments!
&lt;ul&gt;
&lt;li&gt;both comments for the viewer (start with #) &amp;amp; comments for the presenter (start with &lt;code&gt;##&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;allows you to have scripted newlines with no input&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Presenter View!!!&lt;/em&gt;
you can see how you&amp;rsquo;re progressing through your script, what came before, and what&amp;rsquo;s coming up next. All in a separate terminal.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;problems&#34;&gt;problems&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;it&amp;rsquo;s &lt;em&gt;actually&lt;/em&gt; executing the commands.&lt;/li&gt;
&lt;li&gt;if you&amp;rsquo;re in the wrong dir, don&amp;rsquo;t have the commands the script needs installed, etc. it&amp;rsquo;ll blow up&lt;/li&gt;
&lt;li&gt;doesn&amp;rsquo;t support comments, so you can&amp;rsquo;t inline commentary for recordings&lt;/li&gt;
&lt;li&gt;not shareable because others would need the same things installed, sometimes in the same places, and what you&amp;rsquo;re doing may be specific to data on your system.&lt;/li&gt;
&lt;li&gt;it doesn&amp;rsquo;t directly handle, or record, interactive stuff
So, for example, you can have it execute a script, but if you have to navigate around the resulting output with arrow keys, it won&amp;rsquo;t record that. However, during playback it won&amp;rsquo;t interfere with you doing that. Until the interactive script exits you are &lt;em&gt;actually&lt;/em&gt; doing it live, not just pretending.&lt;/li&gt;
&lt;li&gt;during playback you&amp;rsquo;re literally just mashing keys. one keystroke per character output to the screen. So, if you&amp;rsquo;re recording the playback of your recording (see below) you&amp;rsquo;ll actually be recording gibberish. However, unless people are viewing the source code to your recording they won&amp;rsquo;t be able to tell.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;notes&#34;&gt;Notes&lt;/h4&gt;
&lt;p&gt;It will start playback in the default shell. If you want to specify a particular shell to playback with set the shell environment variable to the executable for that shell. E.g. &lt;code&gt;SHELL=/opt/homebrew/opt/bash/bin/bash itsalive recording.sh&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;I keep my bash shell nice and minimal for recordings, but my day-to-day stuff is in fish.&lt;/p&gt;
&lt;h3 id=&#34;doitlive&#34;&gt;doitlive&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://doitlive.readthedocs.io/en/stable/&#34;&gt;docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/sloria/doitlive&#34;&gt;source code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;what-it-does&#34;&gt;What it does&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;create a file of commands to be executed&lt;/li&gt;
&lt;li&gt;have doitlive execute each of those commands as you type keys&lt;/li&gt;
&lt;li&gt;always perfectly, and quickly typed&lt;/li&gt;
&lt;li&gt;easy to control timing&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;problems&#34;&gt;Problems&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Same as &lt;code&gt;itsalive&lt;/code&gt;&amp;rsquo;s problems.&lt;/li&gt;
&lt;li&gt;because you&amp;rsquo;re just mashing keys things that you may have pasted in real life are typed in character by character. this makes you look like an &lt;em&gt;amazing&lt;/em&gt; typist, but it does take longer, because unlike &lt;code&gt;itsalive&lt;/code&gt; there&amp;rsquo;s no key combo to finish off the line in one stroke.&lt;/li&gt;
&lt;li&gt;because of its lack of ability to pause &amp;amp; resume playback interactive things can be a little problematic.&lt;/li&gt;
&lt;li&gt;because of its lack of presenter mode it is harder to time things well during recording.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;notes&#34;&gt;Notes&lt;/h4&gt;
&lt;p&gt;It will start playback in the default shell. If you want to specify a particular shell to playback with set the shell environment variable to the executable for that shell. E.g. &lt;code&gt;SHELL=/opt/homebrew/opt/bash/bin/bash doitlive recording.sh&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;I keep my bash shell nice and minimal for recordings, but my day-to-day stuff is in fish.&lt;/p&gt;
&lt;h3 id=&#34;script--unix-command&#34;&gt;script (unix command)&lt;/h3&gt;
&lt;p&gt;old unix command
BSD version (macOS) and Linux version are different.
Linux needs &lt;code&gt;scriptreplay&lt;/code&gt;. macOS version you can just point the same tool at a file and say &lt;code&gt;-p&lt;/code&gt; to &amp;ldquo;play&amp;rdquo; it back.&lt;/p&gt;
&lt;h4 id=&#34;what-it-does&#34;&gt;What it does&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;records what you type and what came out&lt;/li&gt;
&lt;li&gt;records the timings (or not)&lt;/li&gt;
&lt;li&gt;the file could be run on the command line by others for downloadable examples.
&lt;ul&gt;
&lt;li&gt;I believe the format is the same on BSD and Linux&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;problems&#34;&gt;Problems&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;no way to convert these files directly to SVG or GIF or asciinema files (AFAIK)&lt;/li&gt;
&lt;li&gt;it&amp;rsquo;s nigh-impossible to get the timing right, and not show off bad  / slow typing&lt;/li&gt;
&lt;li&gt;editing of content or timing is not really possible
&lt;ul&gt;
&lt;li&gt;technically you can do it with &lt;a href=&#34;https://savannah.gnu.org/projects/teseq&#34;&gt;teseq&lt;/a&gt; which is &amp;hellip; not a joy
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://asciinema.org/a/7445&#34;&gt;Recording of How to edit here (9 min)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;script -&amp;gt; file -&amp;gt; teseq -&amp;gt; new file -&amp;gt; editor -&amp;gt; reseq&lt;/li&gt;
&lt;li&gt;editing with teseq is doable, but the file format is &lt;em&gt;not&lt;/em&gt; very easy to work with.&lt;/li&gt;
&lt;li&gt;one thing it &lt;em&gt;can&lt;/em&gt; do that&amp;rsquo;s useful is edit timings&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;asciinema&#34;&gt;Asciinema&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://asciinema.org&#34;&gt;asciinema.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/asciinema&#34;&gt;GitHub repo&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/asciinema/asciinema-player&#34;&gt;Player (js + css)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/asciinema/asciinema&#34;&gt;terminal session recorder&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can self-host (just needs the &lt;code&gt;.js&lt;/code&gt; and &lt;code&gt;.css&lt;/code&gt; files), or upload your recordings to Asciinema.org. Who knows how long Asciinema.org will continue to exist though.&lt;/p&gt;
&lt;h4 id=&#34;what-it-does&#34;&gt;What it does&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;records what you type and what came out&lt;/li&gt;
&lt;li&gt;records the timings&lt;/li&gt;
&lt;li&gt;stores a format that can be shared via a web page&lt;/li&gt;
&lt;li&gt;stores in a format that can be replayed in a terminal&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;problems&#34;&gt;Problems&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;editing is not possible.
&lt;ul&gt;
&lt;li&gt;content or timing&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;power-up-combo&#34;&gt;Power-up Combo&lt;/h2&gt;
&lt;p&gt;how to make sweet looking recordings without typos or weird pauses.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;figure out exactly what commands you want to execute&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;create a file &lt;code&gt;itsalive&lt;/code&gt; (or &lt;code&gt;doitlive&lt;/code&gt;) with those commands
My recommendation is to use &lt;code&gt;itsalive&lt;/code&gt; though because of the ability to record comments to yourself and the viewer.&lt;/p&gt;
&lt;p&gt;Note that it&amp;rsquo;s not going to be recording timings, or edits or anything like that. It just records the commands you enter, and the file is &lt;em&gt;only&lt;/em&gt; those commands, so it&amp;rsquo;s really simple.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;add &lt;code&gt;asciinema rec &amp;lt;filename&amp;gt;&lt;/code&gt; to the start of it so that it starts &lt;code&gt;asciinema&lt;/code&gt; recording&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;add a  &lt;code&gt;##@pause&lt;/code&gt; comment in your script and then type &lt;code&gt;^d&lt;/code&gt; to exit &lt;code&gt;asciinema&lt;/code&gt; without seeing the word &lt;code&gt;exit&lt;/code&gt; typed out.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;launch &lt;code&gt;itsalive myfile.sh&lt;/code&gt; or &lt;code&gt;SHELL=/path/to/shell itsalive myfile.sh&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;launch the presenter view in a separate terminal &lt;code&gt;itsalive presenter_view&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;click back into your original terminal but keep presenter view visible.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;Watch the presenter view&lt;/em&gt; not the real terminal. As you mash keys it&amp;rsquo;ll show you your progress against the characters in the line. This makes it trivial to hit &lt;code&gt;CTRL+e&lt;/code&gt; at the right point to make it look like you pasted, or to quickly finish off long lines for any other reason.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;mash keys / hit return at appropriate times to move through the steps of the script&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Party.&lt;/p&gt;
&lt;p&gt;Now you&amp;rsquo;ve got a shell script for itsalive and an asciinema file to do with as you want. You probably don&amp;rsquo;t need the doitlive anymore, as it&amp;rsquo;ll likely produce different results when run months, or years, in the future, but maybe it&amp;rsquo;ll be useful to use as a starting point when you need to make a new recording for an updated version of the tool.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;real-world-example&#34;&gt;Real World Example&lt;/h2&gt;
&lt;p&gt;Here are the things I used to make some documentation for &lt;a href=&#34;https://github.com/masukomi/masuconfigs/blob/master/bin/git-scripts/git-link-to-commit&#34;&gt;my git link-to-commit script&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What follows is the bash file that I ran with &lt;code&gt;itsalive&lt;/code&gt;. Things of note:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lines starting with &lt;code&gt;##&lt;/code&gt; are notes to myself because I&amp;rsquo;m watching the &lt;code&gt;presenter_view&lt;/code&gt; as I run it.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;#&lt;/code&gt; lines are comments that will be included in the output.&lt;/li&gt;
&lt;li&gt;The blank lines are significant, in that they actually cause a return to be emitted as if you hit return on the terminal.&lt;/li&gt;
&lt;li&gt;I&amp;rsquo;m kicking off the &lt;code&gt;asciinema&lt;/code&gt; recording from &lt;em&gt;within&lt;/em&gt; the &lt;code&gt;itsalive&lt;/code&gt; script so that the recording does not include me kicking off the &lt;code&gt;itsalive&lt;/code&gt; playback.&lt;/li&gt;
&lt;li&gt;The first &lt;code&gt;##@pause&lt;/code&gt; line is because the first invocation of &lt;code&gt;git link-to-commit&lt;/code&gt; is going to require me to interact with a pull-down, so I need to pause the playback.&lt;/li&gt;
&lt;li&gt;The second one is because I haven&amp;rsquo;t figured out how to make it emit a &lt;code&gt;CTRL+d&lt;/code&gt; to stop &lt;code&gt;asciinema&lt;/code&gt;&amp;rsquo;s recording. So I need to have interactive control over the terminal. I could have had it type &lt;code&gt;exit&lt;/code&gt; but that would have been ugly.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Getting the timing right is still a bit of an art. The &lt;code&gt;presenter_view&lt;/code&gt; really helped, but I needed to re-record a few times to get all the interactions and timings smooth enough. So, I just started the script off by having it delete any prior recordings (if present).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;rm git-link-to-commit.asciinema 2&amp;gt;  /dev/null
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;## MOVE FAST AFTER THIS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;asciinema rec git-link-to-commit.asciinema
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git log -n1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# generate a link&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;## remember to mash then ^e when you get to the hash&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git link-to-commit 2a15b8dea0ae606dedb8335e1c3106342e2d79ed
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;##@pause&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;##  ^r to RESUME playback&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# skip the &amp;#34;choose a repo&amp;#34; step&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;## remember to mash then ^e when you get to the hash&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git link-to-commit -o origin 2a15b8dea0ae606dedb8335e1c3106342e2d79ed
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;## EXIT ASCIINEMA&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;##@pause&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;## HIT ^d&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;## EXIT itsalive&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;exit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;demo&#34;&gt;Demo&lt;/h2&gt;
&lt;p&gt;The final result.&lt;/p&gt;
&lt;div id=&#39;git-link-to-commit.asciinema&#39;&gt;&lt;/div&gt;
&lt;script&gt;
    AsciinemaPlayer.create(
        &#34;/asciinema/git-link-to-commit.asciinema&#34;,
        document.getElementById(&#39;git-link-to-commit.asciinema&#39;),
        {terminalLineHeight: 2}
    );
  
&lt;/script&gt;

</description>
    </item>
    
  </channel>
</rss>
